【Flutter】小说阅读器改版 (六)—— 在动画播放中拦截手势

「这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战」。

前言

在前面一篇中,还遗留最后一个小问题,当恢复或者确认动画未结束的时候,手势操作可以是可以中断当前动画的,现在这篇就来解决这个问题

设计

  • 由于恢复动画仅仅是通过加上 PageScrollPhysics ,启动模拟器不断改变position的offset来实现的;所以第一步就要暴露出 PageScrollPhysics 的动画播放状态;
  • 暴露出状态后,就可以对状态做个判断,然后允许或者拦截手势事件;

根据上述思路,首先要修改的就是 PageScrollPhysics ,通过controller.isAnimating 方法判断一下是否正在进行动画;

对于接下来的拦截部分,由于ListView的手势事件,是由在 Scrollable 中的 RawGestureDetector 负责驱动的,所以处理一下这块就行;

实现

首先,暴露出播放状态比较简单:

新建一个方法即可:

image.png

至于第二步的事件拦截就有点难搞了;

根据之前的源码分析,包括drag、hold在内的手势操作,都是由放在setCanDrag方法中的 _gestureRecognizers 负责驱动分发的;

那么直接调用setCanDrag(false); 不就完事了么;

在setCanDrag 方法中,replaceGestureRecognizers 负责真正替换recoignizer,但是其有个限制,只允许在layout中调用:

image.png

那么通过调用setCanDrag方法这条路就行不通了;

不过还有个 setIgnorePointer 方法,看上去好像有点用的样子;而且这个方法应用在 IgnorePointer 这个可以用做手势拦截的 widget上,好像也是一条路?

但是 RawGestureDetector 从名字上看好像是个监听器,但其实质是个 widget,其检测手势的方法也是对其自己的Widget进行检测,跟child并无关联;所以这块也行不通……

最后,只能使用最笨的方法,完全复制一个scrollable过来,修改其 _handleDragDown 之类的方法,在前面加个判断播放状态的判断……

这个改动量确实不少,就不贴图了……我看看有没有更好的实现方式~~~

这块是否有更优方案,还待老夫研究一番;

结尾

现在也可以对从右往左的手势加上,完成最终的手势处理;当然处理方式跟从左往右的大同小异,无非对需要操作的页码稍微做下区分即可;

现在看下最终效果,需要的确认和取消动画都没什么问题,动画和drag的过渡衔接也挺顺畅: QQ20211126-204233-HD.gif 如果对拦截方式没有更好的解决方案,接下来就该去做小说阅读翻页动画部分了;

猜你喜欢

转载自juejin.im/post/7034859571193577509