记录一个AppBarLayout的bugfix修复

问题现象: CoordinatorLayout嵌套 上半部分AppBarLayout+下半部分RecyclerView, 对下半部分RecyclerView的显示隐藏做操作(如吟唱recyclerView展示一个ErrorLayout or EmptyLayout, 会导致AppBarLayout区域不再响应滑动, 这个bug较容易忽略, 因为滑动界面上的下半部分立即可以恢复滑动使现象消失.

这个问题是由系统源码导致, 里记录一下原因分析:

从CoordinatorLayout看起:

HeaderBehavior:

AppBarlayout:

lastNestedScrollingChildRef的赋值只有两处,

less 复制代码
@Override
public boolean onStartNestedScroll(
    @NonNull CoordinatorLayout parent,
    @NonNull T child,
    @NonNull View directTargetChild,
    View target,
    int nestedScrollAxes,
    int type) {
  //省略...
  // A new nested scroll has started so clear out the previous ref
  lastNestedScrollingChildRef = null;
  //省略...
  return started;
}

@Override
public void onStopNestedScroll(
    CoordinatorLayout coordinatorLayout, @NonNull T abl, View target, int type) {

  //省略... 
  // Keep a reference to the previous nested scrolling child
  lastNestedScrollingChildRef = new WeakReference<>(target);
}

所以lastNestedScrollingChildRef得含义和名字一样, 是上一次的嵌套滚动view, 如果我们滑动了RecyclerView, 那么这个值就是RecyclerView, 如果此时把RecyclerView隐藏, 再滑动AppBarLayout区域, 就会滑不动了, 因为AppBarLayout中CanDragView中判断RecyclerView isShown()为false.

为什么滑动一下AppBarLayout下面的错误界面或空界面区域就会恢复呢? 因为在View中有如下一段代码:

scss 复制代码
public boolean dispatchTouchEvent(MotionEvent event) {
    //...
    final int actionMasked = event.getActionMasked();
    if (actionMasked == MotionEvent.ACTION_DOWN) {
        // Defensive cleanup for new gesture
        stopNestedScroll();
    }
    //...

由前面源码得知, stopNestedScroll();中会对lastNestedScrollingChildRef重新赋值. 这也是为什么是在 lastNestedScrollingChildRef是在stopNestedScroll();中赋值, 而每次开始滑动是lastNestedScrollingChildRef总是不为空.

至此, AppBarLayout偶现滑不动的原因就清楚了.

相关推荐
爱装代码的小瓶子19 分钟前
【C++与Linux基础】进程间通讯方式:匿名管道
android·c++·后端
兴趣使然HX30 分钟前
Android绘帧流程解析
android
JMchen1231 小时前
Android UDP编程:实现高效实时通信的全面指南
android·经验分享·网络协议·udp·kotlin
黄林晴2 小时前
Android 17 再曝猛料:通知栏和快捷设置终于分家了,这操作等了十年
android
有位神秘人2 小时前
Android获取设备中本地音频
android·音视频
JMchen1232 小时前
Android网络安全实战:从HTTPS到双向认证
android·经验分享·网络协议·安全·web安全·https·kotlin
CS创新实验室2 小时前
Pandas 3 的新功能
android·ide·pandas
ujainu3 小时前
护眼又美观:Flutter + OpenHarmony 鸿蒙记事本一键切换夜间模式(四)
android·flutter·harmonyos
三少爷的鞋3 小时前
为什么我不在 Android ViewModel 中直接处理异常?
android
草莓熊Lotso4 小时前
Linux 文件描述符与重定向实战:从原理到 minishell 实现
android·linux·运维·服务器·数据库·c++·人工智能