ItemTouchHelper源码分析(中)
来源:互联网 发布:淘宝爱奇艺会员店铺 编辑:程序博客网 时间:2024/05/16 08:02
其中最主要的是调用了select(null, ACTION_STATE_IDLE)方法,由于方法复杂,我们目前先暂不讲解。
关于onInterceptTouchEvent(),我们最后再看一下返回值,return mSelected != null;也就是说mSelected不为null的时候就返回true,这个返回值如果为true,那么就会调用 方法
onTouchEvent(RecyclerView recyclerView, MotionEvent event)
这个方法就是用于接收手指移动的事件了。
public void onTouchEvent(RecyclerView recyclerView, MotionEvent event) {
mGestureDetector.onTouchEvent(event);
if (DEBUG) {
Log.d(TAG,
"on touch: x:" + mInitialTouchX + ",y:" + mInitialTouchY + ", :" + event);
}
if (mVelocityTracker != null) {
mVelocityTracker.addMovement(event);
}
if (mActivePointerId == ACTIVE_POINTER_ID_NONE) {
return;
}
final int action = MotionEventCompat.getActionMasked(event);
final int activePointerIndex = MotionEventCompat
.findPointerIndex(event, mActivePointerId);
if (activePointerIndex >= 0) {
checkSelectForSwipe(action, event, activePointerIndex);
}
ViewHolder viewHolder = mSelected;
if (viewHolder == null) {
return;
}
switch (action) {
//Part3
case MotionEvent.ACTION_MOVE: {
// Find the index of the active pointer and fetch its position
if (activePointerIndex >= 0) {
updateDxDy(event, mSelectedFlags, activePointerIndex);
moveIfNecessary(viewHolder);
mRecyclerView.removeCallbacks(mScrollRunnable);
mScrollRunnable.run();
mRecyclerView.invalidate();
}
break;
}
case MotionEvent.ACTION_CANCEL:
if (mVelocityTracker != null) {
mVelocityTracker.clear();
}
//Part4
// fall through
case MotionEvent.ACTION_UP:
select(null, ACTION_STATE_IDLE);
mActivePointerId = ACTIVE_POINTER_ID_NONE;
break;
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = MotionEventCompat.getActionIndex(event);
final int pointerId = MotionEventCompat.getPointerId(event, pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mActivePointerId = MotionEventCompat.getPointerId(event, newPointerIndex);
updateDxDy(event, mSelectedFlags, pointerIndex);
}
break;
}
}
}
首先,请看Part3,:这个是onTouchEvent的核心部分.它给我们呈现的是手指移动的时候需要做的事情。
其次,请看Part4,这个是手指离开屏幕的时候需要做的事情,当手指离开的时候做的事情和在onInterceptTouchEvent 里面介绍的一样,他们都是进行相同的操作。
那么,Part3 里面具体都做了什么呢?
updateDxDy(),计算的是当前touch事件移动的坐标,算法中使用了Part1中记录的位置信息。
moveIfNecessary(),计算是否需要移动正在移动的item在RecyclerView 里面的位置,这个里面会调用一系列的Callback里面接口,通过一系列的判断决定时候需要将当前item在Adapter中的index进行修改。
mScrollRunnable.run(),我们可以先看看mScrollRunnable的源码。
private final Runnable mScrollRunnable = new Runnable() {
@Override
public void run() {
if (mSelected != null && scrollIfNecessary()) {
if (mSelected != null) { //it might be lost during scrolling
moveIfNecessary(mSelected);
}
mRecyclerView.removeCallbacks(mScrollRunnable);
ViewCompat.postOnAnimation(mRecyclerView, this);
}
}
};
这个方法其实是一个递归调用,大家看到没有,ViewCompat.postOnAnimation(mRecyclerView, this)方法就是设置一个帧动画时间,到点就重启Runnable。而这个方法里面主要做的事情是moveIfNecessary(mSelected);这个方法在上面已经介绍过,就是移动item的位置。所以联合起来理解,就是用一个递归的方法反复的调用move来达到一个拖动效果,这个效果就是一个item移动到屏幕边境的时候,会和看不见的又存在的item进行转换位置的动效的数据部分了。
紧接着,mRecyclerView.invalidate();被调用了。
Invalidate(),将触发recyclerView的onDraw方法被调用,onDraw方法如下:
public void onDraw(Canvas c) {
super.onDraw(c);
final int count = mItemDecorations.size();
for (int i = 0; i < count; i++) {
mItemDecorations.get(i).onDraw(c, this, mState);
}
}
这个方法会调用 mItemDecorations.get(i).onDraw(c, this, mState);而ItemTouchHelper就是其中一个item,可以通过setupCallbacks()发现这一点。这个时候ItemTouchHelper的onDraw方法被调用了。
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
// we don't know if RV changed something so we should invalidate this index.
mOverdrawChildPosition = -1;
float dx = 0, dy = 0;
if (mSelected != null) {
getSelectedDxDy(mTmpPosition);
dx = mTmpPosition[0];
dy = mTmpPosition[1];
}
mCallback.onDraw(c, parent, mSelected,
mRecoverAnimations, mActionState, dx, dy);
}
在这个方法里面又会调用mCallback.onDraw,当我们点击进入这个函数的时候,会发现其实它调用了Callback 类的onDraw方法,再看源码:
private void onDraw(Canvas c, RecyclerView parent, ViewHolder selected,
List<ItemTouchHelper.RecoverAnimation> recoverAnimationList,
int actionState, float dX, float dY) {
final int recoverAnimSize = recoverAnimationList.size();
for (int i = 0; i < recoverAnimSize; i++) {
final ItemTouchHelper.RecoverAnimation anim = recoverAnimationList.get(i);
anim.update();
final int count = c.save();
onChildDraw(c, parent, anim.mViewHolder, anim.mX, anim.mY, anim.mActionState,
false);
c.restoreToCount(count);
}
if (selected != null) {
final int count = c.save();
onChildDraw(c, parent, selected, dX, dY, actionState, true);
c.restoreToCount(count);
}
}
- ItemTouchHelper源码分析(中)
- ItemTouchHelper源码分析(上)
- RecyclerView ItemTouchHelper源码分析扩展
- (二十八)RecyclerView ItemTouchHelper 源码分析以及拓展
- ItemTouchHelper源码分析 手势分析OnTouchEvent
- ItemTouchHelper源码分析 拖拽到屏幕边缘的处理
- 源码分析 ItemTouchHelper手势的入口 (OnInterceptTouchEvent onLongPress等)
- RecyclerView源码详解(第一篇ItemTouchHelper源码详解)
- ItemTouchHelper源码解析
- ItemTouchHelper
- material design(三)recycleview的ItemTouchHelper
- coreboot(linuxBIOS)中bootblock源码分析
- Jquery源码分析---DOM元素(中)
- Android中Context源码分析(一)
- Android中ContextImpl源码分析(二)
- HashMap源码分析(中)--Java篇
- kubelet源码分析(编辑中)
- 源码-Spark中Worker源码分析(一)
- Android.mk文件学习笔记
- 调用pdo模式的时候出现"无法加载数据库驱动“
- Python知识点整理
- Nginx启动提示找不到libpcre.so.1解决方法
- 39STL之查找算法
- ItemTouchHelper源码分析(中)
- 关于wampserver里面出现错误的问题解决方法
- 生成随机数的类Random和ThreadLocalRandom
- iOS开发之解决WebView自适应内容高度
- mysql的聚集函数
- 提交文件到svn,提示"is not under version control
- 大数阶乘
- Android饼状图的绘制
- 设计模式在架构设计中的运用