关于嵌套滚动机制的一点思索

最近在做折叠式标题栏效果的时候遇到这样一个问题,布局代码如下所示,截取了两个片段,

关于嵌套滚动机制的一点思索_第1张图片

 

关于嵌套滚动机制的一点思索_第2张图片

我们看到这个页面上有几个个可以滑动的控件,AppBarLayout,NestedScrollview不是什么自定义的控件,是谷歌官方推荐的材料设计语言的控件的一种,可以直接在布局里使用,对于RecyclerView大家肯定不陌生,一个展示列表的控件,他跟Listview有很多渊源,这里主要讨论的问题不是他们,所以我们回到正题。这里会扯到Android的事件分发机制,why,我们知道这个界面上至少有两个可以滑动的控件,那么当出现滑动事件的时候,谁来响应?这里我们在来搞清楚几个问题,问题如下:

1.Android里一直在强调事件分发,那么事件分发的对象到底是谁?

答案:Touch事件( 当我们触摸手机屏幕的时候,View或者是ViewGroup将产生Touch事件)

2.Touch事件是怎么体先的,以及什么叫做事件分发?

答案:Touch事件的具体细节被封装成了MotionEvent对象,具体对应down up move cancle这几个事件,产生这些事件以后,系统需要将这些事件分发给一个具体的View去执行,这便有了事件的分发机制。

3.Android的UI界面的组成包括,以及他们的事件传递顺序?

答案:Activity ViewGroup View 以及他们的派生类,基本的传递顺序是Activity->ViewGroup->View

好到此,我们来思考一个这样的问题,当我们的事件分发到具体的View以后,这个事件就会被这个View消耗,ViewGroup将不会再接收此类事件,直到下一次手指按下。但是我们现在的需求想要让子View父View都去响应这个事件。那么有没有解决的办法呢?(有,肯定有,毕竟方法应该在总比困难多!)

这就引出了我们今天想要说的主角,嵌套滚动机制(NestedScrolling),它的出现就是为了弥补这个不足。

那么嵌套滚动机制跟正常的事件分发机制到底有啥区别?

答案:正常的事件分发机制,是父View拦截事件以后,子View将不会再接到事件,而嵌套滚动机制是子View先拿到事件,然后将他的坐标传递给父View,父View会消耗部分事件,然后再将事件还给子View来消耗,从而实现父View跟子View都能响应事件的情况。

嵌套滚动机制的核心在如下两个接口: NestedScrollingChild  NestedScrollingParent

代码如下所示:(子接口)

关于嵌套滚动机制的一点思索_第3张图片

(父接口)

关于嵌套滚动机制的一点思索_第4张图片

我们着重看一下实现后的这几个方法

关于嵌套滚动机制的一点思索_第5张图片

onStartNestedScroll中,我们判断了如果是纵向返回true,这个一般是需要内部的View去传入的,你要是不确定,或者担心内部View编写的不规范,你可以直接return true;

onNestedPreScroll中,我们判断,如果是上滑且顶部控件未完全隐藏,则消耗掉dy,即consumed[1]=dy;如果是下滑且内部View已经无法继续下拉,则消耗掉dy,即consumed[1]=dy,消耗掉的意思,就是自己去执行scrollBy,。

此外,这里还处理了fling,通过onNestedPreFling方法,这个可以根据自己需求定了,当顶部控件显示时,fling可以让顶部控件隐藏或者显示。

那么这样我们就可以理解一个页面上为何子View和父View可以同时响应滑动事件了,想必一定是有控件实现了响应的接口,那么我们何不去看一下呢?

我们发现RecyclerView内部是实现了该接口的,

关于嵌套滚动机制的一点思索_第6张图片

NestedScrollView是实现了该接口的。

关于嵌套滚动机制的一点思索_第7张图片

CoordinatorLayout也是实现了该接口的

关于嵌套滚动机制的一点思索_第8张图片

所以他可以跟头部一块联动滑动。同样要是想要实现类似的效果,该控件就必须实现类似的接口。

 

你可能感兴趣的:(Android学习总结)