前言
项目中需要实现一个支持手势拖拽控件,控件内部包含ViewPager+RecycleView。大概记录下最后解决问题的过程
1.讨论,找资料
拿到出需求后,首先脑补了下场景,马上拉着小组成员头脑风暴一番,梳理出来几种可能满足的方案
1.在SmartRefresh 提供的类淘宝二楼功能上进行二次开发
2.自定义ViewGroup,或者基于布局,对需要上下滑动的View做手势处理
3.根据BottomSheet或者 BottomSheetFragmentDialog二次开发。
从难易程度上直观看起来说:BottomSheet->SmartRefresh->自定义ViewGroup,或者基于布局
eg:smartRefresh的二楼和需求出入较大,需求是上层View可拖动,下层View固定。
2.实现方案调研
BottomSheet 是官方前两年提供的很成熟控件,毫不费力就把BottomSheet相关配置引入
error:在项目中进行展示直接崩溃
网上找了一圈类似错误的索引。又检查了下自己写的代码发现自己的布局写成了androidx.constraintlayout.widget.ConstraintLayout 。而正确应该是要写成
androidx.coordinatorlayout.widget.CoordinatorLayout。
error :忘记定义app:layout_behavior
之后熟悉了BottomSheetBehavior相关Api梳理出来几个比较好用的配置
1.app:behavior_peekHeight 设置折叠后的高度
2.BottomSheetBehavior.state 设置BottomSheet初始状态,共7种状态的
3.BottomSheetBehavior.setBottomSheetCallback( 回调函数) 状态回调,偏移量回调
4. BottomSheetBehavior.expandedOffset
官方api解释 :解决距离顶部的偏移量
- determines the top offset of the BottomSheet in the {@link #STATE_EXPANDED} state when
- fitsToContent is false. The default value is 0, which results in the sheet matching the
- parent’s top.
完成上面的配置后,让设计人员看了下效果还挺满意。
滑动时候发现刷新问题失效了。打眼一看就明白肯定是BottomSheet的滑动事件和RecycleView的滑动事件冲突导致的。网上搜索下类似问题,还挺多,心中窃喜。
下载资源跑了下,确实解决了问题。紧接着将源码导入自己的项目后,发现ViewPagerUtils的layoutParams.position 报错,看了下原因:
自己项目中使用Androidx依赖,gitHub资源库还是使用Support.v4依赖。而最新的A呢droidx依赖库中的ViewPager.layoutParams.position 非公开。无法访问了
自己项目两年前已经迁移到AndroidX了。总不能走倒退路。将依赖回退到V4的支持库吧 关闭AndroidX依赖
梳理下解决方案:
1.回退到早期依赖私用支持库中的v4.ViewPager
2.拷贝v4.ViewPager,及相关类。
3.改变资源库依赖方式,减少影响范围,跟着报错进行解决
4.寻找替代方案: 采用反射方式获取非public 属性值跳过的无法访问限制。
5.阅读BottomSheet源码,copy一份源码进行改动
对方案1,2,3进行验证,发现需要对项目进行调整,影响范围比较广,而且小组内均不同意禁用AndroidX 相关依赖。
方案4.在不更改依赖情况下影响较小。发现确实可以拿到类中的方法和具体的属性,但是提取属性中的值时崩溃。采用反射方案后期也需要较多的维护,如果哪天position的属性换成其他值了。还需要进行多版本兼容。
方案5是终极解决方案,屡试不爽。花费的时间也无法评估全靠个人经验。(非必要,不会二次更改源码)
总结下:
目前对于冲突原因也知道,(因为BottomSheet只对第一个可以滑动的控件进行事件分发,如果有多个可以滑动的控件就会有滑动问题),也有网友提供的实例代码。没有理由解决不了
早期也总结过关于 Android 嵌套布局简析
还是对源码比较紧张啊!!!
之后翻阅 ViewPagerBottomSheet 的Issue 问题时候看到有网友说在AndroidX 中无法使用该库,紧接着看到贴出来一个解决方案
解决方案: 只需集成BottomSheetBehavior,重写onStartNestedScroll(),重新给nestedScrollingChildRef 软引用赋值。就可以完美解决了
原文链接
其他问题
以上只是记录下遇到问题的解决思路,如果按照上述问题还有冲突。本文在解决完嵌套Viewpager无法滚动问题后,遇到RecycleView 滑动到底部后,向下滑动会连带BottomShee一起滑动问题。看了源码事件拦截部分,发现在BottomSheet 拖动状态,直接消费了事件不传递给子类。这里引用另一篇文章进行方案:
解决BottomSheet滑动冲突问题 ,在BottomSheet 滑动回调中强制更改 STATE_DRAGGING 为 STATE_EXPANDED状态来规避事件分发引起的滑动冲突。
引用
google BottomSheet BottomSheetBehavior+ViewPager+RecyclerView引起的滑动冲突事件解决
重写onStartNestedScroll