赞
踩
现在我们有个需求,要求输入完成后所有字母都转大写,看起来很容易,直接写个TextField,然后在onEditingComplete里处理不就行了,但是,你会发现,键盘里还有个下拉按钮,就上面那个按钮,点击它虽然键盘消失了,但根本不执行onEditingComplete,只有点击下面那个按钮才会执行,这样测试肯定不通过,那就在onChange方法里处理?也不行,因为我输入完成后还得访问后台接口,所以不能在onChange方法里处理。
背景讲完了,上代码:
1,使用扩展类extension...on...,扩展下TextField,混入class WidgetsBindingObserver来监听界面的变化,具体监听尺寸变化的方法是didChangeMetrics()
- extension TextFieldExtension on TextField{
-
- Widget getKeyboardListenerTextField(){
- if(focusNode == null) return this;
- return KeyboardListenerTextField(child: this);
- }
-
- }
- class KeyboardListenerTextField extends StatefulWidget {
- TextField child;
- KeyboardListenerTextField({
- this.child,
- });
-
- @override
- _KeyboardListenerTextFieldState createState() => _KeyboardListenerTextFieldState();
- }
-
- class _KeyboardListenerTextFieldState extends State<KeyboardListenerTextField> with WidgetsBindingObserver {
- //标记键盘是否现实中,默认不显示
- bool isKeyboardActived = false;
- @override
- void initState() {
- super.initState();
- WidgetsBinding.instance.addObserver(this);
- }
- @override
- void dispose() {
- super.dispose();
- WidgetsBinding.instance.removeObserver(this);
- widget.child.focusNode.unfocus();
- }
-
- @override
- void didChangeMetrics() {
- super.didChangeMetrics();
- WidgetsBinding.instance.addPostFrameCallback((_) {
- // 当前是安卓系统并且在焦点聚焦的情况下
- if (Platform.isAndroid && widget.child.focusNode.hasFocus) {
- if (isKeyboardActived) {
- isKeyboardActived = false;
- // 使输入框失去焦点
- widget.child.focusNode.unfocus();
- return;
- }
- isKeyboardActived = true;
- } else {
- isKeyboardActived = false;
- }
- });
- }
- @override
- Widget build(BuildContext context) {
- return widget.child;
- }
- }
2,在使用时直接
- TextField(
- focusNode: focusNode,
- onEditingComplete: () {
- focusNode?.unfocus();
- },
- onSubmitted: (text) {
- focusNode?.unfocus();
- },
- ).getKeyboardListenerTextField();
3,当然,需要监听焦点
- focusNode.addListener(() {
- if (!focusNode.hasFocus) {
- //失去焦点,说明输入完成,该转大写的转大写,该数据请求的数据请求
- }
- });
最后:这样写也有缺点,因为如果一个界面TextField很多,如果焦点直接从这个TextField到另一个TextField,那第二个 TextField当键盘隐藏时因为键盘状态未变化,所以不会失去焦点,所以这只适合界面有一个TextField的情况。
最后的最后:如果界面就是很多TextField,那可以给整个界面混入WidgetsBindingObserver,监听整个界面的尺寸,设置监听时酱紫写:
- double oldBottom = 0;
- @override
- void didChangeMetrics() {
- super.didChangeMetrics();
- WidgetsBinding.instance.addPostFrameCallback((_) {
- var currentBottom = MediaQuery.of(context).viewInsets.bottom;
- // 如果currentBottom为0,表示键盘消失了,这时候整个界面获取焦点,那TextField自然就失去焦点了
- // 为什么还要判断oldBottom,因为在界面没变化的时候,个别机型也会调用这个方法。。。
- // 所以必须在oldBottom不为0的时候,才获取焦点,这里坑的我好惨。。。
- if(oldBottom != 0 && currentBottom==0){
- FocusScope.of(context).requestFocus(FocusNode());
- }
- oldBottom = currentBottom;
- });
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。