kotlin + 列表拖拽重新排序、滑动进行删除

kotlinTouchHelperDemo

其实在一个月前就想写个kotlin的Demo,想在kotlin成为Android的主流开发语言之前学习学习它.
但是中间一直没有时间,正好这几天Google I/O大会,Kotlin都上热搜了,我利用下班后的时间将写的kotlin例子来和大家分享下,让大家感受感受这门神奇的语言.

kotlin

来,先贴上官方对于这门语言的介绍以及官方为何放弃Java而最终选择kotlin

  1. Kotlin 介绍
  • Kotlin是一个基于JVM 实现的静态语言. Kotlin是IntelliJ公司创造并在持续维护这门语言.
  1. 优点
  • 帮你减少实现同一个功能的代码量.
  • 让你的代码更容易阅读,同时易于理解.
  • 移除了你可能会犯错误的功能.
  • 基于 JVM 和 Javascript,你可以在很多地方运行.
  • Kotlin 和 Java 可以相互调用 .
  1. 为何放弃Java
  • 兼容性问题 (Java 7 只支持 API 19 及以上,以及AndroidStudio对于Java 8的新特性支持迟迟没有完善)
  • Java 存在问题
    a. 空引用 : 不论你费多大的功夫,你都无法避免它.因为 Java 的类型系统就是不安全的 .
    b. 原始类型 : 我们在开发的时候总是会为了保持兼容性而卡在范型原始类型的问题上,我们都知道要努力避免 raw type 的警告,但是它们毕竟是在语言层面上的存在,这必定会造成误解和不安全因素.
    c. 协变数组 : 你可以创建一个 string 类型的数组和一个 object 型的数组,然后把 string 数组分配给 object 数组.这样的代码可以通过编译,但是一旦你尝试在运行时分配一个数给那个数组的时候,他就会在运行时抛出异常.
    d. Java 8 存在高阶方法 : 但是他们是通过 SAM 类型 实现的.SAM 是一个单个抽象方法,每个函数类型都需要一个对应的接口.如果你想要创建一个并不存在的 lambda 的时候或者不存着对应的函数类型的时候,
    你要自己去创建函数类型作为接口.
    e. 泛型中的通配符 : 诡异的泛型总是难以操作,难以阅读,书写,以及理解. 对编译器而言,异常检查也变得很困难.
  1. 为何选择Kotlin
  • 对于上面Java存在的问题 很好的解决了.
  • 添加新特性
    a. Lambda 表达式 (Java8 才有)
    b. 数据类
    c. 函数字面量和内联函数
    d. 函数扩展
    e. 空安全
    f. 智能转换
    g. 字符串模板
    h. 类委托
    i. 类型推断
    j. 声明点变量
    k. 区间表达式
    ...

简单介绍完了kotlin,说下小编对于这门新语言的感受吧 -- 嗨到不行!

kotlin 在Android Studio 中的使用。

在最新版的AS3.0中将可以直接使用Kotlin作为开发语言,但是3.0之前版本则需要通过安装kotlin的插件来进行配置并使用kotlin。

查找插件.png
配置环境.png

下面我将通过一个功能实现,来带大家看下kotlin的代码.

列表拖拽重新排序 + 滑动删除实现原理

