嵌套滑动 – NestedScrollView

本文得配合 :
事件分发浅析 – 仿京东首页二级联动 + 事件分发详解 食用。

事件分发与问题

事件分发详解:
juejin.cn/post/697614…

事件分发,是自上而下的:activity -> viewgroup -> view
事件消费,是从下往上的:view -> viewgroup -> activity

问题:
当需要实现这样的嵌套滑动的时候。事件冲突常规解决方案有两种:内部拦截、外部拦截。
但是不管什么样的解决方案,(当头部还有能滑动的时候,父亲消费,让头部先滑动。否则儿子消费,下面滑动)。
都不能解决一次滑动事件(一个Down – 多个Move,前面的Move滑父亲。但是后面的Move父亲滑完了,得滑儿子),即让父亲消费又让儿子消费。(也就是滑到头,得抬手在滑动一次,才能滑动儿子)

444.gif

NestedScrollView

因为无法将一次事件中的Move,即分发给父亲,又分发给儿子。这样的嵌套滑动,谷歌在Material Design给了一个NestedScrollView来解决嵌套滑动。

NestedScrollView 分为 NestedScrollingParent 和 NestedScrollingChild

得同时实现NestedScrollingParent和NestedScrollingChild才能嵌套滑动

在需要嵌套滑动的地方,如果解析到实现了儿子NestedScrollingChild的控件,会向上遍历父亲树,直到遍历到实现了父亲NestedScrollingParent的控件,然后绑定(还会继续向上找,因为可能有多层嵌套)。如果没找到父亲,那就不支持嵌套滑动。

在处理滚动事件的时候,都是由儿子发起请求,然后父亲接收,所以儿子都是dispatch、start这样的,父亲都是onXXX

总结:孔融让梨
孔融有一个梨(事件),可孔融比较孝顺,所以:
1.孔融 dispatchNestedPreScroll 询问父亲吃不吃 –> 父亲:1.吃完(事件结束) 2. 咬一口,还有剩余
2.还有剩余,孔融再吃 1.吃完(事件结束) 2. 咬一口,还有剩余
3.还有剩余,孔融 dispatchNestedScroll 询问父亲吃不吃 –> 父亲:1.吃完(事件结束) 2. 咬一口,还有剩余
4.还有剩余孔融吃完。

image.png

初始化阶段:儿子 StartNestedScroll 向上寻找父亲并绑定。(起点其实是儿子的onTouchEvent的Down)
预滚动阶段:儿子boolean dispatchNestedPreScroll第一次询问父亲是否消费,父亲onNestedPreScroll接收处理事件 (起点其实是儿子的onTouchEvent的Move)
滚动阶段:儿子boolean dispatchNestedScroll第二次询问父亲是否消费,父亲onNestedScroll接收处理事件

NestedScrollingChild

NestedScrollingChild与NestedScrollingParent是接口interface。

注释已经很清楚了。
image.png

NestedScrollingChild 与 NestedScrollingChild2

差别就是NestedScrollingChild2多了一个int type。这个Type代表滑动的类型,一共有两种类型,Touch和fling 手滑的还是惯性

image.png

NestedScrollingParent

NestedScrollingParent没啥好说的,跟Child一样

image.png

NestedScrollingChildHelper 与 NestedScrollingParentHelper

帮助类,开始和结束可以直接调用helper里的方法,省的自己写。(StartNestedScroll、onStopNestedScroll等等)
自己写的主要就是中间 预滚动阶段、滚动阶段(dispatchNestedPreScroll、onNestedPreScroll等)。

自己不实现的方法全丢给NestedScrollingChildHelper,然后只实现自己需要的
image.png
image.png

image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享