键盘弹出时TextFormField焦点失效且被遮挡,如何解决?
问题描述
我有一个TextFormField,上方有一个存储其输入值的List。现在遇到两个问题:
- 向List添加条目后,
TextFormField被键盘遮挡 - 调用
FocusScope.of(context).requestFocus(focusNode)无法维持输入框焦点
我的TextFormField代码如下:
TextFormField( cursorColor: Colors.black, onFieldSubmitted: (value) { FocusScope.of(context).requestFocus(focusNode); // 这行代码不起作用 }, style: new TextStyle( fontSize: 15.0, fontFamily: "Roboto", fontWeight: FontWeight.w400, color: darkGreyColor, ), controller: _textFieldController, keyboardType: TextInputType.text, focusNode: focusNode, textInputAction: TextInputAction.done, onChanged: (text) { }, inputFormatters: [ new LengthLimitingTextInputFormatter(200), ], onSaved: (String? val) { }, ),
预期效果:输入框始终显示在键盘上方,提交输入内容后,输入框保持焦点并清空内容,方便继续输入
当前效果:输入框被键盘遮挡,提交后输入框焦点丢失,无法继续连续输入
解决方案
1. 修复输入框被键盘遮挡问题
用SingleChildScrollView包裹页面所有内容(List + TextFormField),并动态适配键盘高度:
SingleChildScrollView( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: Column( children: [ // 你的List渲染组件 ..._listItems.map((item) => Text(item)).toList(), // 你的TextFormField _buildTextFormField(), ], ), )
同时确保Scaffold的resizeToAvoidBottomInset保持默认的true(如果手动修改过需恢复):
Scaffold( resizeToAvoidBottomInset: true, body: // ...上述SingleChildScrollView )
2. 修复焦点无法维持问题
提交后延迟请求焦点,避免页面布局刷新覆盖焦点操作,同时清空输入框:
onFieldSubmitted: (value) { // 先执行添加条目到List的逻辑 setState(() { _listItems.add(value); }); // 清空输入框 _textFieldController.clear(); // 延迟100ms请求焦点,等待布局完成 Future.delayed(const Duration(milliseconds: 100), () { if (!focusNode.hasFocus) { FocusScope.of(context).requestFocus(focusNode); } }); },
另外必须保证focusNode和_textFieldController在initState中初始化,而非build方法内:
late FocusNode _focusNode; late TextEditingController _textFieldController; List<String> _listItems = []; @override void initState() { super.initState(); _focusNode = FocusNode(); _textFieldController = TextEditingController(); } @override void dispose() { _focusNode.dispose(); _textFieldController.dispose(); super.dispose(); }
3. 进阶优化:自动滚动到输入框
如果List条目较多,添加后输入框可能被挤出可视区域,可通过GlobalKey配合滚动确保输入框可见:
// 定义全局Key final GlobalKey _textFieldKey = GlobalKey(); // 给TextFormField绑定Key TextFormField( key: _textFieldKey, // ...其他属性 ) // 添加条目后执行滚动 setState(() { _listItems.add(value); }); WidgetsBinding.instance.addPostFrameCallback((_) { Scrollable.ensureVisible( _textFieldKey.currentContext!, duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, ); });
内容的提问来源于stack exchange,提问作者Yashraj
相关产品推荐
相关产品推荐

