博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android NestedScrolling解决滑动冲突问题(2) - fling问题与NestedScroll++
阅读量:6207 次
发布时间:2019-06-21

本文共 3217 字,大约阅读时间需要 10 分钟。

滑动的处理

前一篇文章中分析了解决滑动冲突问题的 NestedScroll 接口,也给出了解决此类问题的一般性方案:

NestedScrollingChild侧

NestedScrollingChild(后面简称NC)处理MotionEvent(一般在onTouchEvent中,如果是ViewGroup还要注意onInterceptTouchEvent的处理,拦截滑动相关的MotionEvent事件),分析用户滑动操作。

在滑动开始时,调用startNestedScroll找到联动此次滑动的NestedScrollingParent(后面简称NP)。

对于每次用户交互产生的滑动距离,先调用dispatchNestedPreScroll,询问联动NP是否预先处理此滑动,如果NP预先处理了,会给出消耗掉的滑动距离。

对于NP预处理剩下的滑动距离,NC决定自己是否处理部分或者全部距离(自己的滑动)。

如果NC自己滚动之后,还剩下部分滑动距离,则调用dispatchNestedScroll让NP自行选择是否处理最后剩下的这些滑动距离。

用户交互停止滑动,调用stopNestedScroll通知NC停止滑动联动。

NestedScrollingParent侧

onStartNestedScroll中,决定是否与此次NC发起的滑动请求联动,如果决定联动,返回true,否则返回false。返回true之后,会收到onNestedScrollAccepted回调,表示NC同意与其联动,可以开始做初始化操作了;返回false之后,后面的NC联动操作不会通知此NestedScrollingParent(不会收到后续的onNestedPreScrollonNestedScrollonStopNestedScroll等)。

onNestedPreScroll中,决定是否预处理滑动单步,并给出消耗掉的滑动距离(不处理则为0)。

onNestedScroll中,决定是否消耗NC处理剩下的滑动距离。

onStopNestedScroll做联动滑动收尾工作。

通过NC与NP的配合,可以做到很多复杂的滑动操作。只要分析了界面上外层视图与内层视图在滑动时的交互逻辑,就可以利用这两个接口实现。

fling的处理

相对于滑动操作,还有一个fling操作,也叫猛划,指用户拖住UI元素快速滑动之后抬手,这时会有一个fling事件,一般的操作逻辑是UI元素在抬手之后按照初始速度做减速运动。

NestedScroll 接口也提供了API处理fling事件,在NestedScrollingChilddispatchNestedPreFling通知NP预处理fling事件,dispatchNestedFling通知NP后处理fling事件。

boolean dispatchNestedPreFling(float velocityX, float velocityY);boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed);复制代码

NestedScrollingParent中对应的接口为onNestedPreFlingonNestedFling

boolean onNestedPreFling(@NonNull View target, float velocityX, float velocityY);boolean onNestedFling(@NonNull View target, float velocityX, float velocityY, boolean consumed);复制代码

通过这几个接口,可以让NC和NP各自对fling事件做出反应,但是不能像滑动事件一样联动。即不能先让NP预处理 部分 fling 速度,然后NC处理剩下的 部分 fling速度,再将最后剩下的交给NP继续处理。这种情况下,上层UI元素与下层UI元素缺乏交互,很难做到像滑动操作一样的UI效果(例如fling时先收起上层视图部分内容,再滑动下层视图)。

NestedScroll++

为了解决此问题,在support包 26.0.0-beta2 版本中引入了 NestedScroll 接口的升级版本(后面称为 NestedScroll++ ): NestedScrollingParent2NestedScrollingChild2

NestedScroll++ 接口中,引入了touch type 的概念:对于用户手指触摸拖拽产生的滑动事件type为 ViewCompat.TYPE_TOUCH, fling产生的滑动事件 typeViewCompat.TYPE_NON_TOUCH。滑动接口的相应API中加入了此 type 参数,如onNestedScroll接口改为:

void onNestedScroll(@NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @NestedScrollType int type);复制代码

NestedScroll++ 接口中,对于滑动事件的处理,与 NestedScroll 接口一样,只是API中加入了 type 参数。

而对于fling事件的处理,不再依赖于 dispatchNestedPreFlingdispatchNestedFlingonNestedPreFlingonNestedFling等接口,而是选择使用与滑动事件相同的处理方式,只是 type 不同(为ViewCompat.TYPE_NON_TOUCH)。

相应的交互逻辑改为:

NestedScrollingChild侧

在fling开始时,调用startNestedScroll找到联动此次滑动的NestedScrollingParent(后面简称NP)。

每次刷新视图时,计算当前时间片由fling产生的滑动距离,先调用dispatchNestedPreScroll,询问联动NP是否预先处理此滑动距离,如果NP预先处理了,会给出消耗掉的滑动距离。

对于NP预处理剩下的滑动距离,NC决定自己是否处理部分或者全部距离(自己的滑动)。

如果NC自己滚动之后,还剩下部分滑动距离,则调用dispatchNestedScroll让NP自行选择是否处理最后剩下的这些滑动距离。

用户交互停止滑动,调用stopNestedScroll通知NC停止滑动联动。

NestedScrollingParent侧

onStartNestedScroll中,决定是否与此次NC发起的fling联动请求,如果决定联动,返回 true ,否则返回 false 。返回true之后,会收到onNestedScrollAccepted回掉,表示NC同意与其联动,可以开始做初始化操作了;返回false之后,后面的NC联动操作不会通知此NestedScrollingParent(不会收到后续的onNestedPreScrollonNestedScrollonStopNestedScroll等)。

onNestedPreScroll中,决定是否预处理fling产生的滑动距离,并给出消耗掉的滑动距离(不处理则为0)。

onNestedScroll中,决定是否消耗NC处理剩下的滑动距离。

onStopNestedScroll做联动滑动收尾工作。

转载于:https://juejin.im/post/5c08e7b8f265da61193ba2f4

你可能感兴趣的文章
angualejs
查看>>
关于工作的选择之软件开发还是软件维护的建议
查看>>
记录每个用户的操作记录(命令)
查看>>
五年后存储会是什么样子
查看>>
sersync+rsync实现实时同步
查看>>
C# 文件操作详解(三)---------Directory类
查看>>
go grpc 深入笔记
查看>>
Oracle EXP/IMP参数详解
查看>>
PHP 正则表达式分割 preg_split 与 split 函数
查看>>
windows清理剪切板
查看>>
mysql索引随记
查看>>
在Brackets中使用jsHint遇到的问题
查看>>
freemarker 分页逻辑
查看>>
关于Pac-Man,你所要了解的 一切
查看>>
分布式配置管理平台Disconf
查看>>
CountDownLatch线程同步辅助
查看>>
Android 多状态加载布局的开发 Tips
查看>>
天津海运[600751]股票
查看>>
pdf 字体和图片抽取
查看>>
mybatis处理集合、循环、数组和in等语句的使用
查看>>