ItemTouchHelper是什么?
看看官方解释
|
|
通过这段解释其实可以清楚这个ItemTouchHelper到底是干什么的,它是一个可以给RecyclerView提供添加拖动排序与滑动删除等等操作的工具类。
大家应该清楚拖动排序与滑动删除其实如果代码去写会比较麻烦,所以ItemTouchHelper的出现也确实解决了这部分代码比较复杂的问题,这偏文章就简单的介绍下ItemTouchHelper的使用方法
简单实现
1.首先实现一个RecyclerView就好了
直接上代码
|
|
|
|
创建好了,如下

2.创建一个类继承ItemTouchHelper.Callback,并且与RecycleView建立链接
|
|
创建了一个类并继承了ItemTouchHelper.Callback与他的一些方法,但是些方法根据我们的需求需要重写
需要重写getMovementFlags()方法来指定可以支持的拖放和滑动的方向使用helperItemTouchHelper.makeMovementFlags(int, int)来构造返回的flag。这里我们启用了上下左右两种方向。注:上下为拖动(drag),左右为滑动(swipe)。
如下
|
|
接下来建立与RecycleView的链接
|
|
好的接下来就是见证奇迹的时刻了

但是显然不是我们想要的结果,但是还缺少什么呢?Adapter数据并没有发生实质性的变化,所以接下来工作就是去让Adapter内数据产生变化
3.通过接口改变Adapter数据
首先创建接口
|
|
然后在callback中调用
|
|
最后在Adapter中实现这个接口
|
|
接下来就是真正的见证奇迹的时刻了

拖动不知道为什么在模拟器上太难操作了,OMG
源码简析
ItemTouchHelper.CallBack分析
分析ItemTouchHelper之前,我们先看下CallBack的定义了那些方法
|
|
结合这些分析注释就明白了上面一篇文章里面CallBack为什么写那些方法了,还有部分的方法还是没有理解到底是干嘛的所有就没有注释了。
ItemTouchHelper相关分析
上一篇文章中把ItemTouchHelper与RecycleView以及CallBack建立连接的方法如下
|
|
那么从这个将ItemTouchHelper与RecycleView建立的方法进行分析
|
|
这部分的代码其实没有做太多的事情,无非是获取一些默认值,setupCallbacks()与destroyCallbacks()两个方法,这两个方法从名称看就是相对立的,所以分析一个就好了
destroyCallbacks()
setupCallbacks()
这里的步骤有点多了
分布来说明
1.addItemDecoration(this)
这个方法其实是调用了ItemDecoration的接口.从ItemTouchHelper方法声明部分也可以看到
|
|
在ItemTouchHelper中重写了ItemDecoration接口的两个方法如下
|
|
从方法可以看到这里其实没有做什么特别的工作,只是回调了Callback的两个回调方法onDrawOver()与onDraw()而这两个方法是Callback的private方法如下
|
|
这里牵扯的东西比较多,暂时不分析,我们可以看到有两个方法分别为onChildDrawOver()与onChildDraw()
调用了这两个方法,接下来看下这两个方法里面有什么?
|
|
这里面其实是sUICallback的回调方法
这里的sUICallback是一个接口,根据不同的版本执行不同的onDraw与onDrawOver方法
|
|
所以在我们自定义的CallBack中可以取重写onChildDraw()与onChildDrawOver()方法来实现自定义的拖动与滑动交互
2.addOnChildAttachStateChangeListener(this)
这里调用了OnChildAttachStateChangeListener这个接口,这个接口里有两个方法,分别是在RecycleView添加一个View与删除一个View的时候回调
那看看我们在ItemTouchHelper中重写的方法
|
|
因为ItemTouchHelper中只用考虑移除的情况,
这里面的方法暂时不介绍,可以看到回调了clearView()的方法,所以在元素的用户交互已经结束的时候,可以通过这个方法监听到
3.initGestureDetector()
这里主要是初始化GestureDetector
|
|
首先看下Callback调用了hasDragFlag这个方法,那我们看下这个方法
|
|
经过调用发现最后调用了getMovementFlags这个方法,所以我们重写方法如果是没有声明的在onLongPress中就直接return了,不会触发下面的方法了
再往下看,会调用Callback的isLongPressDragEnabled()方法,当return为true的时候会执行select()方法
4. addOnItemTouchListener
这里则是调用了RecycleView的addOnItemTouchListener方法,ItemTouchHelper重写了OnItemTouchListener接口的方法,OnItemTouchListener有三个方法,我们一个个来进行分析
(1).onInterceptTouchEvent
|
|
大部分注释都已经说明了,主要把他们调用的方法来进行说明
首先来看下RecoverAnimation这个类,这个类中有ValueAnimatorCompat主要是根据起始点及ActionState等做动画的。
接下来就贴出这个类
|
|
里面的成员变量大家看名称应该大部分就可以理解了,不做更多的说明了
那么来看看findAnimation()这个方法
|
|
往下看就可以看到endRecoverAnimation方法,这个方法主要就是从mRecoverAnimations集合中删除某个RecoverAnimation对象
|
|
接下来看下select()方法,这个方法作用是开始拖动或者滑动指定的View
|
|
|
|
通过代码这部分代码我们可以大致知道了select这个方法的作用了,它主要是处理当手指拖动或者滑动结束后的动画,要通过两次调用,第一次在我们选中的时候,作用是确定我们手指选择的View,第二次在我们手指放开的时候,作用是给这个View设置动画,并且执行。
接下来看看checkSelectForSwipe() 方法
|
|
这个方法主要是确定当前的我们选择的View是否可以滑动,而前面说的select方法的第一次调用是在这里,这个主要是滑动的select第一个方法,拖动的第一个select方法则在GestureDetector的onLongPress中
到这里基本就介绍结束onInterceptTouchEvent里面做的东西了
(2).onTouchEvent
|
|
在ACTION_UP时候触发的第二次select()则会执行动画效果
而ACTION_MOVE则是处理随着手指运动的效果,那我们看下里面的实现方法
主要有两个一个是moveIfNecessary另外一个是mScrollRunnable
我们看下mScrollRunnable
|
|
那我们先来分析下scrollIfNecessary()然后再分析moveIfNecessary()方法
scrollIfNecessary其实上面的注释解释的很清楚,它的作用是检测我们滑动是否到达RecycleView的边缘区域,如果到达边缘区域则将RecycleView移动(scrollBy),这里也调用了callback的interpolateOutOfBoundsScroll方法,所以我们可以在这里监听到我们拖出视图边界的调用
接下来看一下moveIfNecessary()方法
|
|
所以这里其实是用来判断是否move的带来RecycleView的变化
最后 调用了mRecyclerView.invalidate()方法,而这个方法呢则调用了前面所提到的ItemDecoration里的方法,而那里面的方法处理的是当运动带来的拖动与滑动的交互,前面有提到就不做过多的介绍了
所以总结一下,拖动时通过mRecyclerView.invalidate让onDraw不断重绘带来手指与点击ViewHolder的变化,当手指离开时候则通过select方法启动RecoverAnimation让ViewHolder执行后面的动画,基本的流程就是这样,当然中间有很多Callback方法带来不同的变化,感觉整个流程我还是讲的比较乱的,大家理解大致流程就好了。。到这里就基本分析结束了,当然还有一些方法可能没有介绍了,大家可以通过前面的Callback注释的方法去理解大致的功能就好了。