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

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

 

我们看到这个页面上有几个个可以滑动的控件,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

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

(父接口)

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

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

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

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

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

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

NestedScrollView是实现了该接口的。

CoordinatorLayout也是实现了该接口的

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值