Flutter 框架跨平台鸿蒙开发 - 单位换算大师应用
运行效果图单位换算大师是一款功能全面的单位转换工具,旨在帮助用户快速、准确地进行各类单位之间的换算。在科学研究、工程设计、日常生活、国际贸易等场景中,单位换算是一项基础而重要的工作。本应用整合了长度、重量、面积、体积、温度、时间、速度、数据、压强、能量等十大类单位,支持公制、英制、中国传统单位等多种计量体系,让单位换算变得简单高效。从纳米级的微观测量到光年级的宇宙尺度,从微克的精密称量到吨级的工业
单位换算大师应用
欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net
一、项目概述
运行效果图




1.1 应用简介
单位换算大师是一款功能全面的单位转换工具,旨在帮助用户快速、准确地进行各类单位之间的换算。在科学研究、工程设计、日常生活、国际贸易等场景中,单位换算是一项基础而重要的工作。本应用整合了长度、重量、面积、体积、温度、时间、速度、数据、压强、能量等十大类单位,支持公制、英制、中国传统单位等多种计量体系,让单位换算变得简单高效。
从纳米级的微观测量到光年级的宇宙尺度,从微克的精密称量到吨级的工业计量,本应用覆盖了广泛的换算需求。特别是温度换算,采用非线性转换算法,精确处理摄氏度、华氏度、开尔文三种温标之间的转换关系。
1.2 核心功能
| 功能模块 | 功能描述 | 实现方式 |
|---|---|---|
| 多类别换算 | 支持10大类别单位换算 | 枚举分类 + 因子转换 |
| 温度换算 | 摄氏/华氏/开尔文互转 | 非线性转换算法 |
| 历史记录 | 保存换算记录便于查阅 | List集合 + 状态管理 |
| 收藏功能 | 收藏常用换算组合 | Set集合 + 快捷访问 |
| 单位交换 | 快速交换源/目标单位 | 状态切换 |
| 结果复制 | 一键复制换算结果 | 剪贴板API |
1.3 单位类别概览
| 类别 | 英文标识 | 图标 | 颜色 | 单位数量 | 代表单位 |
|---|---|---|---|---|---|
| 长度 | length | straighten | 蓝色 | 16 | 米、千米、英尺、英寸 |
| 重量 | weight | scale | 绿色 | 11 | 千克、克、磅、盎司 |
| 面积 | area | crop_square | 橙色 | 13 | 平方米、公顷、亩 |
| 体积 | volume | water_drop | 青色 | 13 | 升、毫升、加仑 |
| 温度 | temperature | thermostat | 红色 | 3 | 摄氏度、华氏度、开尔文 |
| 时间 | time | access_time | 紫色 | 10 | 秒、分、时、天 |
| 速度 | speed | speed | 靛蓝色 | 6 | 米/秒、千米/时、马赫 |
| 数据 | data | storage | 蓝绿色 | 7 | 字节、KB、MB、GB |
| 压强 | pressure | compress | 棕色 | 7 | 帕斯卡、大气压、psi |
| 能量 | energy | bolt | 琥珀色 | 9 | 焦耳、卡路里、千瓦时 |
1.4 技术栈
| 技术领域 | 技术选型 | 版本要求 |
|---|---|---|
| 开发框架 | Flutter | >= 3.0.0 |
| 编程语言 | Dart | >= 2.17.0 |
| 设计规范 | Material Design 3 | - |
| 状态管理 | setState | - |
| 目标平台 | 鸿蒙OS | API 21+ |
1.5 项目结构
lib/
└── main_unit_converter.dart
├── UnitConverterApp # 应用入口
├── UnitCategory # 单位类别枚举
├── Unit # 单位模型
├── ConversionRecord # 换算记录模型
├── HomePage # 主页面
│ ├── _buildHomePage() # 首页
│ ├── _buildCategoryPage() # 分类页
│ ├── _buildHistoryPage() # 历史页
│ └── _buildFavoritesPage() # 收藏页
└── ConverterPage # 换算页面
二、系统架构
2.1 整体架构图
2.2 类图设计
2.3 数据流程图
2.4 换算流程时序图
三、核心模块设计
3.1 数据模型设计
3.1.1 单位模型 (Unit)
class Unit {
final String name; // 单位名称(中文)
final String symbol; // 单位符号
final double factor; // 转换因子(相对于基准单位)
final bool isTemperature; // 是否为温度单位
}
转换原理说明:
基准值=输入值×源单位因子 \text{基准值} = \text{输入值} \times \text{源单位因子} 基准值=输入值×源单位因子
结果值=基准值目标单位因子 \text{结果值} = \frac{\text{基准值}}{\text{目标单位因子}} 结果值=目标单位因子基准值
3.1.2 换算记录模型 (ConversionRecord)
class ConversionRecord {
final String id; // 唯一标识
final UnitCategory category; // 单位类别
final String fromUnit; // 源单位
final String toUnit; // 目标单位
final double fromValue; // 源值
final double toValue; // 目标值
final DateTime date; // 换算时间
}
3.1.3 单位类别枚举 (UnitCategory)
3.2 单位换算算法
3.2.1 普通单位换算
void _calculate() {
final input = double.tryParse(_inputController.text);
if (input == null) return;
final fromUnit = widget.category.units[_fromIndex];
final toUnit = widget.category.units[_toIndex];
// 转换为基准单位值
final baseValue = input * fromUnit.factor;
// 转换为目标单位值
final result = baseValue / toUnit.factor;
}
3.2.2 温度换算(非线性)
温度换算采用特殊的非线性转换公式,因为温度刻度不是简单的比例关系:
double _convertTemperature(double value, String from, String to) {
// 第一步:转换为摄氏度
double celsius;
switch (from) {
case '°C':
celsius = value;
break;
case '°F':
celsius = (value - 32) * 5 / 9;
break;
case 'K':
celsius = value - 273.15;
break;
}
// 第二步:从摄氏度转换为目标温标
switch (to) {
case '°C':
return celsius;
case '°F':
return celsius * 9 / 5 + 32;
case 'K':
return celsius + 273.15;
}
}
温度转换公式:
| 转换方向 | 公式 |
|---|---|
| °C → °F | F=C×95+32F = C \times \frac{9}{5} + 32F=C×59+32 |
| °F → °C | C=(F−32)×59C = (F - 32) \times \frac{5}{9}C=(F−32)×95 |
| °C → K | K=C+273.15K = C + 273.15K=C+273.15 |
| K → °C | C=K−273.15C = K - 273.15C=K−273.15 |
3.3 页面结构设计
3.3.1 首页模块
3.3.2 换算页面
3.3.3 历史记录页面
3.4 状态管理
3.4.1 核心状态变量
class _HomePageState extends State<HomePage> {
// 导航状态
int _currentIndex = 0;
// 数据状态
final List<ConversionRecord> _history = [];
final Set<String> _favorites = {};
}
class _ConverterPageState extends State<ConverterPage> {
// 换算状态
late int _fromIndex;
late int _toIndex;
final TextEditingController _inputController = TextEditingController();
String _result = '';
bool _isReversed = false;
}
3.4.2 收藏功能实现
String get _favoriteKey {
// 格式: 类别索引|源单位索引|目标单位索引
return '${widget.category.index}|$_fromIndex|$_toIndex';
}
void _toggleFavorite(String key) {
setState(() {
if (_favorites.contains(key)) {
_favorites.remove(key);
} else {
_favorites.add(key);
}
});
}
四、UI设计规范
4.1 配色方案
应用采用浅色主题设计,营造清爽专业的氛围:
| 颜色类型 | 色值 | 用途 |
|---|---|---|
| 主色 | #1976D2 (Blue) | AppBar、按钮、强调元素 |
| 背景色 | #F5F5F5 | 页面背景 |
| 卡片背景 | #FFFFFF | 卡片、弹窗 |
| 文字主色 | #000000 | 主要文字 |
| 文字次色 | #757575 | 次要文字 |
类别专属颜色:
// 长度 - 蓝色
Colors.blue
// 重量 - 绿色
Colors.green
// 面积 - 橙色
Colors.orange
// 体积 - 青色
Colors.cyan
// 温度 - 红色
Colors.red
// 时间 - 紫色
Colors.purple
// 速度 - 靛蓝色
Colors.indigo
// 数据 - 蓝绿色
Colors.teal
// 压强 - 棕色
Colors.brown
// 能量 - 琥珀色
Colors.amber
4.2 字体规范
| 元素 | 字号 | 字重 | 颜色 |
|---|---|---|---|
| 输入数值 | 32px | Bold | #000000 |
| 换算结果 | 36px | Bold | 类别色 |
| 单位名称 | 16px | Medium | #000000 |
| 单位符号 | 12px | Regular | #757575 |
| 类别标签 | 14px | Medium | #000000 |
4.3 组件规范
4.3.1 分类卡片
┌─────────────────────────────┐
│ ┌────┐ │
│ │ 📏 │ │
│ └────┘ │
│ 长度 │
│ 16 单位 │
└─────────────────────────────┘
4.3.2 换算面板
┌─────────────────────────────────────────────────┐
│ 从 ⇄ 到 │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 米 ▼ │ │ 千米 ▼ │ │
│ └─────────────┘ └─────────────┘ │
│ │
│ 1000 │
│ 米 │
│ │
│ = │
│ │
│ 1 │
│ 千米 │
│ │
│ [复制结果] [保存记录] │
└─────────────────────────────────────────────────┘
4.3.3 历史记录卡片
┌─────────────────────────────────────────────────┐
│ [长度] 1/25 14:30 │
│ │
│ 1000 1 │
│ 米 → 千米 │
└─────────────────────────────────────────────────┘
五、核心功能实现
5.1 单位数据定义
List<Unit> get units {
switch (this) {
case UnitCategory.length:
return [
Unit('千米', 'km', 1000),
Unit('米', 'm', 1),
Unit('分米', 'dm', 0.1),
Unit('厘米', 'cm', 0.01),
Unit('毫米', 'mm', 0.001),
// ... 更多单位
];
// ... 其他类别
}
}
5.2 实时计算
void initState() {
super.initState();
_inputController.addListener(_calculate);
}
void _calculate() {
final input = double.tryParse(_inputController.text);
if (input == null) {
setState(() => _result = '');
return;
}
final fromUnit = widget.category.units[_fromIndex];
final toUnit = widget.category.units[_toIndex];
double result;
if (widget.category == UnitCategory.temperature) {
result = _convertTemperature(input, fromUnit.symbol, toUnit.symbol);
} else {
final baseValue = input * fromUnit.factor;
result = baseValue / toUnit.factor;
}
setState(() => _result = _formatResult(result));
}
5.3 结果格式化
String _formatResult(double value) {
if (value == value.toInt()) {
return value.toInt().toString();
} else if (value.abs() < 0.001 || value.abs() > 1000000) {
return value.toStringAsExponential(6);
} else {
return value
.toStringAsFixed(10)
.replaceAll(RegExp(r'0+$'), '')
.replaceAll(RegExp(r'\.$'), '');
}
}
5.4 单位交换
void _swapUnits() {
setState(() {
final temp = _fromIndex;
_fromIndex = _toIndex;
_toIndex = temp;
_isReversed = !_isReversed;
_calculate();
});
}
5.5 保存记录
void _saveRecord() {
final input = double.tryParse(_inputController.text);
if (input == null || _result.isEmpty) return;
final record = ConversionRecord(
id: DateTime.now().millisecondsSinceEpoch.toString(),
category: widget.category,
fromUnit: widget.category.units[_fromIndex].name,
toUnit: widget.category.units[_toIndex].name,
fromValue: input,
toValue: double.tryParse(_result) ?? 0,
date: DateTime.now(),
);
widget.onConvert(record);
}
六、单位数据详解
6.1 长度单位
| 单位名称 | 符号 | 转换因子 | 说明 |
|---|---|---|---|
| 千米 | km | 1000 | 公制 |
| 米 | m | 1 | 基准单位 |
| 分米 | dm | 0.1 | 公制 |
| 厘米 | cm | 0.01 | 公制 |
| 毫米 | mm | 0.001 | 公制 |
| 微米 | μm | 0.000001 | 公制 |
| 纳米 | nm | 0.000000001 | 公制 |
| 英里 | mi | 1609.344 | 英制 |
| 码 | yd | 0.9144 | 英制 |
| 英尺 | ft | 0.3048 | 英制 |
| 英寸 | in | 0.0254 | 英制 |
| 海里 | nmi | 1852 | 航海 |
| 里 | 里 | 500 | 中国传统 |
| 丈 | 丈 | 3.33333333 | 中国传统 |
| 尺 | 尺 | 0.33333333 | 中国传统 |
| 寸 | 寸 | 0.03333333 | 中国传统 |
6.2 重量单位
| 单位名称 | 符号 | 转换因子 | 说明 |
|---|---|---|---|
| 吨 | t | 1000 | 公制 |
| 千克 | kg | 1 | 基准单位 |
| 克 | g | 0.001 | 公制 |
| 毫克 | mg | 0.000001 | 公制 |
| 微克 | μg | 0.000000001 | 公制 |
| 磅 | lb | 0.45359237 | 英制 |
| 盎司 | oz | 0.028349523 | 英制 |
| 斤 | 斤 | 0.5 | 中国传统 |
| 两 | 两 | 0.05 | 中国传统 |
| 钱 | 钱 | 0.005 | 中国传统 |
| 克拉 | ct | 0.0002 | 珠宝 |
6.3 面积单位
| 单位名称 | 符号 | 转换因子 | 说明 |
|---|---|---|---|
| 平方千米 | km² | 1000000 | 公制 |
| 公顷 | ha | 10000 | 公制 |
| 公亩 | a | 100 | 公制 |
| 平方米 | m² | 1 | 基准单位 |
| 平方分米 | dm² | 0.01 | 公制 |
| 平方厘米 | cm² | 0.0001 | 公制 |
| 平方毫米 | mm² | 0.000001 | 公制 |
| 平方英里 | mi² | 2589988.11 | 英制 |
| 英亩 | ac | 4046.8564224 | 英制 |
| 平方英尺 | ft² | 0.09290304 | 英制 |
| 平方英寸 | in² | 0.00064516 | 英制 |
| 亩 | 亩 | 666.6666667 | 中国传统 |
| 顷 | 顷 | 66666.666667 | 中国传统 |
6.4 体积单位
| 单位名称 | 符号 | 转换因子 | 说明 |
|---|---|---|---|
| 立方米 | m³ | 1 | 基准单位 |
| 立方分米 | dm³ | 0.001 | 公制 |
| 立方厘米 | cm³ | 0.000001 | 公制 |
| 升 | L | 0.001 | 公制 |
| 毫升 | mL | 0.000001 | 公制 |
| 加仑(美) | gal | 0.00378541 | 美制 |
| 夸脱(美) | qt | 0.00094635 | 美制 |
| 品脱(美) | pt | 0.00047318 | 美制 |
| 液量盎司(美) | fl oz | 0.00002957 | 美制 |
| 桶(石油) | bbl | 0.158987 | 石油工业 |
6.5 温度单位
| 温标 | 冰点 | 沸点 | 绝对零度 |
|---|---|---|---|
| 摄氏度 (°C) | 0 | 100 | -273.15 |
| 华氏度 (°F) | 32 | 212 | -459.67 |
| 开尔文 (K) | 273.15 | 373.15 | 0 |
6.6 时间单位
| 单位名称 | 符号 | 转换因子 |
|---|---|---|
| 年 | y | 31536000 |
| 月 | mo | 2592000 |
| 周 | wk | 604800 |
| 天 | d | 86400 |
| 小时 | h | 3600 |
| 分钟 | min | 60 |
| 秒 | s | 1 |
| 毫秒 | ms | 0.001 |
| 微秒 | μs | 0.000001 |
| 纳秒 | ns | 0.000000001 |
6.7 速度单位
| 单位名称 | 符号 | 转换因子 | 说明 |
|---|---|---|---|
| 米/秒 | m/s | 1 | 基准单位 |
| 千米/时 | km/h | 0.277778 | 常用 |
| 英里/时 | mph | 0.44704 | 英制 |
| 节 | kn | 0.514444 | 航海 |
| 马赫 | Ma | 340.29 | 音速 |
| 光速 | c | 299792458 | 物理常数 |
6.8 数据单位
| 单位名称 | 符号 | 转换因子 |
|---|---|---|
| 比特 | bit | 0.125 |
| 字节 | B | 1 |
| 千字节 | KB | 1024 |
| 兆字节 | MB | 1048576 |
| 吉字节 | GB | 1073741824 |
| 太字节 | TB | 1099511627776 |
| 拍字节 | PB | 1125899906842624 |
6.9 压强单位
| 单位名称 | 符号 | 转换因子 | 说明 |
|---|---|---|---|
| 帕斯卡 | Pa | 1 | 基准单位 |
| 千帕 | kPa | 1000 | 公制 |
| 兆帕 | MPa | 1000000 | 工程常用 |
| 巴 | bar | 100000 | 气象 |
| 标准大气压 | atm | 101325 | 物理 |
| 毫米汞柱 | mmHg | 133.322 | 医学 |
| 磅/平方英寸 | psi | 6894.76 | 英制 |
6.10 能量单位
| 单位名称 | 符号 | 转换因子 | 说明 |
|---|---|---|---|
| 焦耳 | J | 1 | 基准单位 |
| 千焦 | kJ | 1000 | 公制 |
| 兆焦 | MJ | 1000000 | 公制 |
| 卡路里 | cal | 4.184 | 热学 |
| 千卡 | kcal | 4184 | 营养学 |
| 瓦时 | Wh | 3600 | 电力 |
| 千瓦时 | kWh | 3600000 | 电表单位 |
| 电子伏特 | eV | 1.602e-16 | 物理 |
| 英热单位 | BTU | 1055.06 | 英制 |
七、换算知识
7.1 单位制简介
7.2 换算原理
线性换算:大多数单位采用线性换算关系
Vtarget=Vsource×FsourceFtarget V_{target} = V_{source} \times \frac{F_{source}}{F_{target}} Vtarget=Vsource×FtargetFsource
非线性换算:温度等特殊单位需要特殊处理
T°F=T°C×95+32 T_{°F} = T_{°C} \times \frac{9}{5} + 32 T°F=T°C×59+32
7.3 精度处理
八、扩展功能规划
8.1 后续版本规划
8.2 功能扩展建议
8.2.1 汇率换算
接入实时汇率数据:
- 支持全球主要货币
- 实时汇率更新
- 历史汇率查询
8.2.2 自定义单位
允许用户添加自定义单位:
- 定义单位名称和符号
- 设置转换因子
- 分享自定义单位库
8.2.3 换算公式展示
显示详细换算过程:
- 展示换算公式
- 分步骤计算过程
- 教育学习用途
九、注意事项
9.1 开发注意事项
-
温度换算:温度采用非线性换算,不能使用因子乘除法
-
精度处理:大数和小数需要科学计数法显示
-
因子精度:转换因子使用高精度数值,避免累积误差
-
单位符号:特殊符号如 μ 需要正确编码
9.2 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 温度换算错误 | 使用了因子法 | 使用专门的温度转换函数 |
| 精度丢失 | 因子精度不足 | 使用更高精度的因子值 |
| 显示异常 | 数值过大或过小 | 使用科学计数法格式化 |
9.3 精度说明
⚠️ 精度提示 ⚠️
本应用的换算因子采用标准值,部分单位换算可能存在微小误差。
对于高精度要求的科学计算,建议使用专业工具验证结果。
十、运行说明
10.1 环境要求
| 环境 | 版本要求 |
|---|---|
| Flutter SDK | >= 3.0.0 |
| Dart SDK | >= 2.17.0 |
| 鸿蒙OS | API 21+ |
10.2 运行命令
# 查看可用设备
flutter devices
# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_unit_converter.dart
# 运行到Windows
flutter run -d windows -t lib/main_unit_converter.dart
# 代码分析
flutter analyze lib/main_unit_converter.dart
十一、总结
单位换算大师通过直观的界面设计和精准的换算算法,为用户提供了一个便捷的单位转换工具。应用采用浅色主题设计,符合清爽专业的定位;代码结构清晰,遵循Flutter最佳实践;数据模型设计合理,便于后续扩展更多单位类别。
核心功能涵盖十大类别单位换算,从长度、重量到能量、压强,从公制到英制再到中国传统单位,满足用户在科学研究、工程设计、日常生活等多场景的换算需求。实时计算功能让用户输入即得结果,历史记录和收藏功能便于快速访问常用换算。
特别值得一提的是温度换算功能,采用非线性转换算法精确处理摄氏度、华氏度、开尔文三种温标之间的转换,确保结果的准确性。通过本应用,希望能够帮助用户轻松应对各类单位换算需求,提升工作和学习效率。
精准换算,一触即达
更多推荐



所有评论(0)