3、findAnimation 方法
在 findAnimation 方法中 , 先调用了 findChildView 方法 , 查找手指按下的 View 子组件 , 该子组件是 RecyclerView 中的一个条目 ;
// 找到手指按下所在位置的条目的 View 组件 // 查找手指按下的 View 子组件 , 该子组件时 RecyclerView 中的一个条目 View target = findChildView(event);
找到该条目对应的 View 组件后 , 遍历恢复动画 , 动画中有 mViewHolder 成员 , mViewHolder 中有 itemView 成员 , 设置 anim.mViewHolder.itemView 为手指按下的子组件 , 即设置该动画作用于 RecyclerView 的哪个条目上 ;
fo
r (int i = mRecoverAnimations.size() - 1; i >= 0; i--) { final RecoverAnimation anim = mRecoverAnimations.get(i); if (anim.mViewHolder.itemView == target) { return anim; } }
findAnimation 方法完整代码注释 :
// 该方法作用 : // 用户按下 RecyclerView 中的某个条目 // 该方法用于找到按下的条目 View , 并设置给 RecoverAnimation 恢复动画 @SuppressWarnings("WeakerAccess") /* synthetic access */ RecoverAnimation findAnimation(MotionEvent event) { if (mRecoverAnimations.isEmpty()) { return null; } // 找到手指按下所在位置的条目的 View 组件 // 查找手指按下的 View 子组件 , 该子组件时 RecyclerView 中的一个条目 View target = findChildView(event); // 遍历恢复动画 // 动画中有 mViewHolder 成员 , mViewHolder 中有 itemView 成员 // 设置 anim.mViewHolder.itemView 为手指按下的子组件 // 即设置该动画作用于 RecyclerView 的哪个条目上 ; for (int i = mRecoverAnimations.size() - 1; i >= 0; i--) { final RecoverAnimation anim = mRecoverAnimations.get(i); if (anim.mViewHolder.itemView == target) { return anim; } } return null; }
4、findChildView 方法
根据按下的 X, Y 坐标 , 查找对应的条目组件 , 先获取触摸的 XY 坐标 ;
final float x = event.getX(); final float y = event.getY();
如果 mSelected 成员不为空 , 则直接使用 , 分支中直接返回了 ;
if (mSelected != null) { final View selectedView = mSelected.itemView; if (hitTest(selectedView, x, y, mSelectedStartX + mDx, mSelectedStartY + mDy)) { return selectedView; } }
如果 mSelected 为空 , 则开始遍历进行检测 ;
for (int i = mRecoverAnimations.size() - 1; i >= 0; i--) { final RecoverAnimation anim = mRecoverAnimations.get(i); final View view = anim.mViewHolder.itemView; // 根据当前按下的坐标 , 找到列表条目对应的 View 组件 if (hitTest(view, x, y, anim.mX, anim.mY)) { return view; } }
findChildView 完整代码注释 :
@SuppressWarnings("WeakerAccess") /* synthetic access */ View findChildView(MotionEvent event) { // first check elevated views, if none, then call RV // 根据按下的 X, Y 坐标 , 查找对应的条目 final float x = event.getX(); final float y = event.getY(); // 如果 mSelected 成员不为空 , 则直接使用 , 分支中直接返回了 if (mSelected != null) { final View selectedView = mSelected.itemView; if (hitTest(selectedView, x, y, mSelectedStartX + mDx, mSelectedStartY + mDy)) { return selectedView; } } // 如果 mSelected 为空 , 则开始遍历进行检测 for (int i = mRecoverAnimations.size() - 1; i >= 0; i--) { final RecoverAnimation anim = mRecoverAnimations.get(i); final View view = anim.mViewHolder.itemView; // 根据当前按下的坐标 , 找到列表条目对应的 View 组件 if (hitTest(view, x, y, anim.mX, anim.mY)) { return view; } } return mRecyclerView.findChildViewUnder(x, y); }
5、动作取消
当拦截的动作是 MotionEvent.ACTION_CANCEL 或 action == MotionEvent.ACTION_UP 动作时 , 说明用户取消了该动作 , 将选择的组件置空 ;
} else if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
mActivePointerId = ACTIVE_POINTER_ID_NONE;
// 抬起 / 取消 时 , 选择项 置空 .
select(null, ACTION_STATE_IDLE);
}
1
2
3
4
5
6、动作完成
ACTIVE_POINTER_ID_NONE 表示是否完成了滑动 , 如果滑动完成 , 触发了侧滑事件 , 才会进入该 else if (mActivePointerId != ACTIVE_POINTER_ID_NONE) 分支 , 如果滑动没有完成 , 滑到半路 , 松开手 , 条目组件缩回去了 , 则不会进入该分支 ;
} else if (mActivePointerId != ACTIVE_POINTER_ID_NONE) { // 该分支表示滑动操作完成的分支 // ACTIVE_POINTER_ID_NONE 表示是否完成了滑动 // 如果滑动完成 , 触发了侧滑事件 , 才会进入该分支 // 如果滑动没有完成 , 滑到半路 , 松开手 , 条目组件缩回去了 , 则不会进入该分支 // in a non scroll orientation, if distance change is above threshold, we // can select the item // 滑动完成后 , 记录当前的触摸指针索引 final int index = event.findPointerIndex(mActivePointerId); if (DEBUG) { Log.d(TAG, "pointer index " + index); } if (index >= 0) { // 检查是否完成了滑动操作 checkSelectForSwipe(action, event, index); } }