如何拆分TextFormField并在SplittedBox中输入字母数字组合的车牌号?
实现拆分式车牌号输入框(Flutter)

需要实现一个拆分式文本输入框,用于输入由字母和数字组成的车牌号,同时解决拆分输入框中输入这类字符的问题。以下是现有代码片段:
Container( color: Colors.grey[200], padding: EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "Vehicle Number:", style: TextStyle( fontWeight: FontWeight.bold, ), ), Padding( padding: const EdgeInsets.all(10), child: TextFormField( controller: vehicleNo, style: const TextStyle( fontWeight: FontWeight.bold), decoration: InputDecoration( border: UnderlineInputBorder( borderRadius: BorderRadius.circular(5.0), borderSide: const BorderSide( width: 0, style: BorderStyle.none, ), ), fillColor: Colors.white, filled: true, //labelText: 'Vehicle Number.*', contentPadding: const EdgeInsets.symmetric( vertical: 10.0, horizontal: 10.0), ), validator: (value) { if (value == null || value.isEmpty) { return 'Please enter vehicle number'; } else {
解决方案
拆分式输入框可以通过多个TextFormField组合实现,配合焦点自动切换、输入限制来完成车牌号输入需求,具体实现代码如下:
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class VehicleNumberInput extends StatefulWidget { const VehicleNumberInput({super.key}); @override State<VehicleNumberInput> createState() => _VehicleNumberInputState(); } class _VehicleNumberInputState extends State<VehicleNumberInput> { // 对应7位车牌号的输入控制器列表 final List<TextEditingController> _inputControllers = List.generate(7, (index) => TextEditingController()); // 每个输入框的焦点节点列表 final List<FocusNode> _focusNodes = List.generate(7, (index) => FocusNode()); @override void dispose() { // 销毁控制器和焦点节点,避免内存泄漏 for (var controller in _inputControllers) { controller.dispose(); } for (var node in _focusNodes) { node.dispose(); } super.dispose(); } @override Widget build(BuildContext context) { return Container( color: Colors.grey[200], padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "车牌号:", style: TextStyle( fontWeight: FontWeight.bold, ), ), Padding( padding: const EdgeInsets.all(10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: List.generate(7, (index) { return SizedBox( width: 40, child: TextFormField( controller: _inputControllers[index], focusNode: _focusNodes[index], style: const TextStyle(fontWeight: FontWeight.bold), decoration: InputDecoration( border: OutlineInputBorder( borderRadius: BorderRadius.circular(5.0), ), fillColor: Colors.white, filled: true, contentPadding: const EdgeInsets.symmetric( vertical: 10.0, horizontal: 10.0), ), keyboardType: TextInputType.text, maxLength: 1, // 只允许输入字母和数字 inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'[A-Za-z0-9]')), ], onChanged: (value) { // 输入字符后自动跳转到下一个输入框 if (value.isNotEmpty && index < 6) { FocusScope.of(context).requestFocus(_focusNodes[index + 1]); } // 删除字符后自动回到上一个输入框 if (value.isEmpty && index > 0) { FocusScope.of(context).requestFocus(_focusNodes[index - 1]); } }, validator: (value) { if (value == null || value.isEmpty) { return '请输入'; } return null; }, ), ); }), ), ), // 点击获取完整车牌号 ElevatedButton( onPressed: () { String fullVehicleNumber = _inputControllers.map((e) => e.text).join(); print("完整车牌号:$fullVehicleNumber"); }, child: const Text('提交'), ) ], ), ); } }
核心实现要点
- 拆分输入框:用7个
TextFormField对应普通车牌号的7位结构,每个输入框限制最多输入1个字符 - 焦点自动切换:通过
onChanged监听输入状态,输入完成后自动跳转下一个输入框,删除时回到上一个,提升输入流畅度 - 输入内容限制:借助
FilteringTextInputFormatter只允许输入字母和数字,符合车牌号的字符规则 - 资源管理:为每个输入框单独创建控制器和焦点节点,并在页面销毁时释放,避免内存泄漏
内容的提问来源于stack exchange,提问作者Bhavya N
相关产品推荐
相关产品推荐

