????????這個問題應該出現很久了,之前的組件WillPopScope用的好好的,flutter做優化打算“軟性”處理禁用返回手勢,出了PopScope,這個組件也能處理在安卓設備上的左滑返回事件。但是iOS上面左滑返回手勢禁用,一直無效。
當然之前一直在使用Navigator動態路由的方式的話是不影響的。
Navigator.push(context,MaterialPageRoute(builder: (context) =>FullScreenImagePage(images: [imagePath]),),);
????????但是對于靜態路由和一些其他三方的路由(fluro,go_route,getx(這個在版本4.7.2中已修復))封裝組件就會有影響。
那我們看下具體為什么會出現這種問題?
????????首先我們看PopScope的內部實現是接口實現了PopEntry的一個ValueNotifier ?canPopNotifier來控制內部的返回手勢是否可用。
ModelRoute注冊該事件,然后在這個抽象類中有統一的返回手勢判斷競技場邏輯:
到此暫告一段落。
????????上面我們說Navigator的動態路由方式沒問題,那么就看下他的處理和其他的路由方式的差別:MaterialPageRoute的混入MaterialRouteTransitionMixin如下:
CupertinoPageRoute的混入CupertinoRouteTransitionMixin如下(我只截取了最有介紹的部分,想看的可以自己去文件里面看,路徑我已經截出來了):
????????????????
????????Flutter最近也一直在優化Cupertinao的組件庫,上面的CupertinoPageRoute就是iOS的路由處理,可以看到差異很明顯,頁面page(這篇文章主要介紹page形式)形式的代碼有自定義實現了手勢_CupertinoBackGestureDetector,他通過參數方法enabledCallback來動態獲取左滑手勢是否有效。它的內部實現如下:
????????可以看到enabledCallback的來源是route.popGestureEnabled,到此就是最終的位置了。通過斷點可以看到,(前提是二級頁面設置了PopScope的canPop為false)當Navigator的動態路由方式的時候,此處是false,左滑返回無效,一般其他的方式路由來的此處是true,左滑返回可以。
????????由此而來,問題就出現在了route的popGestureEnabled上面,我們可以聚焦在此處,點擊尋根,可以追溯到ModalRoute的popGestureEnabled(上面已截圖,本文第三張圖),問題就出在了第三個判斷中的popDisposition==RoutePopDisposition.doNotPop上面,再往上看popDisposition的來源如下:
????????問題的原因應當是此處路由在iOS設備中路由的轉換導致canPopNotifier的變更出現的問題。
下面我們參考看下Get的PageRoute解決關鍵代碼:
????????可以看到GetX的最新調整將路由的手勢帶出來,判斷處理 解決此次Flutter的iOS PopScope問題。(當然這只是表象比較明顯的位置,具體詳細大家有興趣可以自行點進去再細致研究)