You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现按空格/回车键唤起showDatePicker并保留点击唤起功能

问题原因

你现在的问题核心是逻辑实现方向错了:

  1. 你用_setDatePicker布尔值在build方法里触发弹窗,build方法的作用是返回Widget树,_setDatePicker为true时你没有返回任何组件,才会出现build返回null的报错。
  2. 完全不需要用状态变量控制弹窗唤起,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 20:54:01