Flutter如何检测TextField编辑取消/键盘收起/失去焦点并处理未保存修改
问题根源
你遇到的状态不一致核心来自两个问题:
- 你在
build方法中每次都新建TextEditingController,即使Cubit状态更新也不会同步到正在编辑的输入框 - 原生
TextField没有提供编辑中断(失去焦点、收起键盘)的回调,仅靠onSubmitted只能覆盖点击键盘完成的场景
解决方案
通过FocusNode监听输入框的焦点状态,当输入框失去焦点时就触发你需要的自定义逻辑(自动保存/回退原值均可),同时把TextEditingController移到State中维护,不要在build里重复创建。
修改后完整代码
testpage.dart
import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'some_cubit.dart'; class TestPage extends StatefulWidget { const TestPage({Key? key}) : super(key: key); @override _TestPageState createState() => _TestPageState(); } class _TestPageState extends State<TestPage> { // 提前定义控制器和焦点节点 late final TextEditingController _minController; late final TextEditingController _maxController; late final FocusNode _minFocusNode; late final FocusNode _maxFocusNode; @override void initState() { super.initState(); _minController = TextEditingController(); _maxController = TextEditingController(); _minFocusNode = FocusNode(); _maxFocusNode = FocusNode(); // 监听最小值输入框焦点变化 _minFocusNode.addListener(() { if (!_minFocusNode.hasFocus) { // 失去焦点时触发逻辑,这里示例为自动保存,要回退的话直接写_minController.text = context.read<SomeCubit>().state.min.toString()即可 context.read<SomeCubit>().updateMin(_minController.text); } }); // 监听最大值输入框焦点变化 _maxFocusNode.addListener(() { if (!_maxFocusNode.hasFocus) { context.read<SomeCubit>().updateMax(_maxController.text); } }); } @override void dispose() { // 记得销毁资源 _minController.dispose(); _maxController.dispose(); _minFocusNode.dispose(); _maxFocusNode.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Test')), body: BlocProvider( create: (context) => SomeCubit(), child: BlocListener<SomeCubit, SomeState>( // 监听Cubit状态变化,同步更新输入框内容 listener: (context, state) { _minController.text = state.min.toString(); _maxController.text = state.max.toString(); }, child: Column( children: [ Flexible( child: TextField( controller: _minController, focusNode: _minFocusNode, keyboardType: TextInputType.number, onSubmitted: (s) { context.read<SomeCubit>().updateMin(s); // 提交后可以自动清焦点,也可以按需保留 _minFocusNode.unfocus(); }, ), ), Flexible( child: TextField( controller: _maxController, focusNode: _maxFocusNode, keyboardType: TextInputType.number, onSubmitted: (s) { context.read<SomeCubit>().updateMax(s); _maxFocusNode.unfocus(); }, ), ), ], ), ), ), ); } }
some_cubit.dart无需修改,和你原有代码一致即可。
可选逻辑实现
如果你需要在用户中断编辑时回退到原始值,只需要把焦点失去回调里的保存逻辑替换为重置控制器内容即可:
// 示例:失去焦点回退原值 _minFocusNode.addListener(() { if (!_minFocusNode.hasFocus) { final currentMin = context.read<SomeCubit>().state.min.toString(); if (_minController.text != currentMin) { _minController.text = currentMin; } } });
内容的提问来源于stack exchange,提问作者Arek
相关产品推荐
相关产品推荐

