Flutter如何实现支持kg/lbs切换与数值同步换算的Cupertino重量选择器
代码调整方案
核心思路
统一以千克为基准存储选中重量,单位切换时自动换算为当前单位的数值,同时动态切换重量选择器的展示列表、同步选中位置。
具体修改步骤
1. 调整变量定义
// 重量换算常量 const double kgToLbFactor = 2.20462; // 基准存储:始终存千克单位的重量,初始值对应你原来的150lb double _selectedWeightInKg = 68.0; var _selectedUnits = "lbs"; var units = ['kgs', 'lbs']; var lbs = []; var kgs = []; // 重量选择器控制器,用于单位切换时自动滚动到对应数值位置 FixedExtentScrollController? _weightPickerController;
2. 修改initState初始化逻辑
@override void initState() { super.initState(); for (int j = 22; j <= 227; j++) { kgs.add(j); // 磅数值保留1位小数,可按需调整精度 lbs.add((j * kgToLbFactor).toStringAsFixed(1)); } // 初始化控制器,默认选中当前单位对应重量的索引 _weightPickerController = FixedExtentScrollController( initialItem: _getTargetWeightIndex(), ); } // 工具方法:计算当前单位下选中重量对应的列表索引 int _getTargetWeightIndex() { if (_selectedUnits == 'kgs') { return kgs.indexOf(_selectedWeightInKg.round()); } else { double targetLb = _selectedWeightInKg * kgToLbFactor; // 匹配最接近的磅数值索引 return lbs.indexWhere((lbVal) => double.parse(lbVal) >= targetLb); } } // 工具方法:获取当前单位下要显示的重量数值 double get currentDisplayWeight { return _selectedUnits == 'kgs' ? _selectedWeightInKg : _selectedWeightInKg * kgToLbFactor; }
3. 替换重量选择器逻辑
将原来的第一个CupertinoPicker(重量选择部分)替换为如下代码:
Expanded( child: CupertinoPicker( controller: _weightPickerController, itemExtent: 32, onSelectedItemChanged: (int index) { setState(() { if (_selectedUnits == 'kgs') { _selectedWeightInKg = kgs[index].toDouble(); } else { _selectedWeightInKg = double.parse(lbs[index]) / kgToLbFactor; } }); }, children: List<Widget>.generate( _selectedUnits == 'kgs' ? kgs.length : lbs.length, (int index) { return Center( child: Text( _selectedUnits == 'kgs' ? kgs[index].toString() : lbs[index].toString() ), ); }, ), ), ),
4. 修改单位选择器的切换逻辑
将原来的第二个CupertinoPicker(单位选择部分)的onSelectedItemChanged回调修改为:
onSelectedItemChanged: (int index) { setState(() { _selectedUnits = units[index]; // 切换单位后自动滚动到换算后的重量对应位置 _weightPickerController?.jumpToItem(_getTargetWeightIndex()); }); },
5. 修改显示文本
将按钮上的展示文本替换为:
Text( // 保留1位小数显示,可按需调整精度 '${currentDisplayWeight.toStringAsFixed(1)} $_selectedUnits', style: const TextStyle( height: 1, color: Colors.black, fontSize: 16, ), ),
额外说明
原来代码中写在onSelectedItemChanged回调里的Form校验逻辑无效,Text组件放在回调函数中不会渲染到页面,需要校验可统一在提交表单时处理。
内容的提问来源于stack exchange,提问作者Vamsee.
相关产品推荐
相关产品推荐

