构建 OpenHarmony 简易 BMI 健康指数计算器:用基础数学实现健康自评

一、为什么需要"简易 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 计算器,正是对这一理念的践行。

🌐 欢迎加入开源鸿蒙跨平台社区

https://openharmonycrossplatform.csdn.net/

在这里,您将获得:

  • OpenHarmony 健康类应用设计规范;
  • Flutter 安全数值处理模板;
  • 无依赖实用工具开发指南。

用科学,服务生活。


相关推荐
●VON2 小时前
Flutter for OpenHarmony:基于选择模式状态机与原子批量更新的 TodoList 批量操作子系统实现
学习·flutter·ui·openharmony·von
一起养小猫2 小时前
Flutter for OpenHarmony 实战:贪吃蛇蛇的移动逻辑详解
android·flutter
晚霞的不甘2 小时前
Flutter for OpenHarmony:从零到一:构建购物APP的骨架与精美UI
前端·javascript·flutter·ui·前端框架·鸿蒙
kirk_wang2 小时前
Flutter艺术探索-Freezed代码生成:不可变数据模型实战
flutter·移动开发·flutter教程·移动开发教程
BullSmall3 小时前
CloudDR 故障切换演练脚本模板(自动化执行版)
运维·自动化
ElasticPDF-新国产PDF编辑器3 小时前
基于 PDF.js 的 PDF 文字编辑解决方案,纯前端 SDK,跨平台、框架无关、Web 原生
前端·javascript·pdf
带带弟弟学爬虫__3 小时前
速通新Baidu Frida检测
前端·javascript·vue.js·python·网络爬虫
b2077213 小时前
Flutter for OpenHarmony 身体健康状况记录App实战 - 运动分析实现
python·flutter·harmonyos
子春一3 小时前
Flutter for OpenHarmony:用 Flutter 构建一个数字猜谜游戏:从零开始的交互式应用开发
javascript·flutter·游戏