- 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 源码解析
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
事件拦截
touch 事件会先被 onInterceptTouchEvent() 捕获,进行判断是否拦截。
@Override public boolean onInterceptTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) { if (!child.isShown()) { return false; } int action = MotionEventCompat.getActionMasked(event); // Record the velocity if (action == MotionEvent.ACTION_DOWN) { reset(); } if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); switch (action) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mTouchingScrollingChild = false; mActivePointerId = MotionEvent.INVALID_POINTER_ID; // Reset the ignore flag if (mIgnoreEvents) { mIgnoreEvents = false; return false; } break; case MotionEvent.ACTION_DOWN: int initialX = (int) event.getX(); mInitialY = (int) event.getY(); View scroll = mNestedScrollingChildRef.get(); if (scroll != null && parent.isPointInChildBounds(scroll, initialX, mInitialY)) { mActivePointerId = event.getPointerId(event.getActionIndex()); mTouchingScrollingChild = true; } mIgnoreEvents = mActivePointerId == MotionEvent.INVALID_POINTER_ID && !parent.isPointInChildBounds(child, initialX, mInitialY); break; } if (!mIgnoreEvents && mViewDragHelper.shouldInterceptTouchEvent(event)) { return true; } // We have to handle cases that the ViewDragHelper does not capture the bottom sheet because // it is not the top most view of its parent. This is not necessary when the touch event is // happening over the scrolling content as nested scrolling logic handles that case. View scroll = mNestedScrollingChildRef.get(); return action == MotionEvent.ACTION_MOVE && scroll != null && !mIgnoreEvents && mState != STATE_DRAGGING && !parent.isPointInChildBounds(scroll, (int) event.getX(), (int) event.getY()) && Math.abs(mInitialY - event.getY()) > mViewDragHelper.getTouchSlop(); }
onInterceptTouchEvent 做了几件事情:
- 判断是否拦截事件.先使用 mViewDragHelper.shouldInterceptTouchEvent(event) 拦截。
- 使用 mVelocityTracker 记录手指动作,用于后期计算 Y 轴速率。
- 判断点击事件是否在 NestedChildView 上,将 boolean 存到 mTouchingScrollingChild 标记位中,这个主要是用于 ViewDragHelper.Callback 中的判断。
- ACTION_UP 和 ACTION_CANCEL 对标记位进行复位,好在下一轮 Touch 事件中使用。
onTouchEvent 处理
@Override public boolean onTouchEvent(CoordinatorLayout parent, V child, MotionEvent event) { if (!child.isShown()) { return false; } int action = MotionEventCompat.getActionMasked(event); if (mState == STATE_DRAGGING && action == MotionEvent.ACTION_DOWN) { return true; } mViewDragHelper.processTouchEvent(event); // Record the velocity if (action == MotionEvent.ACTION_DOWN) { reset(); } if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); // The ViewDragHelper tries to capture only the top-most View. We have to explicitly tell it // to capture the bottom sheet in case it is not captured and the touch slop is passed. if (action == MotionEvent.ACTION_MOVE) { if (Math.abs(mInitialY - event.getY()) > mViewDragHelper.getTouchSlop()) { mViewDragHelper.captureChildView(child, event.getPointerId(event.getActionIndex())); } } return true; }
onTouchEvent 主要做了几件事情:
- 使用 mVelocityTracker 记录手指动作.用于后期计算 Y 轴速率。
- 使用 mViewDragHelper 处理 Touch 事件.可能会产生拖动效果。
- mViewDragHelper 在滑动的时候对 BehaviorView 的再一次捕获.再一次明确告诉 ViewDragHelper 我要移动的是 BehaviorView 组件.什么情况需要主动告诉 ViewDragHelper ?比如:当你点击在 BehaviorView 的区域,但是 BehaviorView 的视图的层级不是最高的,或者你点击的区域不在 BehaviorView 上,ViewDragHelper 在做处理滑动的时候找不到 BehaviorView, 这个时候你要手动告知它现在要移动的是 BehaviorView,情景类似 ViewDragHelper 处理 EdgeDrag 的样子。
注意:即使你的 onInterceptTouchEvent 返回 false,也可能因为下面的 View 没有处理这个 Touch 事件,而导致 Touch 事件上发被 Behavior 的 onTouchEvent 被截取。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论