flutter实现扫码枪获取数据源禁止系统键盘弹窗示例详解
作者:李小轰_Rex 发布时间:2023-07-23 01:52:41
序言
小编在项目中有遇到使用 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
。
扫码枪本质上是一个外接的输入设备。将 EditableText
封装,控制隐藏。可通过获取 EditableText 的内容来获取扫码枪的输入内容。
控制隐藏可使用 Offstage
标签:
return Stack(
children: [
//让输入框保持隐藏
Offstage(child: edtWidget, offstage: true),
child,
],
);
2. 键盘弹出问题
使用 EditableText
的过程中遇到了系统键盘弹出的问题。我们通过 Edit 的焦点来获取扫码枪的输入。但 EditableText 一旦获取了焦点,内部会调用原生层唤起键盘。这个问题怎么处理呢?
首先,我们来看看源码中 EditableText
是如何唤起键盘的。 省略非关键代码,直接定位到 EditableTextState
当焦点变化时,调用了 _openOrCloseInputConnectionIfNeeded()
在 _openInputConnection()
方法中通过 TextInput
唤起系统键盘
既然了解到了EditableText
唤起键盘的逻辑,通过自定义 EditableText
,将 TextInput.show
步骤过滤掉,只保留单纯的通过焦点获取输入源内容的能力。
3. 扩展,如何自定义监听数据源输入
在 TextInput
源码中,可以发现键盘等输入的数据通过 MessageChannel
的方式进行数据流转:
由于篇幅原因,这里小编只做抛砖引玉。下面列出核心代码部分:
void listenKeyboard() {
SystemChannels.textInput.setMethodCallHandler((call) => _handleTextInputInvocation(call));
}
String scanData = '';
void _update(){
setState(() {});
}
Future<dynamic> _handleTextInputInvocation(MethodCall methodCall) async {
final String method = methodCall.method;
final List<dynamic> args = methodCall.arguments as List<dynamic>;
switch (method) {
case 'TextInputClient.updateEditingState': //每次的内容变化会进来这里
final data = TextEditingValue.fromJSON(args[1] as Map<String, dynamic>);
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();
}
}
来源:https://juejin.cn/post/7163845736411430920
猜你喜欢
- 1. 在原有工程目录右键-> new ->Module->:2. 选择library:3. 一路next,最后finish
- 最近项目中需要实现定时执行任务,比如定时计算会员的积分、调用第三方接口等,由于项目采用spring框架,所以这里结合spring框架来介绍。
- 1 自定义类加载器自定义类加载器的代码很简单,只需要继承ClassLoader类,覆写findClass方法即可其默认实现是会抛出一个异常:
- 本文实例讲解了iOS从背景图中取色的代码,分享给大家供大家参考,具体内容如下实现代码:void *bitmapData; //内存空间的指针
- 前言我们在 页面切换转场动画,英雄救场更有趣!介绍了 Hero 动画效果,使用 Hero 用于转场能够提供非常不错的体验。既然称之
- 前言在电商的应用中,最常见的就是在首页或完成某事件之后,弹出一堆的活动/广告。假如重叠弹出,很丑,给用户的体验也不好,所以一般都会依次依条件
- C++11 引入一个全新的线程库,包含启动和管理线程的工具,提供了同步(互斥、锁和原子变量)的方法,我将试图为你介绍这个全新的线
- 现如今打开一个 App,比如头条、微博,都会有长列表,随着我们不断地滑动,视窗内的内容也会不断地更新。今天就用 Flutter 实现一下这种
- 本文实例讲述了Android+SQLite数据库实现的生词记事本功能。分享给大家供大家参考,具体如下:主activity命名为Dict:代码
- 1、volley 项目地址 https://github.com/smanikandan14/Volley-demo (1)&nb
- 前言我们在学习Windows应用程序开发中,经常会用到消息对话框给用户或者管理员一些的消息提示,它们都是基于对MessageBox类的消息对
- 内容简介本篇将介绍 Flutter 中如何完成图片上传,以及上传成功后的表单提交。涉及的知识点如下:图片选择插件wechat_assets_
- 介绍什么是ThreadLocal?ThreadLocal叫做线程变量,用于在多线程环境下创建线程本地变量。通俗的讲,ThreadLocal可
- 虽然说模块通信、路由协议在Android已经不新鲜了,但是如果脱离了那些优秀的开源库我们从零开始自己造一个库,有时候重复造轮子会让自己对所谓
- 摘要:这个问题算是老生常谈了,我也是一段时间没弄过了,所以感觉有些忘了,就记录一下。一、后端通过shiro在session中存储数据://
- 一、导航栏UINavigationBar1、导航栏的使用在iOS开发中,我们通常会使用导航控制器,导航控制器中封装了一个UINavigati
- 本文实例为大家分享了Android微信摇一摇功能的实现方法,供大家参考,具体内容如下import java.util.ArrayList;
- Android 中ScrollView嵌套GridView,ListView的实例在Android开发中,经常有一些UI需要进行固定styl
- 本文实例为大家分享了C# GDI+实现时钟表盘的具体代码,供大家参考,具体内容如下一、设计如下图界面按键“打开时钟&am
- 在项目迁移到Spring Boot之后,发生内存使用量过高的问题。本文介绍了整个排查过程以及使用到的工具,也非常适用于其他堆外内存排查。背景