CoordinatorLayout的滑动事件处理机制
来源:互联网 发布:尼尔森数据分析 编辑:程序博客网 时间:2024/06/13 21:41
我们知道,安卓中View事件处理是Activity—>Window—>
DecorView—>ViewGroup—>View。当然也可以中途拦截。那么当我们在FloatingActionButton的布局文件中设置layout_anchor、layout_anchorGravity和layout_behavior时,RecyclerView的滑动事件是如何传递的呢?
以onNestedFling方法为例
case MotionEvent.ACTION_UP: { mVelocityTracker.addMovement(vtev); eventAddedToVelocityTracker = true; mVelocityTracker.computeCurrentVelocity(1000, mMaxFlingVelocity); final float xvel = canScrollHorizontally ? -VelocityTrackerCompat.getXVelocity(mVelocityTracker, mScrollPointerId) : 0; final float yvel = canScrollVertically ? -VelocityTrackerCompat.getYVelocity(mVelocityTracker, mScrollPointerId) : 0; if (!((xvel != 0 || yvel != 0) && fling((int) xvel, (int) yvel))) { setScrollState(SCROLL_STATE_IDLE); }
在此过程中会调用fling方法,此方法会先调用onNestedPreFling来处理,如果返回false就接着调用onNestedFling。当然不是直接调用,而是先通过调用NestedScrollingChildHelper类中相应的方法,NestedScrollingChildHelper是ViewParentCompat的代理类,ViewParentCompat会调用FloatingActionButton的父控件来最终调用我们自己Behavior类实现的方法。如下所示:
//RecyclerView中的方法 @Override public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { return mScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);//mScrollingChildHelper是NestedScrollingChildHelper的实例 }
//NestedScrollingChildHelper类中的方法public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { if (isNestedScrollingEnabled() && mNestedScrollingParent != null) { return ViewParentCompat.onNestedFling(mNestedScrollingParent, mView, velocityX,velocityY, consumed); } return false; }//mNestedScrollingParent为mView的父控件
//ViewParentCompat中的方法public static boolean onNestedFling(ViewParent parent, View target, float velocityX, float velocityY, boolean consumed) { return IMPL.onNestedFling(parent, target, velocityX, velocityY, consumed); }
//ViewParentCompat中onNestedFling方法的实现@Override public boolean onNestedFling(ViewParent parent, View target, float velocityX, float velocityY, boolean consumed) { if (parent instanceof NestedScrollingParent) { return ((NestedScrollingParent) parent).onNestedFling(target, velocityX, velocityY, consumed); } return false; }
从这里可以看出相应的事件已经传到父控件中了,即CoordinatorLayout类中,相关实现如下:
//CoordinatorLayout中的方法public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { boolean handled = false; final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { final View view = getChildAt(i); final LayoutParams lp = (LayoutParams) view.getLayoutParams(); if (!lp.isNestedScrollAccepted()) { continue; } final Behavior viewBehavior = lp.getBehavior(); if (viewBehavior != null) { handled |= viewBehavior.onNestedFling(this, view, target, velocityX, velocityY, consumed); } } if (handled) { dispatchOnDependentViewChanged(true); } return handled; }
以前的观念中,当子控件不能处理相关事件时会返回false,交由上级处理,而FloatingActionButton则不是,它是调用父控件中相应的方法,然后父控件遍历子类并最终调用我们的实现。我们反过来想也会知道,RecyclerView是没法调用我们的Behavior实现的,通过父控件来调用才是高明之法。
同时我们也应该知道,FloatingActionButton(archor的View)的父控件必须为CoordinatorLayout,不能中间套上LinearLayout或者其他ViewGroup类的实现,因为他们并没有相应的实现,不然会发生Could not find CoordinatorLayout descendant view with id ……的错误。对于被archor的View则没有要求,从NestedScrollingChildHelper对于父控件的赋值可以看出:
//NestedScrollingChildHelper的startNestedScroll方法部分代码if (isNestedScrollingEnabled()) { ViewParent p = mView.getParent(); View child = mView; while (p != null) { if (ViewParentCompat.onStartNestedScroll(p, child, mView, axes)) { mNestedScrollingParent = p; ViewParentCompat.onNestedScrollAccepted(p, child, mView, axes); return true; } if (p instanceof View) { child = (View) p; } p = p.getParent(); } }
ViewParentCompat.onStartNestedScroll(p, child, mView, axes)会判断p是否是NestedScrollingParent的实例。代码如下:
//ViewParentCompat方类中的方法@Override public boolean onStartNestedScroll(ViewParent parent, View child, View target, int nestedScrollAxes) { if (parent instanceof NestedScrollingParent) { return ((NestedScrollingParent) parent).onStartNestedScroll(child, target, nestedScrollAxes); } return false; }
所以当父控件为LinearLayout或者RelativeLayout或其他非CoordinatorLayout时会返回false,接着访问其父控件,直到碰到CoordinatorLayout,否则返回false。所以对于被archor的view具体父控件没有什么要求,只要最终是CoordinatorLayout就行。
- CoordinatorLayout的滑动事件处理机制
- CoordinatorLayout 的滑动处理
- CoordinatorLayout+ViewPager+SwipeRefreshLayout滑动事件冲突的处理
- Android的事件处理机制和滑动
- Android的事件处理机制和滑动
- Android平台的事件处理机制和手指滑动例子
- Android平台的事件处理机制和手指滑动例子
- Android平台的事件处理机制和手指滑动例子
- Android平台的事件处理机制和手指滑动例子
- Android平台的事件处理机制和手指滑动例子
- Android事件分发机制及滑动冲突处理的几篇博文
- android 滑动事件冲突解决 Touch事件处理机制
- android 滑动事件冲突解决 Touch事件处理机制
- android 滑动事件冲突解决 Touch事件处理机制
- android 滑动事件冲突解决 Touch事件处理机制
- android 滑动事件冲突解决 Touch事件处理机制
- android 滑动事件冲突解决 Touch事件处理机制
- android 滑动事件冲突解决 Touch事件处理机制
- Material Design之TextInputLayout使用示例
- Java基础之容器综述篇
- View的绘制流程
- 小学生算数测试
- Markdown编辑器的使用
- CoordinatorLayout的滑动事件处理机制
- Appium——驱动和常用功能的封装
- C#打印GroupBox控件区域
- Java提高之优化篇(待完成)
- hashMap实现原理
- POJ 2452 Sticks Problem(RMQ+二分)
- SQLserver SSIS的问题 Integration Services项目 ETL 无法保存包的问题
- redis 消息订阅和发布
- Groovy 之 Closure