ItemTouchHelper源码分析 拖拽到屏幕边缘的处理
2017-07-03 20:17
411 查看
如果列表被拖拉到屏幕边缘 该runnable会被递归调用
/**
* When user drags a view to the edge, we start scrolling the LayoutManager as long as View
* is partially out of bounds.
*/
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()实际调用了view.postOnAnimation
下面是调用的方法栈:
static final ViewCompatImpl IMPL;
static {
final int version = android.os.Build.VERSION.SDK_INT;
if (BuildCompat.isAtLeastN()) {
IMPL = new Api24ViewCompatImpl();
} else if (version >= 23) {
IMPL = new MarshmallowViewCompatImpl();
} else if (version >= 21) {
IMPL = new LollipopViewCompatImpl();
} else if (version >= 19) {
IMPL = new KitKatViewCompatImpl();
} else if (version >= 18) {
IMPL = new JbMr2ViewCompatImpl();
} else if (version >= 17) {
IMPL = new JbMr1ViewCompatImpl();
} else if (version >= 16) {
IMPL = new JBViewCompatImpl(); //在这里实现
} else if (version >= 15) {
IMPL = new ICSMr1ViewCompatImpl();
} else if (version >= 14) {
IMPL = new ICSViewCompatImpl();
} else if (version >= 11) {
IMPL = new HCViewCompatImpl();
} else {
IMPL = new BaseViewCompatImpl();
}
}
static class JBViewCompatImpl extends ICSMr1ViewCompatImpl {
@Override
public boolean hasTransientState(View view) {
return ViewCompatJB.hasTransientState(view);
}
@Override
public void setHasTransientState(View view, boolean hasTransientState) {
ViewCompatJB.setHasTransientState(view, hasTransientState);
}
@Override
public void postInvalidateOnAnimation(View view) {
ViewCompatJB.postInvalidateOnAnimation(view);
}
@Override
public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom) {
ViewCompatJB.postInvalidateOnAnimation(view, left, top, right, bottom);
}
@Override
public void postOnAnimation(View view, Runnable action) {
ViewCompatJB.postOnAnimation(view, action);
}
回来看scrollIfNecessary和moveIfNecessary方法
mCallback.interpolateOutOfBoundsScroll 方法介绍
/**
* Called by the ItemTouchHelper when user is dragging a view out of bounds.
* <p>
* You can override this method to decide how much RecyclerView should scroll in response
* to this action. Default implementation calculates a value based on the amount of View
* out of bounds and the time it spent there. The longer user keeps the View out of bounds,
* the faster the list will scroll. Similarly, the larger portion of the View is out of
当用户界外拖动rv 被ItemTouchHelper调用。 返回值 计算应该滚动多少!
您可以重写此方法以决定RecyclerView响应这个动作时应该滚动多少。默认实现基于越界的View数量和它在那里花费的时间来计算一个值。用户将View拖拽在界外越久,列表将滚动得越快。同样,View的较大部分出界,RecyclerView将滚动得更快。
scrollIfNecessary 计算出scrollY之后 mRecyclerView调用scrollBy(scrollX, scrollY); 然后返回true 让moveIfNecessary再去决定是否要回调onMove或者onSwap
/**
* When user drags a view to the edge, we start scrolling the LayoutManager as long as View
* is partially out of bounds.
*/
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()实际调用了view.postOnAnimation
下面是调用的方法栈:
static final ViewCompatImpl IMPL;
static {
final int version = android.os.Build.VERSION.SDK_INT;
if (BuildCompat.isAtLeastN()) {
IMPL = new Api24ViewCompatImpl();
} else if (version >= 23) {
IMPL = new MarshmallowViewCompatImpl();
} else if (version >= 21) {
IMPL = new LollipopViewCompatImpl();
} else if (version >= 19) {
IMPL = new KitKatViewCompatImpl();
} else if (version >= 18) {
IMPL = new JbMr2ViewCompatImpl();
} else if (version >= 17) {
IMPL = new JbMr1ViewCompatImpl();
} else if (version >= 16) {
IMPL = new JBViewCompatImpl(); //在这里实现
} else if (version >= 15) {
IMPL = new ICSMr1ViewCompatImpl();
} else if (version >= 14) {
IMPL = new ICSViewCompatImpl();
} else if (version >= 11) {
IMPL = new HCViewCompatImpl();
} else {
IMPL = new BaseViewCompatImpl();
}
}
static class JBViewCompatImpl extends ICSMr1ViewCompatImpl {
@Override
public boolean hasTransientState(View view) {
return ViewCompatJB.hasTransientState(view);
}
@Override
public void setHasTransientState(View view, boolean hasTransientState) {
ViewCompatJB.setHasTransientState(view, hasTransientState);
}
@Override
public void postInvalidateOnAnimation(View view) {
ViewCompatJB.postInvalidateOnAnimation(view);
}
@Override
public void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom) {
ViewCompatJB.postInvalidateOnAnimation(view, left, top, right, bottom);
}
@Override
public void postOnAnimation(View view, Runnable action) {
ViewCompatJB.postOnAnimation(view, action);
}
class ViewCompatJB { public static boolean hasTransientState(View view) { return view.hasTransientState(); } public static void setHasTransientState(View view, boolean hasTransientState) { view.setHasTransientState(hasTransientState); } public static void postInvalidateOnAnimation(View view) { view.postInvalidateOnAnimation(); } public static void postInvalidateOnAnimation(View view, int left, int top, int right, int bottom) { view.postInvalidate(left, top, right, bottom); } public static void postOnAnimation(View view, Runnable action) { view.postOnAnimation(action); }
回来看scrollIfNecessary和moveIfNecessary方法
/** * If user drags the view to the edge, trigger a scroll if necessary. 如果用户拖拽rv到边缘,必要的话将在这个方法内触发scrollby */ boolean scrollIfNecessary() { if (mSelected == null) { mDragScrollStartTimeInMs = Long.MIN_VALUE; return false; } final long now = System.currentTimeMillis(); final long scrollDuration = mDragScrollStartTimeInMs == Long.MIN_VALUE ? 0 : now - mDragScrollStartTimeInMs; RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager(); if (mTmpRect == null) { mTmpRect = new Rect(); } int scrollX = 0; int scrollY = 0; lm.calculateItemDecorationsForChild(mSelected.itemView, mTmpRect); if (lm.canScrollHorizontally()) { int curX = (int) (mSelectedStartX + mDx); final int leftDiff = curX - mTmpRect.left - mRecyclerView.getPaddingLeft(); if (mDx < 0 && leftDiff < 0) { scrollX = leftDiff; } else if (mDx > 0) { final int rightDiff = curX + mSelected.itemView.getWidth() + mTmpRect.right - (mRecyclerView.getWidth() - mRecyclerView.getPaddingRight()); if (rightDiff > 0) { scrollX = rightDiff; } } } if (lm.canScrollVertically()) { int curY = (int) (mSelectedStartY + mDy); final int topDiff = curY - mTmpRect.top - mRecyclerView.getPaddingTop(); if (mDy < 0 && topDiff < 0) { scrollY = topDiff; } else if (mDy > 0) { final int bottomDiff = curY + mSelected.itemView.getHeight() + mTmpRect.bottom - (mRecyclerView.getHeight() - mRecyclerView.getPaddingBottom()); if (bottomDiff > 0) { scrollY = bottomDiff; } } } if (scrollX != 0) { scrollX = mCallback.interpolateOutOfBoundsScroll(mRecyclerView, mSelected.itemView.getWidth(), scrollX, mRecyclerView.getWidth(), scrollDuration); } if (scrollY != 0) { scrollY = mCallback.interpolateOutOfBoundsScroll(mRecyclerView, mSelected.itemView.getHeight(), scrollY, mRecyclerView.getHeight(), scrollDuration); } if (scrollX != 0 || scrollY != 0) { if (mDragScrollStartTimeInMs == Long.MIN_VALUE) { mDragScrollStartTimeInMs = now; } mRecyclerView.scrollBy(scrollX, scrollY); return true; } mDragScrollStartTimeInMs = Long.MIN_VALUE; return false; }
mCallback.interpolateOutOfBoundsScroll 方法介绍
/**
* Called by the ItemTouchHelper when user is dragging a view out of bounds.
* <p>
* You can override this method to decide how much RecyclerView should scroll in response
* to this action. Default implementation calculates a value based on the amount of View
* out of bounds and the time it spent there. The longer user keeps the View out of bounds,
* the faster the list will scroll. Similarly, the larger portion of the View is out of
当用户界外拖动rv 被ItemTouchHelper调用。 返回值 计算应该滚动多少!
您可以重写此方法以决定RecyclerView响应这个动作时应该滚动多少。默认实现基于越界的View数量和它在那里花费的时间来计算一个值。用户将View拖拽在界外越久,列表将滚动得越快。同样,View的较大部分出界,RecyclerView将滚动得更快。
scrollIfNecessary 计算出scrollY之后 mRecyclerView调用scrollBy(scrollX, scrollY); 然后返回true 让moveIfNecessary再去决定是否要回调onMove或者onSwap
相关文章推荐
- ItemTouchHelper源码分析 手势分析OnTouchEvent
- ItemTouchHelper源码分析(上)
- (二十八)RecyclerView ItemTouchHelper 源码分析以及拓展
- 源码分析 ItemTouchHelper手势的入口 (OnInterceptTouchEvent onLongPress等)
- 从源码来看ItemTouchHelper实现RecyclerView列表的拖拽和侧滑
- android之RecycleView之ItemTouchHelper 处理拖拽、滑动删除
- RecyclerView之使用ItemTouchHelper和ItemTouchHelper.Callback实现条目拖拽排序
- memcached源码分析-----item过期失效处理以及LRU爬虫
- RecyclerView进阶:使用ItemTouchHelper实现拖拽和侧滑删除
- ItemTouchHelper源码解析
- ItemTouchHelper实现拖拽笔刷效果-part1
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- memcached源码分析-----item过期失效处理以及LRU爬虫
- RecyclerView+ItemTouchHelper实现拖拽滑动
- Android实现RecyclerView侧滑删除和长按拖拽-ItemTouchHelper
- android开发游记:ItemTouchHelper 使用RecyclerView打造可拖拽的GridView
- Android学习之ItemTouchHelper实现RecylerView的拖拽以及滑动删除功能
- ItemTouchHelper 使用RecyclerView打造可拖拽的GridView
- 使用ItemTouchHelper轻松实现RecyclerView拖拽排序和滑动删除