「这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战」。
前言
在前一篇文章中,通过自定义ScrollActivity的方式基本实现了需求,但是由于没有处理DragActivity,所以DragActivity和自定义的心ScrollActivity在手势方面处于冲突状态;
虽说仅仅从UI表现层面来说好像没什么太大问题,但是毕竟是个问题;
设计
既然现在存在的问题是跟darg 有冲突,那么我将所有的处理都搬到Drag里面去处理不就行了,
回顾一下,需要做的事也不多,:
- 创建AnimationController;
- 在合适时机去启动、停止;
- 根据情况将事件分别交给Drag和AnimationController去处理;
而在 ScrollDragController 中,涉及对事件处理的部分也就三个:update、end、cancel;
update方法的入参 DragUpdateDetails 中,就有手势位置信息,这样,所需的手势位置也得知了,启动动画自然也不是问题,将方法分发放在这里就行;
而另外两个方法:end 和 cancel、以及dispose中,也别忘了加上动画的取消;
实现
-
首先来到update方法:
由于所需要处理的手势,只有从左往右滑动,调出上一页的事件,所以如果是从右往左滑动,直接super处理即可;
动画也仅仅需要启动一次,执行完成后,停留位置肯定是手势所在的位置,剩下的都交给super处理即可;
同时记得更新一下目标位置,这样,所需的功能就基本实现了:
按照这个思路,简单实现一下:
对于AnimationController这块,有个小优化点:在计算AnimateTo方法的目标值的时候,可以根据当前位置和目标位置算出方向,进而修改传给animateTo的目标值,这样,无论当前位置是否在手势位置前后,都可以正常展示动画到手势的位置;
当然,tick 方法中对于边界的判断,也跟上面同理,根据方向判断;
而 calTargetDx 计算当前目标值的时候,需要注意一下,如果当前page值为整数,需要将page值减1,好将目标指向上一页上面;
-
cancel 、end 、 dispose 方法
所做的事也就是终止动画,停止调用而已:
-
其他部分
由于动画的存在,使得即使drag事件并为执行调用,也有可能更新position信息;
所以在这里加一些拦截判断,让动画执行过程中,不再发送通知信息(或许应该将事件转换为对应通知的detail信息?比如说DragUpdateDetails这种)
结尾
现在对手势进行了区分,再设置上 PageScrollPhysics(),看下效果:
还剩最后一小点:
在小米阅读上面,松开手指后,在恢复动画结束前,手势是不会接受或生效的;
而现在,即使动画没结束,手势操作还是会生效,中断掉恢复动画;那再实现下这个效果,基本就没有任何问题了