前言
在往期的分享中,小编介绍了如何通过 flutter 自带的 EditableText 实现扫码枪数据源的获取。大致实现如下:
- 扫码枪本质上是一个外接的输入设备。
- 使用 Stack 结合自己的布局控件 childWidget 将 editableText 封装,控制隐藏。可通过监听 onSubmitted 获取扫码枪的输入内容。
痛点问题
回顾 往期分享 痛点问题 :
使用 EditableText 的过程中遇到了系统键盘弹出的问题。我们通过 Edit 的焦点来获取扫码枪的输入。但 EditableText 一旦获取了焦点,内部会调用原生层唤起键盘。
扫码枪触发焦点后,系统键盘自动弹起。这样的失败交互困扰了小编很久。
- 往期分享中的临时方案
之前的处理方式是通过定制化源码的方式,将指定版本内的TextInput.show
手动注释掉。
PS:这是一个笨方法,只能解燃眉之急,输入框和文本,一直都是官方每个版本改动的重点。指定版本不是长久的方案。
如何在不改动源码的方式下,动态控制焦点是否触发键盘弹出?
1.系统键盘弹出的原因
实际上,系统键盘是否弹出,完全是因为 SystemChannels.textInput.invokeMethod<void>('TextInput.show')
的调用,但是我们不可能去每个调用该方法地方去做处理,那么这个方法执行后续,我们有办法拦截吗? 答案当然是有的。
2. 如何拦截 methodChannel
Flutter 的 Framework 层发送信息 TextInput.show 到 Flutter 引擎是通过 MethodChannel, 而我们可以通过重载 WidgetsFlutterBinding 的 createBinaryMessenger 方法来处理Flutter 的 Framework 层通过 MethodChannel 发送的信息。
具体代码如下:
使用 mixin 对 WidgetsFlutterBinding 进行方法重载
mixin TextInputBindingMixin on WidgetsFlutterBinding {
BinaryMessenger createBinaryMessenger() {
return TextInputBinaryMessenger(super.createBinaryMessenger());
}
}
在 main 方法中初始化这个 binding
class TextInputBinding extends WidgetsFlutterBinding with TextInputBindingMixin {
}
void main() {
TextInputBinding();
runApp(const MyApp());
}
自定义 TextInputBinaryMessager 对 methodChannel 进行自定义拦截操作
class TextInputBinaryMessenger extends BinaryMessenger {
TextInputBinaryMessenger(this.origin);
final BinaryMessenger origin;
// Flutter 的 Framework 层发送信息到 Flutter 引擎,会走这个方法
Future<ByteData?>? send(
String channel,
ByteData? message,
) {
//TODO 拦截处理
}
// Flutter 引擎 发送信息到 Flutter 的 Framework 层的回调,无需处理
void setMessageHandler(
String channel,
MessageHandler? handler