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

Flutter日期输入框实现静态斜杠:仅输入数字无需手动输入斜杠

实现静态斜杠的日期输入框(Flutter)

可以通过自定义文本输入监听和格式化逻辑来实现需求,无需拆分输入框。核心思路是分离显示文本和存储值:视觉上显示带斜杠的格式,内部仅存储纯数字的ddMMyyyy格式,同时限制用户只能输入数字。

完整代码示例

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:flutter/services.dart';

class DateFormField extends StatefulWidget {
  const DateFormField({super.key});

  @override
  State<DateFormField> createState() => _DateFormFieldState();
}

class _DateFormFieldState extends State<DateFormField> {
  final dateOfBirthController = TextEditingController();
  String _rawDate = ''; // 内部存储纯数字的ddMMyyyy格式

  @override
  void initState() {
    super.initState();
    // 添加输入监听,实时格式化显示文本
    dateOfBirthController.addListener(_formatDateInput);
  }

  @override
  void dispose() {
    dateOfBirthController.dispose();
    super.dispose();
  }

  void _formatDateInput() {
    // 过滤掉所有非数字字符
    String input = dateOfBirthController.text.replaceAll(RegExp(r'[^0-9]'), '');
    _rawDate = input; // 更新内部存储的纯数字值

    // 构建带静态斜杠的显示文本
    String formattedText = '';
    if (input.length >= 2) {
      formattedText += input.substring(0, 2);
      if (input.length > 2) formattedText += '/';
    }
    if (input.length >= 4) {
      formattedText += input.substring(2, 4);
      if (input.length > 4) formattedText += '/';
    }
    if (input.length > 4) {
      formattedText += input.substring(4, 8); // 最多保留8位数字
    }

    // 避免无限循环,仅当显示文本变化时更新
    if (dateOfBirthController.text != formattedText) {
      dateOfBirthController.text = formattedText;
      // 将光标定位到文本末尾,提升输入体验
      dateOfBirthController.selection = TextSelection.fromPosition(
        TextPosition(offset: formattedText.length),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      controller: dateOfBirthController,
      keyboardType: TextInputType.number, // 仅显示数字键盘
      decoration: const InputDecoration(
        labelText: '出生日期',
        hintText: 'dd/MM/yyyy',
        hintStyle: TextStyle(color: Colors.grey),
      ),
      inputFormatters: [
        FilteringTextInputFormatter.digitsOnly, // 禁止输入非数字内容
      ],
      onTap: () async {
        // 点击时收起键盘,避免弹出后立即关闭
        FocusScope.of(context).requestFocus(FocusNode());
        final selectedDate = await showDatePicker(
          context: context,
          initialDate: DateTime.now(),
          firstDate: DateTime(1910),
          lastDate: DateTime.now(),
        );
        if (selectedDate != null) {
          // 将选中日期转换为纯数字格式存储
          _rawDate = DateFormat('ddMMyyyy').format(selectedDate);
          // 格式化显示带斜杠的文本
          dateOfBirthController.text = DateFormat('dd/MM/yyyy').format(selectedDate);
        }
      },
      validator: (String? value) {
        if (_rawDate.isEmpty) {
          return '请输入出生日期!';
        }
        if (_rawDate.length != 8) {
          return '请输入完整的出生日期!';
        }
        // 验证日期有效性
        try {
          final day = int.parse(_rawDate.substring(0, 2));
          final month = int.parse(_rawDate.substring(2, 4));
          final year = int.parse(_rawDate.substring(4, 8));
          DateTime(year, month, day); // 非法日期会抛出异常
        } catch (e) {
          return '请输入有效的出生日期!';
        }
        return null;
      },
    );
  }
}

关键逻辑说明

  • 输入监听与格式化:通过addListener实时处理用户输入,过滤非数字字符后,自动插入静态斜杠生成显示文本,同时将纯数字值存入_rawDate。
  • 日期选择器整合:选中日期后,直接转换为纯数字格式存储,同步更新显示文本,保证视觉和数据的一致性。
  • 输入限制:设置数字键盘+FilteringTextInputFormatter.digitsOnly,确保用户只能输入数字,避免误操作。
  • 验证逻辑:直接基于内部存储的纯数字值验证,检查长度和日期有效性,比验证带格式的文本更可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 09:10:15