Flutter TextFormField唤起日期选择器重复弹出无法关闭的焦点问题问询
问题根因
- 当前的
onFocusChange回调没有判断焦点状态,无论是获得焦点还是失去焦点都会触发日期选择器的弹出逻辑。当你选中日期后调用unfocus,焦点状态再次变化,就会二次触发弹窗逻辑,导致选择器反复弹出。 - 另外
TextFormField默认处于可编辑状态,更新输入框内容时也可能触发焦点重新获取,进一步复现问题。
解决方案
核心修改点有3个:
- 在
onFocusChange中增加判断,只有当focus == true(即输入框获得焦点)时才弹出日期选择器 - 给
TextFormField增加readOnly: true属性,禁止手动输入、避免软键盘弹出,同时阻断内容更新时的焦点异常触发 - 移除不必要的
FocusScope嵌套,简化层级
修正后代码如下:
Container( width: Width * 0.45, child: Focus( onFocusChange: (focus) async { // 仅在获得焦点时触发弹窗 if (!focus) return; DateTime selectedDate = DateTime.now(); final DateTime? picked = await showDatePicker( context: context, initialDate: selectedDate, firstDate: DateTime(1900, 1), lastDate: DateTime(2022) ); if (picked != null && picked != selectedDate) { setState(() { bookDate.text = DateFormat("yyyy-MM-d").format(picked).toString(); }); } // 选中后直接失焦 FocusScope.of(context).unfocus(); }, child: TextFormField( controller: bookDate, // 关键:设置为只读,避免手动输入和异常焦点触发 readOnly: true, decoration: InputDecoration( suffixIcon: IconButton( onPressed: () async {}, icon: Icon( Icons.date_range_outlined, color: Color(0xffbdbdbd), ), ), labelText: "Date", labelStyle: TextStyle( color: textGreyColor, fontFamily: 'SegoeUI' ), fillColor: Colors.white, focusedBorder: OutlineInputBorder( borderSide: BorderSide(color: kPrimaryColor, width: 1.0), ), enabledBorder: OutlineInputBorder( borderSide: BorderSide(color: Color(0xffE6E6E6), width: 1.0), ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: BorderSide(color: Color(0xffE6E6E6)), ), ), style: TextStyle( fontFamily: "SegoeUI", color: kPrimaryColor ), ), ), ),
如果想要更简单的实现,也可以不用监听焦点,直接给TextFormField套一层GestureDetector,监听onTap事件弹出选择器,逻辑更直观,也不会有焦点异常问题。
内容的提问来源于stack exchange,提问作者rameez khan
相关产品推荐
相关产品推荐

