- CompoundButton 源码分析
- LinearLayout 源码分析
- SearchView 源码解析
- LruCache 源码解析
- ViewDragHelper 源码解析
- BottomSheets 源码解析
- Media Player 源码分析
- NavigationView 源码解析
- Service 源码解析
- Binder 源码分析
- Android 应用 Preference 相关及源码浅析 SharePreferences 篇
- ScrollView 源码解析
- Handler 源码解析
- NestedScrollView 源码解析
- SQLiteOpenHelper/SQLiteDatabase/Cursor 源码解析
- Bundle 源码解析
- LocalBroadcastManager 源码解析
- Toast 源码解析
- TextInputLayout
- LayoutInflater 和 LayoutInflaterCompat 源码解析
- TextView 源码解析
- NestedScrolling 事件机制源码解析
- ViewGroup 源码解析
- StaticLayout 源码分析
- AtomicFile 源码解析
- AtomicFile 源码解析
- Spannable 源码分析
- Notification 之 Android 5.0 实现原理
- CoordinatorLayout 源码分析
- Scroller 源码解析
- SwipeRefreshLayout 源码分析
- FloatingActionButton 源码解析
- AsyncTask 源码分析
- TabLayout 源码解析
NestedScrolling 事件处理
当 CoordinatorLayout 的子控件有 NestedScrollingChild 产生 Nested 事件的时候.会调用 onStartNestedScroll 这个方法
@Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) { return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;//滑动 Y 轴方向的判断 }
返回值 true :表示 BehaviorView 要和 NestedScrollingChild 配合消耗这个 NestedScrolling 事件,这里可以看出只要是纵向的滑动都会返回 true.
onNestedPreScroll
NestedScrollingChild 的在滑动的时候会触发 onNestedPreScroll
方法,询问 BehaviorView 消耗多少 Y 轴上面的滑动。
@Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed) { View scrollingChild = mNestedScrollingChildRef.get(); if (target != scrollingChild) { return; } int currentTop = child.getTop(); int newTop = currentTop - dy; if (dy > 0) { // Upward if (newTop < mMinOffset) { consumed[1] = currentTop - mMinOffset; ViewCompat.offsetTopAndBottom(child, -consumed[1]); setStateInternal(STATE_EXPANDED); } else { consumed[1] = dy; ViewCompat.offsetTopAndBottom(child, -dy); setStateInternal(STATE_DRAGGING); } } else if (dy < 0) { // Downward if (!ViewCompat.canScrollVertically(target, -1)) { if (newTop <= mMaxOffset || mHideable) { consumed[1] = dy; ViewCompat.offsetTopAndBottom(child, -dy); setStateInternal(STATE_DRAGGING); } else { consumed[1] = currentTop - mMaxOffset; ViewCompat.offsetTopAndBottom(child, -consumed[1]); setStateInternal(STATE_COLLAPSED); } } } dispatchOnSlide(child.getTop()); mLastNestedScrollDy = dy; mNestedScrolled = true; }
onNestedPreScroll 方法主要做几件事情:
- 判断发起 NestedScrolling 的 View 是否是我们在 onLayoutChild 找到的那个控件.不是的话,不做处理.不处理就是不消耗 y 轴,把所有的 Scroll 交给发起的 View 自己消耗。
- 根据 dy 判断方向,根据之前的偏移范围算出偏移量.使用
ViewCompat.offsetTopAndBottom
对 BehaviorView 进行偏移操作。 - 消耗 Y 轴的偏移量.发起 NestedScrollingChild 会自动响应剩下的部分
其中 comsume[]是个数组,consumed[1]表示 Parent 在 Y 轴消耗的值, NestedScrollingChild 会消耗除 BehaviorView 消耗剩下的那部分( 比如: NestedScrollingChild 要滑动 20 像素,因为 BehaviorView 消耗了 10 像素,最后 NestedScrollingChild 只滑动了 10 像素);
onStopNestedScroll
在 Nestd 事件结束触发. 主要做的事情: 根据 BehaviorView 当前的状态对它的最终位置的确定,有必要的话调用 ViewDragHelper.smoothSlideViewTo
进行滑动. ####注意 当你是往下滑动且 Hideable 为 true ,他会 使用上面计算的 Y 轴的速率的判断.是否应该切换到 Hideable 的状态。
onNestedPreFling
这个是 NestedScrollingChild 要滑行时候触发的,询问 BehaviorView 是否消耗这个滑行。
@Override
public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, V child, View target,
float velocityX, float velocityY) {
return target == mNestedScrollingChildRef.get() &&
(mState != STATE_EXPANDED ||
super.onNestedPreFling(coordinatorLayout, child, target,
velocityX, velocityY));
}
处理逻辑是:发起 Nested 事件要与 onLayoutChild 找到的那个控件一致且当前状态是一个 STATE_EXPANDED 状态。
返回值: true 表示 BehaviorView 消耗滑行事件,那么 NestedScrollingChild 就不会有滑行了
ViewDragHelper.Callback
ViewDragHelper 网上教程挺多的,就不多讲了,他主要是处理滑动拖拽的。
小技巧:在说说一个小技巧,Android 官网中有这样一句话: Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android ,就是说枚举比静态常量更加耗费内存,我们应该避免使用,然后我看 BottomSheetBehavior 源码中 mState 是这样定义的:
public static final int STATE_DRAGGING = 1; public static final int STATE_SETTLING = 2; public static final int STATE_EXPANDED = 3; public static final int STATE_COLLAPSED = 4; public static final int STATE_HIDDEN = 5; @IntDef({STATE_EXPANDED, STATE_COLLAPSED, STATE_DRAGGING, STATE_SETTLING, STATE_HIDDEN}) @Retention(RetentionPolicy.SOURCE) public @interface State {} @State private int mState = STATE_COLLAPSED;
弥补了 Android 不建议使用枚举的缺陷。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论