问题
在 iPad 上,使用 Flutter 的 TextField()
控件写的输入框,iPad 上自带的虚拟键盘可以正常输入,但是当通过蓝牙连接了一个键盘外设(物理键盘)时,输入却没有反应,更诡异的是,iPad 自带的备忘录、短信、搜索框等等却能够得到输入的内容。
所以,为什么 Flutter 的 TextField 不能响应蓝牙键盘(物理键盘)的输入?
又去 Google、Github 的海洋浪了一圈,咩都冇~
(Github 的 Flutter/issues 也有人遇到同样的问题,但也没有具体的解决方案,据说 Flutter 官方已经解决了,在 master 分支上,还没上 stable 分支,那再等等看?)
不存在的,老板不允许,产品不允许、主管不允许...
发现:
在不断的尝试中发现,新建的项目(flutter create XXX_demo),HomePage()
中新增一个 TextField()
控件却可以正常输入。
下图就是连接键盘可正常输入的样子
所以问题的范围缩小到 iOS 启动 Flutter引擎的是不是少了哪些配置?
带着问题,我去看看了 iOS 原生端启动 Flutter 的时候干了什么
默认的引擎初始化:
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// storyboard 上绑定的 FlutterViewController
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
我采用的引擎初始化方式:
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
/// 自己创建 Engine 和 FlutterViewController 绑定
let flutterEngine : FlutterEngine = FlutterEngine.init(name: "flutter_native", project: nil)
GeneratedPluginRegistrant.register(with: flutterEngine)
window = UIWindow.init(frame: UIScreen.main.bounds)
// MainVC 继承于 FlutterViewController
let flutterController = MainViewController.init(engine: flutterEngine, nibName: nil, bundle: nil)
window?.rootViewController = flutterController
window?.makeKeyAndVisible()
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
对比结果:
1.默认方式,使用的是 FlutterViewController 自带的 engine
2.我采用的方式是自己创建了一个 FlutterEngine,并在 FlutterViewController.init 的时候传进去,导致了 FlutterViewController 使用的是外部传入的 engine。
解决方案
经过不断的试错,终于拨开云雾见青天~
方案一:
不需要使用 FlutterViewController
的实例对象,比如:其他需要桥接的内容,自定义 channel 等等操作的话,可以直接使用默认的方式,即 storyboard 绑定 FlutterViewController
,代码在上面。
方案二:
需要使用 FlutterViewController
,可以不再创建新引擎,使用 FlutterVC 自带的引擎即可.
不一样的点是:
1. 创建 flutterVC 不接受外部 engine,否则会覆盖它自带的
2. GeneratedPluginRegistrant 注册的也是 flutterVC 的插件通道
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let flutterController = MainViewController.init()
GeneratedPluginRegistrant.register(with: flutterController.pluginRegistry())
window = UIWindow.init(frame: UIScreen.main.bounds)
window?.rootViewController = flutterController
window?.makeKeyAndVisible()
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
结语
到这里,把我的问题解决了。但是整个过程下来还是有点懵逼的,还有很多疑问,比如说:
- 为什么自己在外部创建的
FlutterEngine
和FlutterViewController
里自带的 engine 有什么区别? - 或许不是 engine 的问题,而是引擎启动的时机问题?
以上是我的解决方案,有错误,讲的不对的地方,或许各位大佬有更好的解决方案,欢迎在评论区指出,我会虚心接受! 谢谢~