单位换算大师应用
欢迎加入开源鸿蒙跨平台社区:
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 整体架构图
Business Logic
Data Layer
Presentation Layer
首页
分类概览
换算页
历史页
收藏页
Unit
单位模型
ConversionRecord
换算记录
UnitCategory
类别枚举
单位换算
_calculate
温度转换
_convertTemperature
收藏管理
_favorites
历史管理
_history
2.2 类图设计
manages
uses
uses
references
belongs to
contains
UnitConverterApp
+Widget build()
HomePage
-int _currentIndex
-List<ConversionRecord> _history
-Set<String> _favorites
+Widget build()
-void _toggleFavorite()
-String _formatResult()
ConverterPage
-UnitCategory category
-int _fromIndex
-int _toIndex
-TextEditingController _inputController
-String _result
+Widget build()
-void _calculate()
-double _convertTemperature()
-void _swapUnits()
-void _saveRecord()
Unit
+String name
+String symbol
+double factor
+bool isTemperature
ConversionRecord
+String id
+UnitCategory category
+String fromUnit
+String toUnit
+double fromValue
+double toValue
+DateTime date
<<enumeration>>
UnitCategory
length
weight
area
volume
temperature
time
speed
data
pressure
energy
+String categoryName
+IconData categoryIcon
+Color categoryColor
+List<Unit> units
2.3 数据流程图
普通单位
温度
保存
收藏
复制
用户输入
单位类别
因子换算
非线性换算
baseValue = input × fromFactor
result = baseValue / toFactor
转换为摄氏度
转换为目标温标
格式化结果
显示结果
用户操作
添加历史记录
添加收藏
复制到剪贴板
2.4 换算流程时序图
换算算法 单位模型 换算页 用户 换算算法 单位模型 换算页 用户 alt [普通单位] [温度单位] 选择单位类别 获取单位列表 返回单位数据 选择源单位 选择目标单位 输入数值 执行换算 因子乘除法 非线性转换 返回结果 显示换算结果
三、核心模块设计
3.1 数据模型设计
3.1.1 单位模型 (Unit)
dart
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)
dart
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)
17% 14% 14% 12% 11% 9% 7% 7% 6% 3% 单位类别分布 长度 重量 面积 体积 温度 时间 速度 数据 压强 能量
3.2 单位换算算法
3.2.1 普通单位换算
dart
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 温度换算(非线性)
温度换算采用特殊的非线性转换公式,因为温度刻度不是简单的比例关系:
dart
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 首页模块
首页 _buildHomePage
头部信息卡
分类网格
应用标题
统计数据
换算类别数
历史记录数
收藏单位数
长度卡片
重量卡片
面积卡片
体积卡片
温度卡片
时间卡片
速度卡片
数据卡片
压强卡片
能量卡片
3.3.2 换算页面
点击交换按钮
点击保存
点击复制
点击收藏
选择源单位
选择目标单位
输入数值
实时计算
显示结果
交换单位
保存记录
复制结果
收藏组合
3.3.3 历史记录页面
是
否
历史页
有记录?
记录列表
空状态提示
类别标签
源值/源单位
目标值/目标单位
换算时间
3.4 状态管理
3.4.1 核心状态变量
dart
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 收藏功能实现
dart
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 | 次要文字 |
类别专属颜色:
dart
// 长度 - 蓝色
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 单位数据定义
dart
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 实时计算
dart
@override
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 结果格式化
dart
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 单位交换
dart
void _swapUnits() {
setState(() {
final temp = _fromIndex;
_fromIndex = _toIndex;
_toIndex = temp;
_isReversed = !_isReversed;
_calculate();
});
}
5.5 保存记录
dart
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 温度单位
温标转换
F = C × 9/5 + 32
C = (F-32) × 5/9
K = C + 273.15
C = K - 273.15
摄氏度 °C
华氏度 °F
开尔文 K
| 温标 | 冰点 | 沸点 | 绝对零度 |
|---|---|---|---|
| 摄氏度 (°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 单位制简介
计量单位制
国际单位制 SI
英制单位
中国传统单位
米 m
千克 kg
秒 s
开尔文 K
英尺 ft
磅 lb
加仑 gal
尺
斤
亩
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 精度处理
整数
极小或极大
普通小数
换算结果
判断数值范围
直接显示整数
科学计数法
去除尾部零
toStringAsExponential 6位
toStringAsFixed 10位
正则去除尾部0
八、扩展功能规划
8.1 后续版本规划
2024-01-07 2024-01-14 2024-01-21 2024-01-28 2024-02-04 2024-02-11 2024-02-18 2024-02-25 2024-03-03 2024-03-10 2024-03-17 2024-03-24 单位数据 换算算法 历史收藏 汇率换算 自定义单位 离线使用 换算公式展示 语音输入 小组件支持 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 单位换算大师开发计划
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 运行命令
bash
# 查看可用设备
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最佳实践;数据模型设计合理,便于后续扩展更多单位类别。
核心功能涵盖十大类别单位换算,从长度、重量到能量、压强,从公制到英制再到中国传统单位,满足用户在科学研究、工程设计、日常生活等多场景的换算需求。实时计算功能让用户输入即得结果,历史记录和收藏功能便于快速访问常用换算。
特别值得一提的是温度换算功能,采用非线性转换算法精确处理摄氏度、华氏度、开尔文三种温标之间的转换,确保结果的准确性。通过本应用,希望能够帮助用户轻松应对各类单位换算需求,提升工作和学习效率。
精准换算,一触即达