Flutter中如何实现填写一个输入框后自动填充其他关联输入框的值
实现方案
该功能无需引入第三方插件,基于Flutter原生能力即可实现。核心逻辑是通过输入框控制器的监听事件触发联动换算,同时增加更新锁避免循环触发更新。
完整可运行代码
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void main() => runApp(const UnitConverterApp()); class UnitConverterApp extends StatelessWidget { const UnitConverterApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: '单位换算', home: Scaffold( appBar: AppBar(title: const Text('长度单位换算')), body: const LengthConverter(), ), ); } } class LengthConverter extends StatefulWidget { const LengthConverter({super.key}); @override State<LengthConverter> createState() => _LengthConverterState(); } class _LengthConverterState extends State<LengthConverter> { // 定义三个输入框的控制器 final _meterController = TextEditingController(); final _cmController = TextEditingController(); final _feetController = TextEditingController(); // 更新锁,避免循环触发监听 bool _isUpdating = false; @override void initState() { super.initState(); // 给每个控制器添加监听 _meterController.addListener(() => _onInputChanged(UnitType.meter)); _cmController.addListener(() => _onInputChanged(UnitType.centimeter)); _feetController.addListener(() => _onInputChanged(UnitType.feet)); } // 输入变更触发的换算逻辑 void _onInputChanged(UnitType activeType) { if (_isUpdating) return; _isUpdating = true; try { double? inputValue; // 读取当前激活输入框的值 switch (activeType) { case UnitType.meter: inputValue = double.tryParse(_meterController.text.trim()); break; case UnitType.centimeter: inputValue = double.tryParse(_cmController.text.trim()); break; case UnitType.feet: inputValue = double.tryParse(_feetController.text.trim()); break; } // 输入为空或者非法时清空所有输入框 if (inputValue == null) { _meterController.clear(); _cmController.clear(); _feetController.clear(); _isUpdating = false; return; } // 统一转换为米作为基准值 double meterValue; switch (activeType) { case UnitType.meter: meterValue = inputValue; break; case UnitType.centimeter: meterValue = inputValue / 100; break; case UnitType.feet: meterValue = inputValue / 3.28084; break; } // 更新其他输入框的值 if (activeType != UnitType.meter) { _meterController.text = meterValue.toStringAsFixed(4); } if (activeType != UnitType.centimeter) { _cmController.text = (meterValue * 100).toStringAsFixed(2); } if (activeType != UnitType.feet) { _feetController.text = (meterValue * 3.28084).toStringAsFixed(4); } } finally { _isUpdating = false; } } @override void dispose() { // 销毁控制器,避免内存泄漏 _meterController.dispose(); _cmController.dispose(); _feetController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ _buildInputItem('米 (m)', _meterController), const SizedBox(height: 16), _buildInputItem('厘米 (cm)', _cmController), const SizedBox(height: 16), _buildInputItem('英尺 (ft)', _feetController), ], ), ); } // 复用输入框组件 Widget _buildInputItem(String label, TextEditingController controller) { return TextField( controller: controller, keyboardType: const TextInputType.numberWithOptions(decimal: true), inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d*'))], decoration: InputDecoration( labelText: label, border: const OutlineInputBorder(), ), ); } } // 单位类型枚举 enum UnitType { meter, centimeter, feet, }
注意事项
- 如果需要新增换算单位,只需新增对应的
TextEditingController、UnitType枚举值,补充换算逻辑和输入框组件即可 - 代码中已经添加了输入校验,仅允许输入数字和小数点,可根据需求修改
inputFormatters调整校验规则 toStringAsFixed用来控制输出的小数位数,可根据实际精度需求调整- 如果项目中已经使用状态管理框架(如Provider、Bloc等),也可以把换算逻辑放到状态层实现,适配更复杂的业务场景
内容的提问来源于stack exchange,提问作者MNBLabs
相关产品推荐
相关产品推荐

