【Flutter】小说阅读器改版 (五)—— 整合ScrollActivity

1,691 阅读3分钟

「这是我参与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处理即可;

    同时记得更新一下目标位置,这样,所需的功能就基本实现了:

    按照这个思路,简单实现一下:

    image.png

    image.png

    对于AnimationController这块,有个小优化点:在计算AnimateTo方法的目标值的时候,可以根据当前位置和目标位置算出方向,进而修改传给animateTo的目标值,这样,无论当前位置是否在手势位置前后,都可以正常展示动画到手势的位置;

    image.png 当然,tick 方法中对于边界的判断,也跟上面同理,根据方向判断;

    image.png

    而 calTargetDx 计算当前目标值的时候,需要注意一下,如果当前page值为整数,需要将page值减1,好将目标指向上一页上面;

  • cancel 、end 、 dispose 方法

    image.png

    所做的事也就是终止动画,停止调用而已:

  • 其他部分

    image.png

    image.png

    image.png

    由于动画的存在,使得即使drag事件并为执行调用,也有可能更新position信息;

    所以在这里加一些拦截判断,让动画执行过程中,不再发送通知信息(或许应该将事件转换为对应通知的detail信息?比如说DragUpdateDetails这种)

结尾

现在对手势进行了区分,再设置上 PageScrollPhysics(),看下效果:

修改后.gif

还剩最后一小点:

在小米阅读上面,松开手指后,在恢复动画结束前,手势是不会接受或生效的;

而现在,即使动画没结束,手势操作还是会生效,中断掉恢复动画;那再实现下这个效果,基本就没有任何问题了