浅谈CoordinatorLayout
写在前面
最近这一周空余的时间比较多,然后去重构了一个公司项目里的一个个人中心的页面,原来使用了ListView
再加上addHead
的方式,然后动态的去控制Head
的高度去实现嵌套滑动的效果,因为我的模拟器没有跑起来,所以也没有去录下个GIF来,因为这篇主要说一下CoordinatorLayout
的处理嵌套滑动的原理,没有效果图也影响不大。
开始吧
先写出来点大纲吧:
- 为什么要有
CoordinatorLayout
CoordinatorLayout
是怎么实现嵌套滑动的事件分发的AppBarLayout
的一些东西
为什么要有CoordinatorLayout
先来回想一下Android
系统的事件分发有什么不足的地方,就是一个view
消费了事件,与此同时,其他的view
的没有机会去接触到这个事件了。也就是在一个事件的某一时刻,有且只有一个View
去相应这个事件。那么当我们要去做一些嵌套滑动的时候,就会有一些不方便。例如需要一个View
跟随另一个View
滑动,一般就是一个CallBack
进行滑动状态的回调。CoordinatorLayout
就可以比较优雅的处理这种事件。
CoordinatorLayout
是怎么实现嵌套滑动的事件分发的
先说一下两个接口吧,NestedScrollingParent
和NestedScrollingChild
,这两个接口看名字就比较容易理解他们的作用,就是一个给嵌套滑动的parent实现的,一个是给child实现,在现在的组件中,只有CoordinatorLayout
实现了parent,所以下面说到parent就理解成CoordinatorLayout
就OK啦,而child这个接口其实方法已经在View
这个类里面帮我们实现好了,也就是说想要去成为一个可以嵌套滑动的child,仅仅去实现这个child接口就OK了,其他的View
已经帮你写完了。下面还是以RecycleView
为例子,它是实现了这个child的接口,还是回到情景里面说吧,说一下到底是怎么传递事件的。
- 在
ReclceView
上down ->parent.onStartNestedScroll
->遍历有Behavior
的直接子view ->child的Behavior.onStartNestedScroll
。
这里说一下onStartNestedScroll
这个方法是有boolean的返回值,true
的意思是要去处理这个事件,同时还会去调用parent.onNestedScrollAccepted
-> 遍历有Behavior
的直接子view ->child的Behavior.onNestedScrollAccepted
.这个方法里面可以做一些view配置的初始化。如果不需要当然可以不去重写。 - 在
RecycleView
上move ->dispatchNestedPreScroll
(也是child这个接口里面的)->parent.onNestedPreScroll
-> 遍历有Behavior
的直接子view ->child的Behavior.onNestedPreScroll
,同时之后还有一个流程也是在move的时候触发的 ->dispatchNestedScroll
(也是child这个接口里面的) ->parent.onNestedScroll
-> 遍历有Behavior
的直接子view ->child的Behavior.onNestedScroll
.。这两个的主要区别的pre那个方法里面可以去处理消费了多少的滑动距离,比如手指滑动了12px,你可以选择把consumed[1]赋值为2,那么head就移动(消费)了2px,剩下的10px就给了下面的recycleview,而在onNestedScroll
方法中还有机会去已经消费的和没有消费的距离再进行一次处理。 - 在
RecycleView
上面up ->stopNestedScroll
(也是child这个接口里面的) ->parent.onStopNestedScroll
-> 遍历有Behavior
的直接子view ->child的Behavior.onStopNestedScroll
。 - 还有两个关于
Fling
的方法,就不说了,一个套路。
还有就是再说一下CoordinatorLayout
的onInterceptTouchEvent
和onTouchEvent
,这里贴一下代码吧
|
|
可以看出,每个直接的childview都会接受到拦截事件,即使你的手势不是在这个child上面触发的。
- 还有个方法就是
layoutDependsOn
这个方法是在哪里调用的,这个是在onpredraw的时候就调用了,也就是没显示之前就已经开始准备各个view直接的依赖关系。当然内部实现也是在parent里面去便利child来实现的,也就只有parent可以获取到所有的child。
AppBarLayout
的一些东西
我觉得AppBarLayout
这个组件还是十分重要的,特别是里面的两个Behavior
的实现,给了我们很好的参考的例子。具体的还是去看源码吧,太多了要说也是再开一篇。