携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
需求
某一天,一个同事向我吐槽:艾玛你这App啥玩意,太难用了!
我:???
同事:就比如说你这个列表,固定按创建顺序来排序。
我:这不是很正常吗?有啥问题?
同事:那要是我创建顺序搞错了,就得重新删掉再按顺序重新创建一遍,太不方便了!
我:这是你操作问题,咋还赖上我的App咧?
同事:我不管!就是难用!
虽然最后也没真的去修改,但作为未雨绸缪的Coder,我不禁思考起来,排序能不能优化呢?首先想到的是弄个按钮做切换不同的排序策略,比如创建时间升降序、文字升降序等。但还是觉得不足够灵活。最后还是觉得让用户自定义排序,你爱咋排咋排。
RecycleView拖动排序
官方其实早已明了我们的需求了,推出了ItemTouchHelper帮助类来让开发者更容易地完成拖动操作(drag)以及滑动操作(swipe)。
实现拖动排序跟把大象放进冰箱一样,拢共三步:
- 继承ItemTouchHelper.Callback
- 使用Callback的实现构造ItemTouchHelper实例。
- 将ItemTouchHelper实例与RecycleView绑定。
实现ItemTouchHelper.Callback
对于拖动排序这种简单的操作,相比于直接继承Callback,更推荐使用预置的Callback抽象子类SimpleCallback。
首先我们来看看SimpleCallback的构造方法:
public SimpleCallback(int dragDirs, int swipeDirs) {
mDefaultSwipeDirs = swipeDirs;
mDefaultDragDirs = dragDirs;
}
- dragDirs:拖动方向。假如垂直布局的拖动方向一般就是上下;水平布局就是左右;流布局则通常为四个方向都可以。
- swipeDirs:滑动方向。常见的场景是垂直布局,把Item向左或者向右滑删除Item,这里用到的就是swipeDirs。一般与拖动方向垂直。
dragDirs与swipeDirs都取值与ItemTouchHelper的常量值:
| Value | Description |
|---|---|
| ItemTouchHelper.UP | 向上方向 |
| ItemTouchHelper.DOWN | 向下方向 |
| ItemTouchHelper.START | 向前方向(从左到右布局即向左) |
| ItemTouchHelper.END | 向后方向(从左到右布局即向右) |
以上的值可以通过与、或运算混合使用。
再来看看需要实现的两个方法:
public abstract boolean onMove(
//触发事件的RV
@NonNull RecyclerView recyclerView,
//正在拖动的Item对应的VH
@NonNull ViewHolder viewHolder,
//拖动到的Item对应的VH
@NonNull ViewHolder target
);
public abstract void onSwiped(@NonNull ViewHolder viewHolder, int direction);
- onMove。当拖动发生并移动到其他Item位置上时调用。也就是说如果按着Item,移动经过了10个Item,就会被调用10次。
- onSwipe。滑动发生时调用。
实现拖动排序重点是onMove,整个Callback如下:
val myCallback = object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
0
) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
//取出原位置的position
val from = viewHolder.adapterPosition
//取出目标位置的position
val to = target.adapterPosition
//取出原位置的数据
val e = list[from]
//删除原位置的数据
list.removeAt(from)
//向目标位置添加原位置的数据
list.add(to, e)
//通知Adapter移动了Item
recyclerView.adapter?.notifyItemMoved(from, to)
return true
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) = Unit
}
构造ItemTouchHelper实例
这就很简单了,没啥好说的了。
val helper = ItemTouchHelper(myCallback)
关联RecycleView
同样很简单!
helper.attachToRecyclerView(rv)
结言
通过对ItemTouchHelper的学习,掌握到了RecycleView拖动以及滑动相关的实现,实在是受益匪浅。