1、前言
滑动对于android来说,是一个必不可少;它不复杂,大家都知道在onTouchEvent中,让它滑动就完事了,说它复杂,其嵌套处理复杂;在本系列文章,最终是为了熟悉嵌套滑动机制;对于滑动,分为下面几篇文章来完成解读:
- 滑动基础
- ScrollView滑动源码解读
- NestedScrollView嵌套滑动源码解读
- CoordinatorLayout-AppBarLayout-CollapsingToolbarLayout复杂滑动逻辑源码解读
在本章内,本章从两个嵌套的两个视角来分析
- 子滑动视图视角:涉及NestedScrollingChild3接口以及NestedScrollingChildHelper辅助类
- 父滑动容器视角:涉及NestedScrollingParent3接口以及NestedScrollingParentHelper辅助类
这篇内容分三个小章节
- NestedScrollingChildHelper类
- NestedScrollingParentHelper类
- 实现处理以及调用时机
在这里类的解读是必须的,不然只能死记其调用时机,这里是不建议的;下面会贴一部分源码,在源码中会对代码的一些关键进行注释说明
2、NestedScrollingChildHelper类
嵌套子视图角色;主要功能
- 事件是否需要通知
- 事件通知
类中如下变量:
private ViewParent mNestedScrollingParentTouch; // touch事件接力的父容器
private ViewParent mNestedScrollingParentNonTouch; // 非touch事件接力的父容器
private final View mView; // 当前容器,也是作为嵌套滑动时孩子角色的容器
private boolean mIsNestedScrollingEnabled; // 当前容器是否支持嵌套滑动
private int[] mTempNestedScrollConsumed; // 二维数组,保存x、y消耗的事件长度;减少对象生成的
复制代码
2.1 实例获取
public NestedScrollingChildHelper(@NonNull View view) {
mView = view;
}
复制代码
2.2 嵌套滑动支持
是对嵌套子视图的角色来说的
public void setNestedScrollingEnabled(boolean enabled) {
if (mIsNestedScrollingEnabled) {
ViewCompat.stopNestedScroll(mView); // 兼容模式调用
}
mIsNestedScrollingEnabled = enabled;
}
public boolean isNestedScrollingEnabled() {
return mIsNestedScrollingEnabled;
}
复制代码
2.3 嵌套滑动相关方法
要支持嵌套滑动,那么必须有多个支持嵌套滑动的容器;作为子视图,其需要有通知的一套,因此方法有:
- 父容器的查找、判断
- 通知开始、过程以及结束
2.3.1 嵌套父容器的查找
成员变量mNestedScrollingParentTouch、mNestedScrollingParentNonTouch为父容器缓存变量;其直接设置和获取方法如下
private ViewParent getNestedScrollingParentForType(@NestedScrollType int type) {
switch (type) {
case TYPE_TOUCH:
return mNestedScrollingParentTouch;
case TYPE_NON_TOUCH:
return mNestedScrollingParentNonTouch;
}
return null;
}
private void setNestedScrollingParentForType(@NestedScrollType int type, ViewParent p) {
switch (type) {
case TYPE_TOUCH:
mNestedScrollingParentTouch = p;
break;
case TYPE_NON_TOUCH:
mNestedScrollingParentNonTouch = p;
break;
}
}
复制代码
2.3.2 嵌套父容器的支持判断
public boolean hasNestedScrollingParent() {
return hasNestedScrollingParent(TYPE_TOUCH);
}
public boolean hasNestedScrollingParent(@NestedScrollType int type) {
return getNestedScrollingParentForType(type) != null;
}
复制代码
2.3.3 滑动开始通知
public boolean startNestedScroll(@ScrollAxis int axes, @NestedScrollType int type) {
if (hasNestedScrollingParent(type)) {
return true;
}
if (isNestedScrollingEnabled()) { // 孩子视图支持嵌套滑动,只有支持才会继续执行
ViewParent p = mView.getParent();
View child = mView;
while (p != null) { // 查找的不仅仅直接父容器
// 兼容调用,父容器是否可以作为嵌套父容器角色
if (ViewParentCompat.onStartNestedScroll