Flutter ToggleButtons添加可编辑数值并同步至指定输入框的实现问询
实现方案
核心思路
- 为每个餐食(Breakfast/Lunch/Tea)单独创建输入框控制器,预设默认值
- 配置
ToggleButtons为单选模式,选中时将对应餐食输入框的值同步到目标控制器numR3C2controller - 限制输入框仅允许数字和小数输入,同时支持实时同步(选中状态下修改餐食值时自动更新目标输入框)
完整代码示例
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class MealCarbsPage extends StatefulWidget { const MealCarbsPage({super.key}); @override State<MealCarbsPage> createState() => _MealCarbsPageState(); } class _MealCarbsPageState extends State<MealCarbsPage> { // 控制ToggleButtons选中状态(单选) List<bool> isSelected = [false, false, false]; // 餐食输入框控制器,预设默认值 final TextEditingController breakfastController = TextEditingController(text: '1.0'); final TextEditingController lunchController = TextEditingController(text: '0.6'); final TextEditingController teaController = TextEditingController(text: '0.55'); // 目标计算输入框控制器 final TextEditingController numR3C2Controller = TextEditingController(); @override void dispose() { // 销毁控制器避免内存泄漏 breakfastController.dispose(); lunchController.dispose(); teaController.dispose(); numR3C2Controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Meal Carbs Calculator')), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // 餐食选择ToggleButtons ToggleButtons( isSelected: isSelected, onPressed: (index) { setState(() { // 切换单选状态 for (int i = 0; i < isSelected.length; i++) { isSelected[i] = i == index; } // 同步选中餐食的值到目标输入框 switch(index) { case 0: numR3C2Controller.text = breakfastController.text; break; case 1: numR3C2Controller.text = lunchController.text; break; case 2: numR3C2Controller.text = teaController.text; break; } }); }, children: const [ Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: Text('Breakfast'), ), Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: Text('Lunch'), ), Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: Text('Tea'), ), ], ), const SizedBox(height: 20), // Breakfast输入框 TextField( controller: breakfastController, keyboardType: TextInputType.numberWithOptions(decimal: true), inputFormatters: [ // 仅允许数字和小数点输入 FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d*$')), ], decoration: const InputDecoration( labelText: 'Breakfast Ratio', border: OutlineInputBorder(), ), onChanged: (value) { // 如果当前选中Breakfast,实时同步到目标输入框 if (isSelected[0]) { numR3C2Controller.text = value; } }, ), const SizedBox(height: 12), // Lunch输入框 TextField( controller: lunchController, keyboardType: TextInputType.numberWithOptions(decimal: true), inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d*$')), ], decoration: const InputDecoration( labelText: 'Lunch Ratio', border: OutlineInputBorder(), ), onChanged: (value) { if (isSelected[1]) { numR3C2Controller.text = value; } }, ), const SizedBox(height: 12), // Tea输入框 TextField( controller: teaController, keyboardType: TextInputType.numberWithOptions(decimal: true), inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'^\d+\.?\d*$')), ], decoration: const InputDecoration( labelText: 'Tea Ratio', border: OutlineInputBorder(), ), onChanged: (value) { if (isSelected[2]) { numR3C2Controller.text = value; } }, ), const SizedBox(height: 20), // 目标计算输入框(Meal Carbs) TextField( controller: numR3C2Controller, keyboardType: TextInputType.numberWithOptions(decimal: true), decoration: const InputDecoration( labelText: 'Meal Carbs', border: OutlineInputBorder(), hintText: 'Selected meal ratio will sync here', ), ), ], ), ), ); } }
关键细节说明
- 单选ToggleButtons:通过遍历
isSelected列表,确保每次只有一个按钮处于选中状态,符合餐食单选的需求 - 输入限制:使用
FilteringTextInputFormatter配合正则表达式r'^\d+\.?\d*$',严格限制输入内容为数字和最多一个小数点;同时设置keyboardType为数字键盘,提升输入体验 - 双向同步:不仅在选中按钮时同步值,当选中状态下修改餐食输入框内容时,也会实时更新目标输入框,保证数值一致性
- 内存管理:在
dispose方法中销毁所有控制器,避免Flutter内存泄漏问题
内容的提问来源于stack exchange,提问作者rnmuk
相关产品推荐
相关产品推荐

