一、为什么需要"简易 BMI 计算器"?
在 OpenHarmony 的智慧健康场景中,用户常需快速评估身体状态:
- 家庭健康管理(父母/儿童体重监测);
- 健身目标设定(增肌/减脂参考);
- 医疗预筛(初步判断是否需就医)。
虽然专业设备可测量体脂率、肌肉量,但 BMI(Body Mass Index,身体质量指数) 作为国际通用的初筛工具,仅需身高和体重即可计算,简单、无创、低成本。
公式为:
BMI = 体重(kg) 身高(m) 2 \text{BMI} = \frac{\text{体重(kg)}}{\text{身高(m)}^2} BMI=身高(m)2体重(kg)
例如:体重 70kg,身高 175cm → BMI = 70 / (1.75 × 1.75) ≈ 22.9
本文将构建一个极简页面:「简易 BMI 健康指数计算器」。它只包含:
- 一个身高输入框(单位:厘米);
- 一个体重输入框(单位:公斤);
- 一个"计算"按钮;
- 两行结果显示区(如 "BMI: 22.9" 和 "正常范围")。
所有逻辑基于浮点运算与条件分支,无外部依赖,完全在应用内闭环。
二、完整可运行代码
dart
// lib/main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'BMI 计算器',
debugShowCheckedModeBanner: false,
theme: ThemeData(useMaterial3: true, colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal)),
home: const BmiCalculatorPage(),
);
}
}
class BmiCalculatorPage extends StatefulWidget {
const BmiCalculatorPage({super.key});
@override
State<BmiCalculatorPage> createState() => _BmiCalculatorPageState();
}
class _BmiCalculatorPageState extends State<BmiCalculatorPage> {
final TextEditingController _heightController = TextEditingController();
final TextEditingController _weightController = TextEditingController();
String _bmiResult = '';
String _categoryResult = '';
void _calculateBmi() {
final heightStr = _heightController.text.trim();
final weightStr = _weightController.text.trim();
if (heightStr.isEmpty || weightStr.isEmpty) {
setState(() {
_bmiResult = '请输入身高和体重';
_categoryResult = '';
});
return;
}
double? heightCm = double.tryParse(heightStr);
double? weightKg = double.tryParse(weightStr);
if (heightCm == null || weightKg == null || heightCm <= 0 || weightKg <= 0) {
setState(() {
_bmiResult = '请输入有效数值';
_categoryResult = '';
});
return;
}
final heightM = heightCm / 100;
final bmi = weightKg / (heightM * heightM);
final category = _getCategory(bmi);
setState(() {
_bmiResult = 'BMI: ${bmi.toStringAsFixed(1)}';
_categoryResult = category;
});
}
String _getCategory(double bmi) {
if (bmi < 18.5) return '体重过轻';
if (bmi < 24.0) return '正常范围';
if (bmi < 28.0) return '超重';
return '肥胖';
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('BMI 健康指数')),
body: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
TextField(
controller: _heightController,
keyboardType: TextInputType.numberWithOptions(decimal: true),
decoration: const InputDecoration(labelText: '身高 (cm)'),
),
TextField(
controller: _weightController,
keyboardType: TextInputType.numberWithOptions(decimal: true),
decoration: const InputDecoration(labelText: '体重 (kg)'),
),
const SizedBox(height: 24),
ElevatedButton(onPressed: _calculateBmi, child: const Text('计算 BMI')),
const SizedBox(height: 24),
Text(_bmiResult, style: const TextStyle(fontSize: 18)),
Text(_categoryResult, style: const TextStyle(fontSize: 16, color: Colors.grey)),
],
),
),
);
}
}
三、设计原则:科学、清晰、无误导
BMI 虽是初筛工具,但错误解读可能引发焦虑。因此本页面设计强调:
- 明确单位:标注 "cm" 和 "kg",避免混淆;
- 有效范围校验:拒绝负数或零值;
- 分级说明:使用"体重过轻""正常范围"等中性词汇,而非"瘦""胖"等主观表述;
- 不提供医疗建议:仅显示分类,不推荐饮食或运动方案。
这种克制的设计,符合健康类应用的伦理要求。
四、安全输入解析与 BMI 计算:
我们首先看核心计算逻辑:
dart
void _calculateBmi() {
final heightStr = _heightController.text.trim();
final weightStr = _weightController.text.trim();
if (heightStr.isEmpty || weightStr.isEmpty) {
setState(() {
_bmiResult = '请输入身高和体重';
_categoryResult = '';
});
return;
}
double? heightCm = double.tryParse(heightStr);
double? weightKg = double.tryParse(weightStr);
if (heightCm == null || weightKg == null || heightCm <= 0 || weightKg <= 0) {
setState(() {
_bmiResult = '请输入有效数值';
_categoryResult = '';
});
return;
}
final heightM = heightCm / 100;
final bmi = weightKg / (heightM * heightM);
final category = _getCategory(bmi);
setState(() {
_bmiResult = 'BMI: ${bmi.toStringAsFixed(1)}';
_categoryResult = category;
});
}


