前言
最近在做公司flutter項目的時候,接到了一個需求,本質上就是實現收起鍵盤的時候讓TextField組件失去焦點的功能。
這個需求乍一看很好解決,心想,就這!就這!就這!so easy!
但是!但是!但是!萬萬沒想到啊,實現時候卻讓我本來就很稀薄的頭發雪上加霜,原因就是安卓手機第三方輸入法有一個很蛋疼的地方,就是他會有一個收起鍵盤的按鈕,如下圖所示:
問題就在,這!個!按!鈕!他不屬於原生鍵盤按鈕,無法檢測到鍵盤事件!並且不能夠屏蔽!真的要給搞崩潰了。下面就給兄弟萌說說我最后的解題思路,希望能有所幫助!
vi設計http://www.maiqicn.com 辦公資源網站大全https://www.wode007.com
解題思路
上面說過,鍵盤事件無法監聽,所以我只能另外想辦法。能不能監聽鍵盤關閉呢?通過一番查找,得出的答案是可以,那么就來搞一下!
keyboard_visibility
地址: https://pub.dev/packages/keyb...
這個庫可以用來監聽鍵盤的彈出和收起,引用庫里的例子:
import 'package:keyboard_visibility/keyboard_visibility.dart'; @protected void initState() { super.initState(); KeyboardVisibilityNotification().addNewListener( onChange: (bool visible) { print(visible); }, ); }
通常來講,這個就完全可以解決我們的需求,但是!事情並沒有這么簡單!我們在升級了flutter版本之后,發現無法打包apk,最后提示是keyboard_visibility不!兼!容!查了一下資料發現,這個庫應該是作者停更了,沒有做到與時俱進,這咋整!
由於網上相關資料極少,上網也不能立刻解決我的問題,萬般無奈之下,只能換個思路。那能不能監聽界面的高度變化?經過查找資料,得出的結論是可以這樣做的。
WidgetsBindingObserver & didChangeMetrics
這個組件可以監聽頁面的一些生命周期,並且其中有一個回調didChangeMetrics可以監聽界面高度的變化。其中鍵盤的彈出和收起這些其實都屬於高度的變化自然也是可以監聽到的。
Nice!看到這里,那么我們的解決方案也就有了,那就是設置一個flag,區分出來什么時候鍵盤彈出,什么時候鍵盤收起。
class _InputState extends State<Input> with WidgetsBindingObserver { // 輸入框的焦點實例 FocusNode _focusNode; // 當前鍵盤是否是激活狀態 bool isKeyboardActived = false; @override void initState() { super.initState(); _focusNode = FocusNode(); // 監聽輸入框焦點變化 _focusNode.addListener(_onFocus); // 創建一個界面變化的觀察者 WidgetsBinding.instance.addObserver(this); } @override void didChangeMetrics() { super.didChangeMetrics(); WidgetsBinding.instance.addPostFrameCallback((_) { // 當前是安卓系統並且在焦點聚焦的情況下 if (Platform.isAndroid && _focusNode.hasFocus) { if (isKeyboardActived) { isKeyboardActived = false; // 使輸入框失去焦點 _focusNode.unfocus(); return; } isKeyboardActived = true; } }); } // 既然有監聽當然也要有卸載,防止內存泄漏嘛 @override void dispose() { super.dispose(); _focusNode.dispose(); WidgetsBinding.instance.removeObserver(this); } // 焦點變化時觸發的函數 _onFocus() { if (_focusNode.hasFocus) { // 聚焦時候的操作 return; } // 失去焦點時候的操作 isKeyboardActived = false; } @override Widget build(BuildContext context) { return TextField( focusNode: _focusNode, textInputAction: TextInputAction.done, ); } }
這樣就大功告成了,測試之后暫時沒發現什么大問題,還是比較好用的。