返回
巧用FlutterViewController,化解原生弹窗触碰烦恼**
IOS
2023-11-03 01:51:37
摘要:
原生弹窗与Flutter内容共存时,弹窗触碰事件往往被Flutter响应,导致交互混乱。本文将深入探讨这一问题,并通过剖析FlutterViewController源码,提供一种巧妙的解决方案,让原生弹窗的触碰事件得到正确的处理。
关键词:
正文:
问题
在Flutter应用中,原生弹窗和Flutter内容常常并存,例如在Flutter界面中弹出原生对话框。然而,当用户触碰原生弹窗时,事件会被底层的Flutter内容响应,导致原生弹窗无法正常交互,出现错乱现象。
原因分析:
深入研究FlutterViewController源码,我们发现以下原因:
- FlutterViewController使用
hitTest
方法处理触碰事件。当原生弹窗被点击时,hitTest
方法会优先返回Flutter控件,导致事件被Flutter响应。 - Flutter的事件处理机制遵循冒泡原则,事件会被逐层向上传递,直至被某个控件处理。由于Flutter控件优先获得事件,原生弹窗的事件无法到达底层。
解决方案:
为了解决这个问题,需要让原生弹窗的事件能够正确到达底层,而不被Flutter控件拦截。一种可行的方案是修改FlutterViewController的hitTest
方法:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// 自定义hitTest逻辑,优先返回原生弹窗视图
if ([self.nativePopupView containsPoint:point]) {
return self.nativePopupView;
}
// 否则,按默认逻辑处理
return [super hitTest:point withEvent:event];
}
通过重写hitTest
方法,当原生弹窗视图包含触碰点时,优先返回原生弹窗视图。这样,触碰事件将直接到达原生弹窗,从而解决交互混乱的问题。
代码示例:
以iOS为例,实现自定义hitTest
方法的代码如下:
import Flutter
class MyFlutterViewController: FlutterViewController {
var nativePopupView: UIView?
override func viewDidLoad() {
super.viewDidLoad()
// 初始化原生弹窗视图...
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if nativePopupView?.frame.contains(point) ?? false {
return nativePopupView
}
return super.hitTest(point, with: event)
}
}
其他注意事项:
- 确保原生弹窗视图的层级高于Flutter视图。
- 在原生弹窗关闭后,记得释放对原生弹窗视图的引用,以避免内存泄漏。
总结:
通过修改FlutterViewController的hitTest
方法,我们巧妙地解决了原生弹窗触碰事件被Flutter响应的问题。这种解决方案既优雅又高效,充分利用了FlutterViewController的自定义能力。通过遵循这些步骤,开发人员可以轻松解决交互问题,打造流畅无缝的原生弹窗体验。