这段代码实现了健壮的健康计算流程。
- 空值检查:先判断是否为空,避免无效解析;
double.tryParse:- 安全转换字符串为
double?; - 支持整数("175")和小数("68.5");
- 安全转换字符串为
- 有效性校验 :
- 排除
null(非数字输入); - 排除 ≤0 值(身高/体重不能为零或负);
- 排除
- 单位转换 :
- 将厘米转为米(
/ 100),符合公式要求;
- 将厘米转为米(
- 格式化输出 :
toStringAsFixed(1)保留一位小数(如 22.86 → "22.9"),避免冗长数字。
💡 此设计不处理极端值(如身高 300cm),因面向普通用户,假设输入合理。
五、健康分级逻辑:
再看 BMI 分级函数:
dart
String _getCategory(double bmi) {
if (bmi < 18.5) return '体重过轻';
if (bmi < 24.0) return '正常范围';
if (bmi < 28.0) return '超重';
return '肥胖';
}

这里采用中国成人 BMI 标准(区别于 WHO 国际标准):
- < 18.5:体重过轻;
- 18.5 -- 23.9:正常范围;
- 24.0 -- 27.9:超重;
- ≥ 28.0:肥胖。
📌 为何用
< 24.0而非<= 23.9?因浮点数精度问题,
23.95可能被四舍五入为 24.0,但实际属于正常范围。使用< 24.0更安全,覆盖 [18.5, 24.0) 区间。
此函数纯计算、无副作用,易于测试和维护。
六、为何这个计算器适合 OpenHarmony 场景?
1. 健康普惠
- 无需智能体脂秤,仅用手机即可初筛;
- 适合家庭共享(老人、儿童均可使用)。
2. 隐私安全
- 所有计算在本地完成;
- 不上传数据,不申请网络权限;
- 关闭即清空,无隐私残留。
3. 教育价值
- 向用户普及 BMI 概念;
- 展示数学公式在生活中的应用。
更重要的是,它不替代医疗诊断,仅提供参考,符合健康类应用的合规边界。
七、工程注意事项
1. 输入体验优化
TextInputType.numberWithOptions(decimal: true)允许输入小数;- 自动聚焦下一个输入框(可通过
FocusNode实现,但为简洁未加入)。
2. 国际化扩展
- 当前文本为中文,若需多语言,可提取字符串常量;
- 但本文聚焦功能,未引入复杂度。
3. 精度说明
- BMI 是粗略指标,不区分肌肉与脂肪;
- 页面虽未声明,但开发者应知晓其局限性。
八、结语:用数学,守护健康起点
本文的页面仅 68 行代码,却将一个国际通用的健康指标,转化为简单、可用、可信的交互工具。它没有连接云端,没有 AI 分析,只有清晰的输入、可靠的计算、负责任的输出。
在 OpenHarmony 构建的智慧健康生态中,我们应始终铭记:技术的价值,不在于多先进,而在于多可靠。
这个小小的 BMI 计算器,正是对这一理念的践行。
🌐 欢迎加入开源鸿蒙跨平台社区 :
在这里,您将获得:
- OpenHarmony 健康类应用设计规范;
- Flutter 安全数值处理模板;
- 无依赖实用工具开发指南。
用科学,服务生活。