Android嵌套滑动和NestedScrollView
问题分析
嵌套滑动一直是Android中比较棘手的问题, 根本原因是Android的事件分发机制导致的.不了解事件分发机制的同学可以先看看一点见解: Android事件分发机制, 导致嵌套滑动难处理的关键原因在于当子控件消费了事件, 那么父控件就不会再有机会处理这个事件了, 所以一旦内部的滑动控件消费了滑动操作, 外部的滑动控件就再也没机会响应这个滑动操作了
嵌套滑动
不过这个问题终于在LOLLIPOP(SDK21)之后终于有了官方的解决方法, 就是嵌套滑动机制. 在分析具体的代码逻辑之前, 下面先简单介绍下嵌套滑动的一些基本知识.
嵌套滑动机制可以理解为一个约定, 原生的支持嵌套滑动的控件都是依据这个约定来实现嵌套滑动的, 例如CoordinatorLayout, 所以如果你自定义的控件也遵守这个约定, 那么就可以跟原生的控件进行嵌套滑动了
基本原理
嵌套滑动的基本原理是在子控件滑动一段距离的请求时,先询问父控件是否要滑动,如果滑动了父控件就通知子控件它消耗了一部分滑动距离,子控件就只处理剩下的滑动距离,然后子控件滑动完毕后把剩余的滑动距离传给父控件。
版本区别
SDK21之后
嵌套滑动的相关逻辑作为普通方法写进了View
和ViewGroup
类,例如dispatchNestedScroll()
SDK21之前
官方在android.support.v4
兼容包中提供了两个接口NestedScrollingChild
和NestedScrollingParent
,还有两个辅助类NestedScrollingChildHelper
和NestedScrollingParentHelper
来帮助控件实现嵌套滑动.
这个兼容的原理很简单
两个接口NestedScrollingChild
和NestedScrollingParent
分别定义上面提到的View和ViewParent新增的普通方法
在代码中是通过ViewCompat
和ViewParentCompat
类来判断调用的方法是控件自有的方法, 还是接口的方法
如果版本是SDK21之前, 那么就会判断控件是否实现了接口, 然后调用接口的方法, 如果是SDK21之后, 那么就可以直接调用对应的方法.
接下来通过分析相对简单的支持嵌套滑动的容器NestedScrollView
来了解下怎样主动调起嵌套滑动的方法, 以及嵌套滑动的具体逻辑.
相关方法
NestedScrollingChild
startNestedScroll
: 起始方法, 主要作用是找到接收滑动距离信息的外控件.
dispatchNestedPreScroll
: 在内控件处理滑动前把滑动信息分发给外控件.
dispatchNestedScroll
: 在内控件处理完滑动后把剩下的滑动距离信息分发给外控件.
stopNestedScroll
: 结束方法, 主要作用就是清空嵌套滑动的相关状态
setNestedScrollingEnabled
和isNestedScrollingEnabled
: 一对get&set方法, 用来判断控件是否支持嵌套滑动.
dispatchNestedPreFling
和dispatchNestedFling
: 跟Scroll的对应方法作用类似, 不过分发的不是滑动信息而是Fling信息.(这个Fling好难翻译.. =。=)本文主要关注滑动的处理, 所以后续不分析这两个方法.
NestedScrollingParent
因为内控件是发起者, 所以外控件的大部分方法都是被内控件的对应方法回调的.
onStartNestedScroll
: 对应startNestedScroll
, 内控件通过调用外控件的这个方法来确定外控件是否接收滑动信息.
onNestedScrollAccepted
: 当外控件确定接收滑动信息后该方法被回调, 可以让外控件针对嵌套滑动做一些前期工作.
onNestedPreScroll
: 关键方法, 接收内控件处理滑动前的滑动距离信息, 在这里外控件可以优先响应滑动操作, 消耗部分或者全部滑动距离.
onNestedScroll
: 关键方法, 接收内控件处理完滑动后的滑动距离信息, 在这里外控件可以选择是否处理剩余的滑动距离.
onStopNestedScroll
: 对应stopNestedScroll
, 用来做一些收尾工作.
getNestedScrollAxes
: 返回嵌套滑动的方向, 区分横向滑动和竖向滑动, 作用不大
onNestedPreFling
和onNestedFling : 同上略
从NestedScrollView看嵌套机制
更多相关文章
- android中使用httpclient方法获得网页内容并对json对象解析
- Android Studio3.0开发JNI流程------在Android原程序添加自己类
- 利用Android的Matrix类实现J2ME的drawRegion的镜像方法
- 一个非常好用的自定义圆形控件
- Systrace 分析性能工具使用方法详解
- 简单的Android ROM制作方法:创建刷机包 备份ROM
- ScrollView中若嵌套有滑动的控件(如:WebView,ListView或GridView)
- Android原生Switch控件滑块thumb卡住问题的解决方法