Flutter实现按空格/回车键唤起showDatePicker并保留点击唤起功能
问题原因
你现在的问题核心是逻辑实现方向错了:
- 你用
_setDatePicker布尔值在build方法里触发弹窗,build方法的作用是返回Widget树,_setDatePicker为true时你没有返回任何组件,才会出现build返回null的报错。 - 完全不需要用状态变量控制弹窗唤起,
showDatePicker本身是异步调用方法,直接在按键/点击的事件回调里调用即可。
修复方案
步骤1:删除无用变量
删掉状态类里的bool _setDatePicker = false;,这个变量完全不需要。
步骤2:修改按键处理逻辑
直接在按键回调里调用你已经封装好的_datePicker方法即可,不需要走setState:
KeyEventResult _handleKeyPress(FocusNode node, RawKeyEvent event) { if (event is RawKeyDownEvent) { if (event.logicalKey == LogicalKeyboardKey.space || event.logicalKey == LogicalKeyboardKey.enter) { _datePicker(); print("key pressed: $event.logicalKey"); return KeyEventResult.handled; } } return KeyEventResult.ignored; }
步骤3:修复build方法
删除build里判断_setDatePicker的逻辑,直接返回你的输入组件即可:
@override Widget build(BuildContext context) { refreshValidationMessages(); final formProvider = Provider.of<FormProvider>(context); final alerts = formProvider.getFieldAlerts( widget.fieldName, ); bool isReadonly = isFieldReadonly( formProvider, widget.fieldName, widget.templateCell.control, widget.isFormReadonly); InputDecoration inputDecoration = buildInputDecoration(alerts, isReadonly, isValid: validationMessages.isEmpty); addAlertsToValidationMessage(alerts, formProvider.form.template); _nodeAttachment.reparent(); Future _datePicker() async { if (!isReadonly) { DateTime initialDate = widget.formField.value ?? DateTime.now(); final DateTime pickedDate = await showDatePicker( context: context, initialDate: initialDate, firstDate: DateTime(2000), lastDate: DateTime(2101), cancelText: translate(I18n.CORE_ERASE), confirmText: translate(I18n.CORE_OK), builder: (BuildContext context, Widget child) { return MediaQuery( data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true, accessibleNavigation: true), child: child, ); } ); if (pickedDate == null) { setState(() { _dateController.text = ''; _focused = true; }); } else { setState(() { _dateController.text = widget.formField.valueAccessor.modelToViewValue(pickedDate); _focused = true; }); } } } return wrapAlertTooltip( Container( height: 30, child: MouseRegion( cursor: SystemMouseCursors.click, child: GestureDetector( child: InputDecorator( decoration: inputDecoration, isFocused: _focused, child: Text( _dateController.text, overflow: TextOverflow.visible, maxLines: 1, style: TextStyle(fontSize: 16.0), ), ), onTap: _datePicker , ), ), ), alerts, validationMessages, ); }
可选优化:修复聚焦状态判断
你当前_onFocusChanges里的判断逻辑写错了,修改后判断更准确:
Future<Null> _onFocusChanges() async { // 原来的判断是FocusNode对象和布尔值对比,逻辑错误 if (_fieldFocusNode.hasFocus != _focused) { setState(() { _focused = _fieldFocusNode.hasFocus; }); } }
内容的提问来源于stack exchange,提问作者Gino Chasles
相关产品推荐
相关产品推荐