简述原理:主要通过使用recyclerview 提供的ItemTouchHelper 来实现效果。

  1. app/build.gradle 配置 (此处我用的recyclerview版本是25.3.1,可以选择其他版本)

    compile 'com.android.support:recyclerview-v7:25.3.1'
    
  2. RecyclerView.Adapter中使用ItemTouchHelper详解:

    • ItemTouchHelper.Callback 来实现用户手势的控制以及数据的操作

      1. getMovementFlags : 通过调用 getMovementFlags,告诉RecyclerView可以实现的手势类型
      2. onMove : 拖拽时回调的方法,返回值决定是否可以长按拖拽
      3. onSwiped : 左右滑动到满足删除时的回调方法,可以此处执行删除数据
      4. isLongPressDragEnabled : 是否可以长摁拖拽
      5. isItemViewSwipeEnabled : 是否可以滑动删除
      6. onSelectedChanged :状态改变回调方法,可以在此处用于更换图片背景。
      7. clearView :拖动完成回调方法,此处用于更换图片背景



      上面只是简单的对于函数的介绍,详细的操作在下面的代码中可以了解到。

      //kotlin 如果内部类需要访问外部类数据 则要声明为inner
        inner class ItemDragHelperCallback : ItemTouchHelper.Callback() {
            /**
             * 获取可以拖动的方向标志
             * */
            override fun getMovementFlags(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?): Int {
                //此处返回可以拖动的方向值
                var swipe = 0
                var move = 0
                //此处为 假设recyclerview 不为空
                recyclerView?.let {
                    if (recyclerView.layoutManager is GridLayoutManager) {
                        //如果是网格型 则可以左右上下都可以拖动
                        move = ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
                    } else if (recyclerView.layoutManager is LinearLayoutManager) {
                        //支持上下拖动
                        move = ItemTouchHelper.UP or ItemTouchHelper.DOWN
                        //左右滑动删除
                        swipe = ItemTouchHelper.START or ItemTouchHelper.END
                    }
                }
                return ItemTouchHelper.Callback.makeMovementFlags(move, swipe)
            }
      
            override fun onMove(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?, target: RecyclerView.ViewHolder?): Boolean {
                //此处的返回值 决定是否可以拖动
                if (viewHolder != null && target != null) {
                    //此处不让标题来进行拖动效果 也就是拖动时 标题不会动
                    if (viewHolder.itemViewType == TYPE_TITLE || target.itemViewType == TYPE_TITLE) {
                        return false
                    }
      
                    val fromPos = viewHolder.adapterPosition
                    val toPos = target.adapterPosition
                    //此处为mData不为空时
                    mData?.let {
                        val from = mData[fromPos]
                        mData.removeAt(fromPos)
                        mData.add(toPos, from)
                        //执行交换动画
                        notifyItemMoved(fromPos, toPos)
                        return true
                    }
                }
                //默认不让拖动
                return false
            }
      
            override fun onSwiped(viewHolder: RecyclerView.ViewHolder?, direction: Int) {
                //用于执行滑动删除
            }
      
            //不重写默认是返回true的 如果返回false的话 需要使用ItemTouchHelper的实例方法
            //使用 startDrag 来执行拖拽
            //使用 startSwipe 来执行滑动删除
            override fun isLongPressDragEnabled(): Boolean {
                return true
            }
      
            //是否支持滑动功能
            override fun isItemViewSwipeEnabled(): Boolean {
                return true
            }
      
            /**
             * 此处用于状态变化时 更换图片状态
             * */
            override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
                super.onSelectedChanged(viewHolder, actionState)
                if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
                    //显示遮罩
                    viewHolder?.let {
                        if (viewHolder is ItemViewHolder) {
                            viewHolder.mShadow!!.visibility = View.VISIBLE
                        }
                    }
                }
            }
      
            /**
             * 此处当拖拽完成
             * */
            override fun clearView(recyclerView: RecyclerView?, viewHolder: RecyclerView.ViewHolder?) {
                super.clearView(recyclerView, viewHolder)
                //隐藏遮罩
                viewHolder?.let {
                    if (viewHolder is ItemViewHolder) {
                        viewHolder.mShadow!!.visibility = View.GONE
                    }
                }
            }
      
        }
      
    • ItemTouchHelper 当需要自定义条件才执行拖拽或者滑动删除,则可以使用startDrag、startSwipe来主动调用开始拖拽与滑动,并isLongPressDragEnabled与 isItemViewSwipeEnabled返回false。

    //开始执行滑动
    ItemTouchHelper.startSwipe(RecyclerView.ViewHolder)
    //开始执行拖拽
    ItemTouchHelper.startDrag(RecyclerView.ViewHolder)
    
    • ItemTouchHelper.attachToRecyclerView 当一切设置好了,则调用此方法设置到RecyclerView中。
     //将recyclerView依附到触摸辅助类
     open fun attachiToRecyclerView(recyclerView: RecyclerView) {
         if (mItemTouchHelper != null && recyclerView != null) {
             mItemTouchHelper.attachToRecyclerView(recyclerView)
         }
     }
    

效果图

拖拽重新排序.gif
滑动删除.gif

给各位客官奉上Github地址:
https://github.com/Nichooool/kotlinTouchHelperDemo
↓↓↓↓↓↓↓↓如果觉得可以的话,请点击下面的喜欢。或者打赏哦,我不会骄傲的。↓↓↓↓↓↓↓↓

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,547评论 4 374
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,787评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,175评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,752评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,169评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,056评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,195评论 2 321
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,980评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,724评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,872评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,344评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,667评论 3 264
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,379评论 3 245
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,202评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,992评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,189评论 2 286
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,987评论 2 279

推荐阅读更多精彩内容