在Flutter与iOS混合开发中,当Flutter页面内包含可滚动的组件时,用户在iOS设备上使用手势滚动Flutter组件时,会触发iOS原生的侧滑返回手势,导致用户意外返回上一级页面。本发明提供了一种方法,有效避免了此类手势冲突,确保了Flutter组件和iOS系统之间的无缝交互。
在iOS平台内集成Flutter后,由于iOS和Flutter有各自的手势,当用手势操作Flutter页面时,由于iOS系统机制原因会优先使iOS的手势生效,导致Flutter滑动组件无法滑动,页面返回。
架构及逻辑流程:
为了解决Flutter和iOS返回手势冲突创建了ProxyGestureRecognizer(代理手势),他的作用如下
1、接收 iOS 触摸事件,并传递给 Flutter(cancelsTouchesInView 设置为 NO 即可)。
ProxyGestureRecognizer.cancelsTouchesInView = NO;
2、根据Flutter页面是否能滑动映射成代理手势是否可响应,isWorking 代表Flutter页面滑动状态,isWorking 为YES时代表Flutter页面在滑动,此时代理手势生效,返回手势失效
3、代理手势根据状态去和其他 iOS 侧滑返回手势竞争后续触摸事件的处理权。此方法可设置代理手势优先级大于返回手势。
[popGestureRecognizer requireGestureRecognizerToFail:ProxyGestureRecognizer];
Flutter侧代理手势设置:
class FlutterGestureTracker extends StatelessWidget {
const FlutterGestureTracker({ Key? key, this.child})
: super(key: key);
final Widget? child;
@override
Widget build(BuildContext context) {
return RawGestureDetector(
behavior: HitTestBehavior.translucent,
gestures: {
PointerTracker: GestureRecognizerFactoryWithHandlers<PointerTracker>(
() => PointerTracker(), //constructor
(PointerTracker instance) {
//initializer
instance.onStart = (_)=>BJLog.log('parent onStart');
instance.onUpdate = (_)=>BJLog.log('parent onUpdate');
instance.onEnd = (_)=>BJLog.log('parent onEnd');
},
)
},
child: child,
);
}
}
class PointerTracker extends PanGestureRecognizer {
bool _flutterGestureIsWorking = false;
@override
void rejectGesture(int pointer) {
super.rejectGesture(pointer);
_flutterGestureIsWorking = true;
_notify();
}
@override
void acceptGesture(int pointer) {
super.acceptGesture(pointer);
_flutterGestureIsWorking = false;
_notify();
}
void _notify() {
BoostChannel.instance.sendEventToNative(BoostNavigator.instance.getTopPageInfo()?.uniqueId??'',{"event":"flutterGestureStateChanged","args":{"isWorking":_flutterGestureIsWorking}});
}
}
用FlutterGestureTracker包裹控件即可。