【Flutter】小說閱讀器改版 (六)—— 在動畫播放中攔截手勢

語言: CN / TW / HK

theme: condensed-night-purple

「這是我參與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 如果對攔截方式沒有更好的解決方案,接下來就該去做小說閱讀翻頁動畫部分了;

「其他文章」