flutter:实现扫码枪获取数据源,禁止系统键盘弹窗

您所在的位置:网站首页 flutter扫码 flutter:实现扫码枪获取数据源,禁止系统键盘弹窗

flutter:实现扫码枪获取数据源,禁止系统键盘弹窗

2023-09-07 22:43| 来源: 网络整理| 查看: 265

序言

小编在项目中有遇到使用 flutter 实现扫码枪接入的需求。为方便使用,小编把能力封装成 package 并发布。好记性不如烂笔头,下面是该插件的使用方式,以及途中遇到的坑和处理想法。

效果图 使用方式: 在pubspec.yaml文件中进行引用: dependencies: scan_gun: ^1.0.0 提供 ScanMonitorWidget 作为父节点,嵌套使用: ScanMonitorWidget({ Key? key, required ChildBuilder childBuilder, FocusNode? scanNode, FocusNode? textFiledNode, required void Function(String) onSubmit, })

参数说明:

childBuilder : typedef ChildBuilder = Widget Function(BuildContext context),使用者自己UI作为子节点

scanNode:

非必传,如果传,可通过 scanNode 监听获取当前扫码可用状态,hasFocus 时为可用 也可通过 scanNode requestFocus 方法,强制扫码获取焦点,保证扫码能力

textFiledNode: 提供外部存在输入框键盘输入与扫码输入同时存在的场景。内部做了焦点切换能力,保证输入框焦点取消后,能马上切换成扫码枪的焦点

onSubmit: 接收扫码枪返回的结果

两种场景能力支持 无输入框交互,获取扫码结果: @override Widget build(BuildContext context) { return ScanMonitorWidget( childBuilder: (context) { return body(); }, onSubmit: (String result) { print(result); //接收到扫码结果 }, ); } 带输入框交互,获取扫码结果: FocusNode textFiledNode = FocusNode(); TextEditingController controller = TextEditingController(); Widget body() { return TextField( focusNode: textFiledNode, controller: controller, ); } @override Widget build(BuildContext context) { return ScanMonitorWidget( textFiledNode: textFiledNode, childBuilder: (context) { return body(); }, onSubmit: (String result) { print(result); //接收到扫码结果 }, ); }

github 源码已上传 :传送门

目前该方案为非通用方案,依赖 flutter 版本进行定制,小编使用的是 Flutter 2.8.1 ,后续更新通用方案。 通用方案已更新:新方案传送门

技术点分析 1. 如何获取扫码枪输入内容

使用过 flutter 编写输入框的同学都用过 TextField,通过源码我们可以看到 TextField 的功能实现者是它的子节点:EditableText。

1

扫码枪本质上是一个外接的输入设备。将 EditableText 封装,控制隐藏。可通过获取 EditableText 的内容来获取扫码枪的输入内容。

控制隐藏可使用 Offstage 标签:

return Stack( children: [ //让输入框保持隐藏 Offstage(child: edtWidget, offstage: true), child, ], ); 2. 键盘弹出问题

使用 EditableText 的过程中遇到了系统键盘弹出的问题。我们通过 Edit 的焦点来获取扫码枪的输入。但 EditableText 一旦获取了焦点,内部会调用原生层唤起键盘。这个问题怎么处理呢?

首先,我们来看看源码中 EditableText 是如何唤起键盘的。 省略非关键代码,直接定位到 EditableTextState

1. 当焦点变化时,调用了 _openOrCloseInputConnectionIfNeeded()

2.

在 _openInputConnection() 方法中通过 TextInput 唤起系统键盘

3.

4.

既然了解到了EditableText唤起键盘的逻辑,通过自定义 EditableText,将 TextInput.show 步骤过滤掉,只保留单纯的通过焦点获取输入源内容的能力。

3. 扩展,如何自定义监听数据源输入

在 TextInput 源码中,可以发现键盘等输入的数据通过 MessageChannel 的方式进行数据流转:

1.

由于篇幅原因,这里小编只做抛砖引玉。下面列出核心代码部分:

void listenKeyboard() { SystemChannels.textInput.setMethodCallHandler((call) => _handleTextInputInvocation(call)); } String scanData = ''; void _update(){ setState(() {}); } Future _handleTextInputInvocation(MethodCall methodCall) async { final String method = methodCall.method; final List args = methodCall.arguments as List; switch (method) { case 'TextInputClient.updateEditingState': //每次的内容变化会进来这里 final data = TextEditingValue.fromJSON(args[1] as Map); final text = data.text; scanData += text; dev.log('rex: -updateEditingState - $text'); break; case 'TextInputClient.performAction': final action = args[1] as String; dev.log('rex: -performAction - $action'); if(action == 'TextInputAction.none'){ //点击确定 _update(); } break; default: throw MissingPluginException(); } }

通用方案已更新:新方案传送门



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3