如何像Flutter本地化与主题切换那样实现单位(C、F、K)切换?
最简实现Flutter计量单位切换方案
和切换暗黑模式、语言的思路一致,核心是全局状态管理+组件自动响应更新,无需给每个文本手动添加监听器。下面是具体实现步骤:
1. 定义计量单位枚举
先明确支持的温度单位类型:
enum TemperatureUnit { celsius, fahrenheit, kelvin, }
2. 创建状态管理类
用ChangeNotifier封装当前选中单位、切换逻辑和温度转换方法,让所有需要转换的地方复用统一逻辑:
import 'package:flutter/foundation.dart'; class UnitSettings extends ChangeNotifier { TemperatureUnit _currentUnit = TemperatureUnit.celsius; TemperatureUnit get currentUnit => _currentUnit; // 切换单位并通知组件更新 void switchUnit(TemperatureUnit newUnit) { _currentUnit = newUnit; notifyListeners(); } // 将原始摄氏度值转为当前单位的显示文本 String convertTemperature(double celsiusValue) { double converted; String suffix; switch (_currentUnit) { case TemperatureUnit.celsius: converted = celsiusValue; suffix = '°C'; break; case TemperatureUnit.fahrenheit: converted = celsiusValue * 9/5 + 32; suffix = '°F'; break; case TemperatureUnit.kelvin: converted = celsiusValue + 273.15; suffix = 'K'; break; } return '${converted.toStringAsFixed(1)}$suffix'; } }
3. 在应用顶层注入状态
用ChangeNotifierProvider把状态类挂载到应用根节点,让所有子组件都能访问状态:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; void main() { runApp( ChangeNotifierProvider( create: (context) => UnitSettings(), child: const MyApp(), ), ); }
4. 组件中自动响应状态变化
在需要显示温度的地方,用Consumer监听状态变化,自动更新UI:
// 示例温度显示组件 class TemperatureDisplay extends StatelessWidget { final double celsiusTemp; const TemperatureDisplay({super.key, required this.celsiusTemp}); @override Widget build(BuildContext context) { return Consumer<UnitSettings>( builder: (context, unitSettings, child) { return Text( unitSettings.convertTemperature(celsiusTemp), style: const TextStyle(fontSize: 24), ); }, ); } }
5. 实现单位切换UI
用下拉菜单或按钮组触发单位切换操作:
class UnitSwitcher extends StatelessWidget { const UnitSwitcher({super.key}); @override Widget build(BuildContext context) { final unitSettings = Provider.of<UnitSettings>(context, listen: false); return DropdownButton<TemperatureUnit>( value: unitSettings.currentUnit, items: const [ DropdownMenuItem( value: TemperatureUnit.celsius, child: Text('摄氏度'), ), DropdownMenuItem( value: TemperatureUnit.fahrenheit, child: Text('华氏度'), ), DropdownMenuItem( value: TemperatureUnit.kelvin, child: Text('开尔文'), ), ], onChanged: (newUnit) { if (newUnit != null) { unitSettings.switchUnit(newUnit); } }, ); } }
方案优势
- 贴合Flutter原生Theme、Localizations的设计思路,符合框架使用习惯
- 全局状态统一管理,一次切换操作即可触发所有关联组件自动更新
- 转换逻辑集中封装,后续扩展新单位只需修改状态类,无需改动业务组件
- 用
Consumer精准监听状态变化,性能开销远低于手动添加监听器
内容的提问来源于stack exchange,提问作者Maritn Ge
相关产品推荐
相关产品推荐

