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

Flutter实现从右到左的时间输入格式化及焦点自动切换

Flutter 实现反向时间输入效果

需求明确

要实现一行内两个TextField组件,左侧显示小时、右侧显示分钟,输入规则如下:

  • 从右侧分钟框开始输入,每次输入的字符追加到分钟末尾
  • 输入效果严格遵循以下流程:
    • 输入2 → 显示 00:02
    • 输入6 → 显示 00:26
    • 输入3 → 显示 02:63
    • 输入1 → 显示 26:31
  • 分钟框每输入满两位字符后,自动将焦点切换至左侧小时TextField

现有代码的问题

当前代码未实现核心逻辑,主要问题包括:

  1. 焦点逻辑反向:现行为小时框输入4位后切换到分钟框,与需求不符
  2. 缺少文本转移逻辑:输入溢出时不会将分钟的字符转移到小时框
  3. 分钟输入范围限制:原有规则限制分钟为0-59,不符合需求中显示63、31的要求
  4. 格式化规则不匹配:无法实现动态补零与文本转移的联动效果

修正后的完整代码

先在State类中定义焦点节点与文本控制器,再替换目标Widget代码:

// 在你的State类中声明变量
final FocusNode _hourFocus = FocusNode();
final FocusNode _minuteFocus = FocusNode();
final TextEditingController _hourCtrl = TextEditingController(text: '00');
final TextEditingController _minuteCtrl = TextEditingController(text: '00');

// ... 保留其他原有代码,替换以下Widget部分 ...

if (goalData.goalType == "du") ...[
  Container(
    decoration: BoxDecoration(
      borderRadius: BorderRadius.circular(10),
      color: AppColors.grayLightColor.withOpacity(0.3),
    ),
    margin: const EdgeInsets.symmetric(horizontal: 18),
    padding: const EdgeInsets.only(bottom: 5),
    height: 40,
    child: Row(
      children: [
        Flexible(
          flex: 1,
          child: TextField(
            focusNode: _hourFocus,
            controller: _hourCtrl,
            textAlign: TextAlign.center,
            keyboardType: TextInputType.number,
            decoration: const InputDecoration(
              border: InputBorder.none,
              hintText: "HH",
            ),
            inputFormatters: [
              FilteringTextInputFormatter.digitsOnly,
              LengthLimitingTextInputFormatter(2), // 小时固定显示两位
            ],
            onChanged: (value) {
              // 可选逻辑:小时输入满两位后切回分钟框
              if (value.length == 2) {
                _minuteFocus.requestFocus();
              }
              // 自动补零,确保小时始终显示两位
              if (value.length < 2) {
                _hourCtrl.text = value.padLeft(2, '0');
                _hourCtrl.selection = TextSelection.collapsed(offset: _hourCtrl.text.length);
              }
            },
          ),
        ),
        const Text(":"),
        Flexible(
          child: TextField(
            focusNode: _minuteFocus,
            controller: _minuteCtrl,
            textAlign: TextAlign.center,
            keyboardType: TextInputType.number,
            decoration: const InputDecoration(
              border: InputBorder.none,
              hintText: "MM",
            ),
            inputFormatters: [
              FilteringTextInputFormatter.digitsOnly,
              LengthLimitingTextInputFormatter(3), // 允许临时输入3位,用于字符转移
            ],
            autofocus: true, // 默认焦点在分钟框,符合输入顺序
            onChanged: (value) {
              if (value.length > 2) {
                // 取出最左侧字符,转移到小时框
                final transferChar = value[0];
                // 分钟保留最后两位
                final newMinute = value.substring(1);
                // 更新分钟框文本与光标位置
                _minuteCtrl.text = newMinute;
                _minuteCtrl.selection = TextSelection.collapsed(offset: newMinute.length);

                // 更新小时框:追加转移字符,保留最后两位
                final newHour = (_hourCtrl.text + transferChar).substring((_hourCtrl.text + transferChar).length - 2);
                _hourCtrl.text = newHour.padLeft(2, '0');
                _hourCtrl.selection = TextSelection.collapsed(offset: newHour.length);

                // 自动切换焦点到小时框
                _hourFocus.requestFocus();
              } else {
                // 不足两位时自动补零,保证显示格式统一
                _minuteCtrl.text = value.padLeft(2, '0');
                _minuteCtrl.selection = TextSelection.collapsed(offset: _minuteCtrl.text.length);
              }
            },
          ),
        ),
      ],
    ),
  ),
],

核心修改说明

  1. 焦点与初始化:默认焦点设置在分钟框,控制器初始值设为00,确保初始显示00:00
  2. 文本转移逻辑:分钟输入超过两位时,将最左侧字符转移到小时框末尾,小时与分钟均保留最后两位,完全匹配需求的输入效果
  3. 格式化调整:移除分钟的范围限制,仅允许数字输入,同时自动补零保持两位显示
  4. 焦点切换:分钟输入溢出时自动切换焦点到小时框,符合需求流程

额外提醒

记得在State的dispose方法中销毁焦点节点与控制器,避免内存泄漏:

@override
void dispose() {
  _hourFocus.dispose();
  _minuteFocus.dispose();
  _hourCtrl.dispose();
  _minuteCtrl.dispose();
  super.dispose();
}

内容的提问来源于stack exchange,提问作者Shubham vyas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 22:35:25