flutter優(yōu)雅實現(xiàn)掃碼槍獲取數(shù)據(jù)源示例詳解
前言
在往期的分享中,小編介紹了如何通過 flutter 自帶的 EditableText 實現(xiàn)掃碼槍數(shù)據(jù)源的獲取。大致實現(xiàn)如下:
- 掃碼槍本質(zhì)上是一個外接的輸入設(shè)備。
- 使用 Stack 結(jié)合自己的布局控件 childWidget 將 editableText 封裝,控制隱藏??赏ㄟ^監(jiān)聽 onSubmitted 獲取掃碼槍的輸入內(nèi)容。
痛點問題
回顧 往期分享 痛點問題 :
使用 EditableText 的過程中遇到了系統(tǒng)鍵盤彈出的問題。我們通過 Edit 的焦點來獲取掃碼槍的輸入。但 EditableText 一旦獲取了焦點,內(nèi)部會調(diào)用原生層喚起鍵盤。
掃碼槍觸發(fā)焦點后,系統(tǒng)鍵盤自動彈起。這樣的失敗交互困擾了小編很久。
- 往期分享中的臨時方案 之前的處理方式是通過定制化源碼的方式,將指定版本內(nèi)的
TextInput.show
手動注釋掉。
PS:這是一個笨方法,只能解燃眉之急,輸入框和文本,一直都是官方每個版本改動的重點。指定版本不是長久的方案。
如何在不改動源碼的方式下,動態(tài)控制焦點是否觸發(fā)鍵盤彈出?
1.系統(tǒng)鍵盤彈出的原因
實際上,系統(tǒng)鍵盤是否彈出,完全是因為 SystemChannels.textInput.invokeMethod<void>('TextInput.show')
的調(diào)用,但是我們不可能去每個調(diào)用該方法地方去做處理,那么這個方法執(zhí)行后續(xù),我們有辦法攔截嗎? 答案當(dāng)然是有的。
2. 如何攔截 methodChannel
Flutter 的 Framework 層發(fā)送信息 TextInput.show 到 Flutter 引擎是通過 MethodChannel, 而我們可以通過重載 WidgetsFlutterBinding 的 createBinaryMessenger 方法來處理Flutter 的 Framework 層通過 MethodChannel 發(fā)送的信息。
具體代碼如下:
使用 mixin 對 WidgetsFlutterBinding 進(jìn)行方法重載
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 進(jìn)行自定義攔截操作
class TextInputBinaryMessenger extends BinaryMessenger { TextInputBinaryMessenger(this.origin); final BinaryMessenger origin; // Flutter 的 Framework 層發(fā)送信息到 Flutter 引擎,會走這個方法 @override Future<ByteData?>? send( String channel, ByteData? message, ) { //TODO 攔截處理 } // Flutter 引擎 發(fā)送信息到 Flutter 的 Framework 層的回調(diào),無需處理 @override void setMessageHandler( String channel, MessageHandler? handler, ) { ... 省略 } //無需處理 @override Future<void> handlePlatformMessage( String channel, ByteData? data, PlatformMessageResponseCallback? callback, ) { ... 省略 } }
send 方法:flutter 的 framework 層發(fā)送信息到 flutter 引擎,會走這個方法,這也是我們需要的處理的方法。
3. 攔截思路
可以根據(jù)我們的需求處理 send 方法了。當(dāng) channel
為 SystemChannels.textInput
的時候,根據(jù)方法名字來攔截 TextInput.show
。
再定義一個特別的 FocusNode,并且定義好一個屬性用于判斷(也有那種需要隨時改變是否需要攔截信息的需求)。例如 TextInputFocusNode
:
import 'package:flutter/material.dart'; class TextInputFocusNode extends FocusNode { bool ignoreSystemKeyboardShow = true; }
根據(jù)思路,我們的攔截方法實現(xiàn)如下:
@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); }
掃碼庫更新
小編已將本次的方案調(diào)整重新發(fā)布上傳,使用方式如下:
- 在pubspec.yaml文件中進(jìn)行引用:
dependencies: scan_gun: ^2.0.0
- 提供
ScanMonitorWidget
作為父節(jié)點,嵌套使用:
ScanMonitorWidget({ Key? key, required ChildBuilder childBuilder, TextInputFocusNode? scanNode, FocusNode? textFiledNode, required void Function(String) onSubmit, })
- 在 main 方法中初始化 TextInputBinding
void main() { TextInputBinding(); runApp(const MyApp()); }
參數(shù)說明:
- childBuilder :
typedef ChildBuilder = Widget Function(BuildContext context)
,使用者自己UI作為子節(jié)點 - scanNode:
- 非必傳,如果傳,可通過
scanNode
監(jiān)聽獲取當(dāng)前掃碼可用狀態(tài),hasFocus
時為可用 - 也可通過
scanNode
requestFocus 方法,強制掃碼獲取焦點,保證掃碼能力
- textFiledNode:
提供外部存在輸入框鍵盤輸入與掃碼輸入同時存在的場景。內(nèi)部做了焦點切換能力,保證輸入框焦點取消后,能馬上切換成掃碼槍的焦點
以上就是flutter優(yōu)雅實現(xiàn)掃碼槍獲取數(shù)據(jù)源示例詳解的詳細(xì)內(nèi)容,更多關(guān)于flutter掃碼槍獲取數(shù)據(jù)源的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android 獲取手機(jī)聯(lián)系人實例代碼詳解
最近做了個項目,其中有項目需求是這樣的,需要獲取手機(jī)聯(lián)系人,下面小編把代碼分享給大家,供大家參考2015-12-12Android自定義狀態(tài)欄顏色與APP風(fēng)格保持一致的實現(xiàn)方法
我們知道iOS上的應(yīng)用,狀態(tài)欄的顏色總能與應(yīng)用標(biāo)題欄顏色保持一致,用戶體驗很不錯,那安卓是否可以呢?下面小編給大家?guī)砹薃ndroid自定義狀態(tài)欄顏色與APP風(fēng)格保持一致的實現(xiàn)方法,跟著小編一起學(xué)習(xí)吧2016-10-10Flutter listview如何實現(xiàn)下拉刷新上拉加載更多功能
這篇文章主要給大家介紹了關(guān)于Flutter listview如何實現(xiàn)下拉刷新上拉加載更多功能的相關(guān)資料,對于新聞列表數(shù)據(jù)的更新和加載更多是必不可少的,而實現(xiàn)下拉刷新與上劃加載更多的方式有很多種,需要的朋友可以參考下2021-08-08Android實現(xiàn)給TableLayou繪制邊框的方法
這篇文章主要介紹了Android實現(xiàn)給TableLayou繪制邊框的方法,涉及Android TableLayou布局控制相關(guān)技巧,需要的朋友可以參考下2016-03-03Android USB轉(zhuǎn)串口通信開發(fā)實例詳解
這篇文章主要介紹了 Android USB轉(zhuǎn)串口通信開發(fā)實例詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04Android開發(fā)之設(shè)置開機(jī)自動啟動的幾種方法
這篇文章主要介紹了Android開發(fā)之設(shè)置開機(jī)自動啟動的幾種方法的相關(guān)資料,這里提供三種方法幫助大家實現(xiàn)這樣的功能,需要的朋友可以參考下2017-08-08