CoordinatorLayout滚动回调onNestedFling的入坑及出坑

CoordinatorLayout为我们实现各种现代App动效提供了方便,最普及的用法无非就是CoordinatorLayout/CollapsingToolbarLayout/Toolbar/AppBarLayout的综合使用,但是由CollapsingToolbarLayout及AppBarLayout实现的布局效果有3个很致命的问题:

1.非常明显的没有处理向上滑动时的fling事件

2.上层的CoordinatorLayout继承自ViewGroup,当与AppBarLayout及CollapsingToolbarLayout结合使用时,不能方便的进行页面布局

3.无法实现复杂的自定义效果

虽然对于问题1相关解法网上有很多,但普遍都不甚优雅,需添加较多补丁性质的代码,再加上问题2、3,所以许多时候我们就会偏向依靠自己写CoordinatorLayout中的Behavior来实现需求,搭配使用Behavior中的onDependentViewChanged、onNestedScroll方法理论上来讲可以实现任何我们想要的动效,但如果你的项目中需要依赖onNestedFling来写逻辑的话,恭喜你入坑了。

问题的关键在于几方面:

1.相比于OnScrollListener onNestedScroll的触发频率非常低,在你需要实时获取滚动距离的时候这个回调往往会令你失望

2.当你触发fling事件的时候系统会先运行不定次的onNestedScroll,然后当速度达到阀值时触发onNestedFling,之后onNestedScroll便不会再触发,并且onStopNestedScroll方法会在手指离开屏幕时就触发,并没有回调去触发fling事件的结束,这种触发机制也有可能在一定程度上影响自定义事件的编写,对此SO上有人用ScrollerCompat的方式自己手动获取fling事件的结束,可以解决此问题

3.最重要的,在这种模式下我们想要精确获取滚动距离的话往往会使用computeVerticalScrollOffset或findFirstCompletelyVisibleItemPosition之类的方式,但是实践可知,这两种方式在由onNestedFling触发时反馈滚动距离上存在“延迟”,检验方法可以在触发onNestedFling方法后开启线程,并用while(true)的方式不断获取computeVerticalScrollOffset,可以看到当滑动停止时可滚动view的滚动距离依旧在不断变化,并在稍后的很小一段时间内停止

针对这些问题,我尝试了各种方式去hack它们,终究是不想丢弃CoordinatorLayout这本应强大的布局系统,但事与愿违的是各种回调还不如RecyclerView的OnScrollListener或者自己去写OverScroller、ScrollerCompat手动实时获取滚动距离(OnScrollListener的底层就是OverScroller),或者甚至不如自己去继承viewgroup然后自己去在各种控件的onTouch中做联动处理来的爽快,至少现在看来,CoordinatorLayout/CollapsingToolbarLayout/Toolbar/AppBarLayout结合使用是非常符合MD风格的,但体验和实用性还有待Google做进一步的优化

后面我会自己封装一套类似的东西去增强CoordinatorLayout在获取滚动距离上的短板,并贡献出来,有进展后我会编辑此文章附上地址,感兴趣的读者可以关注此文章

你可能感兴趣的:(CoordinatorLayout滚动回调onNestedFling的入坑及出坑)