flutter實現(xiàn)掃碼槍獲取數(shù)據(jù)源禁止系統(tǒng)鍵盤彈窗示例詳解
序言
小編在項目中有遇到使用 flutter 實現(xiàn)掃碼槍接入的需求。為方便使用,小編把能力封裝成 package 并發(fā)布。好記性不如爛筆頭,下面是該插件的使用方式,以及途中遇到的坑和處理想法。
使用方式:
- 在pubspec.yaml文件中進行引用:
dependencies: scan_gun: ^1.0.0
- 提供
ScanMonitorWidget
作為父節(jié)點,嵌套使用:
ScanMonitorWidget({ Key? key, required ChildBuilder childBuilder, FocusNode? scanNode, FocusNode? textFiledNode, required void Function(String) onSubmit, })
參數(shù)說明:
- childBuilder :
typedef ChildBuilder = Widget Function(BuildContext context),使用者自己UI作為子節(jié)點
- scanNode:
非必傳,如果傳,可通過 scanNode
監(jiān)聽獲取當前掃碼可用狀態(tài),hasFocus
時為可用也可通過 scanNode
requestFocus 方法,強制掃碼獲取焦點,保證掃碼能力
- textFiledNode:
提供外部存在輸入框鍵盤輸入與掃碼輸入同時存在的場景。內(nèi)部做了焦點切換能力,保證輸入框焦點取消后,能馬上切換成掃碼槍的焦點
- onSubmit:
接收掃碼槍返回的結(jié)果
兩種場景能力支持
- 無輸入框交互,獲取掃碼結(jié)果:
@override Widget build(BuildContext context) { return ScanMonitorWidget( childBuilder: (context) { return body(); }, onSubmit: (String result) { print(result); //接收到掃碼結(jié)果 }, ); }
- 帶輸入框交互,獲取掃碼結(jié)果:
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); //接收到掃碼結(jié)果 }, ); }
github 源碼已上傳 :傳送門
目前該方案為非通用方案,依賴 flutter 版本進行定制,小編使用的是 Flutter 2.8.1
,后續(xù)更新通用方案。
技術(shù)點分析
1. 如何獲取掃碼槍輸入內(nèi)容
使用過 flutter 編寫輸入框的同學(xué)都用過 TextField
,通過源碼我們可以看到 TextField 的功能實現(xiàn)者是它的子節(jié)點:EditableText
。
掃碼槍本質(zhì)上是一個外接的輸入設(shè)備。將 EditableText
封裝,控制隱藏??赏ㄟ^獲取 EditableText 的內(nèi)容來獲取掃碼槍的輸入內(nèi)容。
控制隱藏可使用 Offstage
標簽:
return Stack( children: [ //讓輸入框保持隱藏 Offstage(child: edtWidget, offstage: true), child, ], );
2. 鍵盤彈出問題
使用 EditableText
的過程中遇到了系統(tǒng)鍵盤彈出的問題。我們通過 Edit 的焦點來獲取掃碼槍的輸入。但 EditableText 一旦獲取了焦點,內(nèi)部會調(diào)用原生層喚起鍵盤。這個問題怎么處理呢?
首先,我們來看看源碼中 EditableText
是如何喚起鍵盤的。 省略非關(guān)鍵代碼,直接定位到 EditableTextState
當焦點變化時,調(diào)用了 _openOrCloseInputConnectionIfNeeded()
在 _openInputConnection()
方法中通過 TextInput
喚起系統(tǒng)鍵盤
既然了解到了EditableText
喚起鍵盤的邏輯,通過自定義 EditableText
,將 TextInput.show
步驟過濾掉,只保留單純的通過焦點獲取輸入源內(nèi)容的能力。
3. 擴展,如何自定義監(jiān)聽數(shù)據(jù)源輸入
在 TextInput
源碼中,可以發(fā)現(xiàn)鍵盤等輸入的數(shù)據(jù)通過 MessageChannel
的方式進行數(shù)據(jù)流轉(zhuǎn):
由于篇幅原因,這里小編只做拋磚引玉。下面列出核心代碼部分:
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': //每次的內(nèi)容變化會進來這里 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(); } }
以上就是flutter實現(xiàn)掃碼槍獲取數(shù)據(jù)源禁止系統(tǒng)鍵盤彈窗示例詳解的詳細內(nèi)容,更多關(guān)于flutter掃碼槍獲取數(shù)據(jù)源的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
android 把float轉(zhuǎn)換成Int的實例講解
今天小編就為大家分享一篇android 把float轉(zhuǎn)換成Int的實例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07Android實現(xiàn)仿360桌面懸浮清理內(nèi)存
今天給大家?guī)硪粋€仿360手機衛(wèi)士懸浮窗清理內(nèi)存的效果的教程,非常的簡單實用,需要的小伙伴可以參考下2015-12-12Android使用ViewPager實現(xiàn)頂部tabbar切換界面
這篇文章主要為大家詳細介紹了使用ViewPager實現(xiàn)頂部tabbar切換界面,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08Flutter檢查連接網(wǎng)絡(luò)connectivity_plus實現(xiàn)步驟
這篇文章主要為大家介紹了Flutter檢查連接網(wǎng)絡(luò)connectivity_plus實現(xiàn)步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06Android中ViewPager帶來的滑動卡頓問題解決要點解析
這里我們主要針對ViewGroup的SwipeRefreshLayout中引入ViewPager所引起的滑動沖突問題進行討論,一起來看一下Android中ViewPager帶來的滑動卡頓問題解決要點解析:2016-06-06