目录前言痛点问题如何在不改动源码的方式下,动态控制焦点是否触发键盘弹出?1.系统键盘弹出的原因2. 如何拦截 methodChannel3. 拦截思路扫码库更新前言 在往期的分享中
在往期的分享中,小编介绍了如何通过 Flutter 自带的 EditableText 实现扫码枪数据源的获取。大致实现如下:
回顾 往期分享 痛点问题 :
使用 EditableText 的过程中遇到了系统键盘弹出的问题。我们通过 Edit 的焦点来获取扫码枪的输入。但 EditableText 一旦获取了焦点,内部会调用原生层唤起键盘。
扫码枪触发焦点后,系统键盘自动弹起。这样的失败交互困扰了小编很久。
TextInput.show
手动注释掉。PS:这是一个笨方法,只能解燃眉之急,输入框和文本,一直都是官方每个版本改动的重点。指定版本不是长久的方案。
实际上,系统键盘是否弹出,完全是因为 SystemChannels.textInput.invokeMethod<void>('TextInput.show')
的调用,但是我们不可能去每个调用该方法地方去做处理,那么这个方法执行后续,我们有办法拦截吗? 答案当然是有的。
Flutter 的 Framework 层发送信息 TextInput.show 到 Flutter 引擎是通过 MethodChannel, 而我们可以通过重载 WidgetsFlutterBinding 的 createBinaryMessenger 方法来处理Flutter 的 Framework 层通过 MethodChannel 发送的信息。
具体代码如下:
使用 mixin 对 WidgetsFlutterBinding 进行方法重载
mixin TextInputBindingMixin on WidgetsFlutterBinding {
@override
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 引擎,会走这个方法
@override
Future<ByteData?>? send(
String channel,
ByteData? message,
) {
//TODO 拦截处理
}
// Flutter 引擎 发送信息到 Flutter 的 Framework 层的回调,无需处理
@override
void setMessageHandler(
String channel,
MessageHandler? handler,
) {
... 省略
}
//无需处理
@override
Future<void> handlePlatfORMMessage(
String channel,
ByteData? data,
PlatformMessageResponseCallback? callback,
) {
... 省略
}
}
send 方法:flutter 的 framework 层发送信息到 flutter 引擎,会走这个方法,这也是我们需要的处理的方法。
可以根据我们的需求处理 send 方法了。当 channel
为 SystemChannels.textInput
的时候,根据方法名字来拦截 TextInput.show
。
再定义一个特别的 Focusnode,并且定义好一个属性用于判断(也有那种需要随时改变是否需要拦截信息的需求)。例如 TextInputFocusNode
:
import 'package:flutter/material.dart';
class TextInputFocusNode extends FocusNode {
bool ignoreSystemKeyboardShow = true;
}
根据思路,我们的拦截方法实现如下:
@override
Future<ByteData?>? send(
String channel,
ByteData? message,
) {
if (channel == SystemChannels.textInput.name) {
final methodCall = SystemChannels.textInput.codec.decodeMethodCall(
message,
);
switch (methodCall.method) {
case 'TextInput.show':
final FocusNode? focus = FocusManager.instance.primaryFocus;
if (focus != null &&
focus is TextInputFocusNode &&
focus.ignoreSystemKeyboardShow) {
return Future.value(
SystemChannels.textInput.codec.encodeSuccessEnvelope(null),
);
}
break;
default:
break;
}
}
return origin.send(channel, message);
}
小编已将本次的方案调整重新发布上传,使用方式如下:
dependencies:
scan_gun: ^2.0.0
ScanMonitorWidget
作为父节点,嵌套使用: ScanMonitorWidget({
Key? key,
required ChildBuilder childBuilder,
TextInputFocusNode? scanNode,
FocusNode? textFiledNode,
required void Function(String) onSubmit,
})
void main() {
TextInputBinding();
runApp(const MyApp());
}
参数说明:
typedef ChildBuilder = Widget Function(BuildContext context)
,使用者自己UI作为子节点scanNode
监听获取当前扫码可用状态,hasFocus
时为可用scanNode
requestFocus 方法,强制扫码获取焦点,保证扫码能力以上就是flutter优雅实现扫码枪获取数据源示例详解的详细内容,更多关于flutter扫码枪获取数据源的资料请关注编程网其它相关文章!
--结束END--
本文标题: flutter优雅实现扫码枪获取数据源示例详解
本文链接: https://www.lsjlt.com/news/177357.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-01-21
2023-10-28
2023-10-28
2023-10-27
2023-10-27
2023-10-27
2023-10-27
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0