網站首頁 編程語言 正文
序言
小編在項目中有遇到使用 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
相關推薦
- 2022-02-07 出現報錯nginx: [emerg] unknown directive nginx.htacces
- 2022-09-04 mat矩陣和npy矩陣實現互相轉換(python和matlab)_python
- 2022-06-21 git基礎之各版本控制系統介紹_其它綜合
- 2024-04-02 docker開機自啟設置
- 2023-11-21 什么是交叉編譯、交叉編譯有什么用,為什么需要交叉編譯
- 2022-08-01 C語言深入探索遞歸的特點_C 語言
- 2022-03-03 關于使用iview table 組件中使用 tooltip 樣式覆蓋的問題
- 2023-10-16 el-radio單選框,取消選中
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支