ItemTouchHelper是v7包RecyclerView的ItemDecoration接口的一个实现,其前身是v4包的ViewDragHelper(可在任意ViewGroup中使用)在DrawerLayout、SlidingPaneLayout源码中都有应用。
两者使用方法也很类似,都是实现各自的Callback
ItemTouchHelper手势的实现都在匿名内部类mOnItemTouchListener中实现,
private final OnItemTouchListener mOnItemTouchListener
= new OnItemTouchListener()
与RecyclerView的绑定,则在attachToRecyclerView方法中的setupCallbacks()中
add到RV中
/**
* Attaches the ItemTouchHelper to the provided RecyclerView. If TouchHelper is already
* attached to a RecyclerView, it will first detach from the previous one. You can call this
* method with {@code null} to detach it from the current RecyclerView.
*
* @param recyclerView The RecyclerView instance to which you want to add this helper or
* {@code null} if you want to remove ItemTouchHelper from the current
* RecyclerView.
*/
public void attachToRecyclerView(@Nullable RecyclerView recyclerView) {
if (mRecyclerView == recyclerView) {
return; // nothing to do
}
if (mRecyclerView != null) {
destroyCallbacks(); //避免重复绑定
}
mRecyclerView = recyclerView;
if (mRecyclerView != null) {
final Resources resources = recyclerView.getResources();
mSwipeEscapeVelocity = resources
.getDimension(R.dimen.item_touch_helper_swipe_escape_velocity);
mMaxSwipeVelocity = resources
.getDimension(R.dimen.item_touch_helper_swipe_escape_max_velocity);
setupCallbacks(); //初始化 setup
}
}
private void setupCallbacks() {
ViewConfiguration vc = ViewConfiguration.get(mRecyclerView.getContext());
mSlop = vc.getScaledTouchSlop(); //初始化TouchSlop
mRecyclerView.addItemDecoration(this); //绑定Callback.OnDraw供实现onChildDraw
mRecyclerView.addOnItemTouchListener(mOnItemTouchListener); //绑定手势监听
mRecyclerView.addOnChildAttachStateChangeListener(this);
initGestureDetector();
}
private void destroyCallbacks() {
mRecyclerView.removeItemDecoration(this); //避免重复绑定
mRecyclerView.removeOnItemTouchListener(mOnItemTouchListener); //避免重复绑定
mRecyclerView.removeOnChildAttachStateChangeListener(this); //避免重复绑定
// clean all attached
final int recoverAnimSize = mRecoverAnimations.size();
for (int i = recoverAnimSize - 1; i >= 0; i--) {
final RecoverAnimation recoverAnimation = mRecoverAnimations.get(0);
mCallback.clearView(mRecyclerView, recoverAnimation.mViewHolder);
}
mRecoverAnimations.clear();
mOverdrawChild = null;
mOverdrawChildPosition = -1;
releaseVelocityTracker();
}
进入正题
严格的说,ItemTouchHelper的手势正式接管方法是select()方法,而通过手势开始(达到某种条件)而进入select的入口总共3个
1、长按
2、与rv垂直方向的swipe移动(超过touchSlop的Move)
3、按下一个正在做恢复动画的vh(对RecoverAnimation没做完的vh触发Down事件)
既然是手势接管,毫无疑问,这些入口的入口一定来自mOnItemTouchListener的OnInterceptTouchEvent方法
@Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent event) {
mGestureDetector.onTouchEvent(event);//主要实现onLongPress的监听
这里就是
入口1,下有对于ItemTouchHelperGestureListener的onLongPress具体分析
//如果是个长按 那么拦截短路掉RV自己的滑动
//并判定Down选中的vh ItemTouchHelper正式接管
if (DEBUG) {
Log.d(TAG, "intercept: x:" + event.getX() + ",y:" + event.getY() + ", " + event);
}
final int