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
相关产品推荐
相关产品推荐

