github地址:
(https://github.com/liyuzero/NestedRecyclerView)
示例
1. 已知实现方案
-
AppBarLayout 实现
优:使用简单
劣:1、动画无法衔接,会有停顿 2、上半部分视图会一次加载完毕,会造成两个影响,(1)无法走recyclerView的缓存机制,(2)会使该部分视图的曝光逻辑复杂化
-
RecyclerView嵌套ViewPager嵌套RecyclerView实现
1. 重写外层RecyclerView的dispatchTouch事件分发,以及子RecyclerView的touch事件分发,处理滑动冲突
2. 依照nestedScroll机制,重写内外层RecyclerView的触摸事件
优:可以无停滞滑动,内外层recyclerView可以进行正常的回收、绘制
劣:需要重写内外层RecyclerView,使用不太方便
3. 【本框架采用】只重写外层RecyclerView的事件分发,屏蔽RecyclerView本身的滑动逻辑,自行编写Scroller实现所有滑动逻辑
优:可以无停滞滑动,内外层recyclerView可以进行正常的回收、绘制,只有最外层RecyclerView需要使用特定类
劣:因为是外层RecyclerView实现所有触摸事件分发,所以横滑效果不能完全媲美原版,但是有办法弥补
2. 写该框架的原因
- 目前没找到成熟的开源嵌套框架,都有各自的问题,基本都是思路性的开源代码,基本都需要重写内外RecyclerView,使用不方便。没有一个可以稳定商用的通用框架,所以,自行实现了嵌套逻辑,并在产品中使用,有问题也能即时修改。
3. 原理
具体原理可分为三部分,1、将触摸事件组(按下到抬起)进行分类处理,并屏蔽RecyclerView自身的滑动, 2、在用户手指抬起时触发fling滑动,3、编写Scroller整合内外RecyclerView滑动,使其有连续性
- 滑动事件分组和屏蔽部分
- 1、触摸事件处理部分,该部分将每组触摸事件(从 down 到 up)类型分为两种,一是水平滑动
SCROLL_HOR
,二是竖直滑动SCROLL_VER
,屏蔽RecyclerView自身滑动部分简略概括为:onInterceptTouchEvent
,依据事件组类型进行拦截,onTouchEvent
直接返回true
if (mCurScrollState == SCROLL_VER) {
//竖直滑动时,对Recycler内容进行滑动,该方法处理了内外RecyclerView滑动切换逻辑
scrollVer(ev, offsetY);
return true;
} else if (mCurScrollState == SCROLL_HOR) {
// 水平滑动时,外层RecyclerView 不拦截触摸事件,该事件将会传给child
return false;
} else if (mCurScrollState == SCROLL_NONE) {
//触摸事件组分类
float dx = Math.abs(curX - mDownX);
float dy = Math.abs(curY - mDownY);
if (dx <= 0.01f && dy < 0.01f) {
return false;
} else {
if (Math.abs