嗯,还是之前的路线详情的页面,新增了需求,导致界面结构又发生变化了。
添加了一个途经点的列表,与打点列表并列,可以和横向滑动切换 Tab。
之前写过一篇文章CoordinatorLayout + RecyclerView 处理滑动说的也是这个页面,这里再贴一下当前的 xml 布局:
1 |
|
基于这个布局,为了实现新增需求,改成了如下:
1 |
|
将旧布局中的路线详情 Header 单独抽出个布局,添加到 headerContainer 中。这里使用 NestedScrollView 进行包裹是因为 MyCoordinatorLayout 拦截了 onTouchEvent 始终返回 false,MyCoordinatorLayout 就只能处理自身实现了 NestedScrollingChild2 的 View 了,tabLayout 则是 Tab 栏。
嗯,这样功能是能实现了,但是在这界面进行滑动的时候,总会感觉不流畅,而且在快速滑动的时候,还容易反弹。这是很好理解的,因为 MyCoordinatorLayout 重写 onTouchEvent 并且始终返回 false,可能就会导致事件的传递有问题,造成这种滑动不顺的感觉。
那如果不使用 MyCoordinatorLayout,地图上按钮的点击事件如何传递下去呢?这就得想另外一个法子了。CoordinatorLayout 本身是一个增强型的 FrameLayout,增加了嵌套滑动的处理。所以另一种方式的布局就出来了:
1 |
|
将地图布局直接被 CoordinatorLayout 包裹,弃用 MyCoordinatorLayout。当页面处于非全屏时,设置 mapFakeView 的 isClickable 为 false。那么 AppBarLayout 便不会消费地图上按钮的点击事件,事件就会传递到地图那一层进行处理了。
在使用 CoordinatorLayout + AppBarLayout 时,会有一些滑动抖动的问题,和 AppBarLayout 无法拖动的问题,这些在网上都有案例。所以会有自定义的 AppBarLayout、Behavior:
1 | /** |
但是仍然有一个问题:当点击地图全屏按钮时,隐藏 barLayout 与 viewPager,只剩下 CoordinatorLayout 包裹一层地图。这个时候滑动地图下面可以滑动流畅,但是滑动上面被 AppBarLayout 盖住的一部分(即使不可见)则不流畅。然后监听 AppBarLayout 的 addOnOffsetChangedListener 方法会发现有回调。也就是说,即使 AppBarLayout 即使是 GONE,但是它仍然在消费触摸事件,这很令人费解。但是转念一想,好像也不无道理。CoordinatorLayout 是结合 Behavior 来进行处理嵌套滑动的,说明 Behavior 是具有事件处理能力的,在 Behavior 内没有对 View 是否可见进行控制则显得没那么重要了。这里看到 Behavior 中有一个是否可拖动的 Callback:
1 | /** |
想来 NestAppBarLayout 里设置 canDrag 一直返回 true 是为了解决 AppBarLayout 无法拖动的问题了,所以要解决我现在的问题就很简单了:
1 | private fun compactAppbarNestScroll() { |
当 AppBarLayout 不可见时,当然是不能拖动的了。至此,整个页面的滑动又如丝般顺滑了~