当前位置: 首页 > news >正文

Flutter for OpenHarmony BMI 健康计算器:打造支持深色模式的智能健康工具

Flutter for OpenHarmony BMI 健康计算器:打造支持深色模式的智能健康工具

在健康管理日益普及的今天,身体质量指数(BMI)作为衡量体重是否健康的简易指标,已成为大众日常关注的焦点。而一个优秀的 BMI 计算器,不仅要准确计算数值,更应提供清晰的健康解读、友好的交互体验与个性化的视觉适配

🌐 加入社区 欢迎加入开源鸿蒙跨平台开发者社区,获取最新资源与技术支持: 👉开源鸿蒙跨平台开发者社区


完整效果

一、核心功能:从输入到健康建议

该应用的核心逻辑简洁而完整:

  1. 用户输入:身高(cm)、体重(kg);
  2. 数据校验:非空、正数、有效数字;
  3. BMI 计算:公式为体重(kg) / (身高(m))²
  4. 健康分级
    • < 18.5:偏瘦(橙色提示)
    • 18.5–23.9:正常(绿色鼓励)
    • 24–27.9:超重(橙红警示)
    • ≥ 28:肥胖(红色警告)
  5. 结果展示:大号数值 + 个性化健康建议。

💡 不仅告诉你“是多少”,更告诉你“意味着什么”。


二、智能输入处理与错误反馈

1. 安全解析用户输入

finalheight=double.tryParse(heightStr);finalweight=double.tryParse(weightStr);if(height==null||weight==null||height<=0||weight<=0){_showError('请输入有效的正数');return;}

2. 即时错误提示


三、双主题系统:自动适配用户偏好

1. 主题定义

theme:ThemeData(/* 亮色主题 */),darkTheme:ThemeData(/* 深色主题 */),themeMode:ThemeMode.system,// 跟随系统

2. 动态颜色获取

finalisDark=Theme.of(context).brightness==Brightness.dark;finaltextColor=isDark?Colors.white:Colors.black87;finalcardColor=isDark?constColor(0xFF1E1E1E):Colors.white;

无障碍设计:高对比度文本 + 清晰图标,照顾不同视觉需求。


四、UI/UX 设计亮点

1. 输入体验优化

2. 按钮层级分明

按钮类型视觉权重作用
计算 BMIElevatedButton高(主色填充)核心操作
重置TextButton低(文字链接)辅助操作

3. 结果区域动态呈现

4. 平滑动画过渡

AnimatedContainer(duration:constDuration(milliseconds:500),curve:Curves.easeOut,child:Card(...),)

五、技术实现细节

技术点应用说明
TextEditingController精确控制输入框内容,支持清空(clear()
SingleChildScrollView确保小屏幕设备可滚动查看全部内容
CrossAxisAlignment.stretch使按钮与输入框宽度一致,布局整齐
toStringAsFixed(1)保留一位小数,避免冗长数字(如 22.3456 → 22.3)
Theme.of(context).brightness实时获取当前主题亮度,用于动态着色

六、扩展与应用场景

可扩展方向

应用场景


七、结语:小工具,大关怀

这个 BMI 计算器虽功能简单,却处处体现对用户的尊重与关怀

import'package:flutter/material.dart';voidmain(){runApp(const BmiApp());}class BmiApp extends StatelessWidget{const BmiApp({super.key});@override Widget build(BuildContext context){returnMaterialApp(debugShowCheckedModeBanner: false, title:'📏 BMI 计算器', theme: ThemeData(brightness: Brightness.light, primarySwatch: Colors.blue, scaffoldBackgroundColor: Colors.grey[50], inputDecorationTheme: const InputDecorationTheme(filled: true, fillColor: Colors.white, border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(12)), borderSide: BorderSide.none,),),), darkTheme: ThemeData(brightness: Brightness.dark, primarySwatch: Colors.blue, scaffoldBackgroundColor: const Color(0xFF121212), inputDecorationTheme: const InputDecorationTheme(filled: true, fillColor: Color(0xFF1E1E1E), border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(12)), borderSide: BorderSide.none,),),), themeMode: ThemeMode.system, home: const BmiCalculatorScreen(),);}}class BmiCalculatorScreen extends StatefulWidget{const BmiCalculatorScreen({super.key});@override State<BmiCalculatorScreen>createState()=>_BmiCalculatorScreenState();}class _BmiCalculatorScreenState extends State<BmiCalculatorScreen>{final TextEditingController _heightController=TextEditingController();final TextEditingController _weightController=TextEditingController();double? _bmi;String _interpretation='';Color _resultColor=Colors.blue;void_calculateBMI(){final heightStr=_heightController.text.trim();final weightStr=_weightController.text.trim();if(heightStr.isEmpty||weightStr.isEmpty){_showError('请输入身高和体重');return;}final height=double.tryParse(heightStr);final weight=double.tryParse(weightStr);if(height==null||weight==null||height<=0||weight<=0){_showError('请输入有效的正数');return;}// 身高从 cm 转为 m final heightInMeters=height /100;final bmi=weight /(heightInMeters * heightInMeters);String interpretation;Color color;if(bmi<18.5){interpretation='偏瘦\n建议增加营养摄入,保持规律作息。';color=Colors.orange;}elseif(bmi<24){interpretation='正常\n继续保持健康的生活方式!';color=Colors.green;}elseif(bmi<28){interpretation='超重\n建议适当运动,控制饮食。';color=Colors.orangeAccent;}else{interpretation='肥胖\n建议咨询医生,制定科学减重计划。';color=Colors.red;}setState((){ _bmi=bmi;_interpretation=interpretation;_resultColor=color;});} void _showError(String message){ ScaffoldMessenger.of(context).showSnackBar(SnackBar(content:Text(message)),);}void_reset(){_heightController.clear();_weightController.clear();setState((){ _bmi=null;_interpretation='';_resultColor=Colors.blue;});} @override Widget build(BuildContext context){ final isDark=Theme.of(context).brightness==Brightness.dark;final textColor=isDark?Colors.white:Colors.black87;final cardColor=isDark?const Color(0xFF1E1E1E):Colors.white;return Scaffold(appBar:AppBar(title:const Text('BMI 健康计算器'),centerTitle:true,backgroundColor:Colors.transparent,elevation:0,),body:SingleChildScrollView(padding:const EdgeInsets.all(24),child:Column(crossAxisAlignment:CrossAxisAlignment.stretch,children:[//输入区域 TextField(controller:_heightController,keyboardType:TextInputType.numberWithOptions(decimal:true),decoration:InputDecoration(labelText:'身高(cm)',hintText:'例如:175',prefixIcon:const Icon(Icons.height),),),const SizedBox(height:16),TextField(controller:_weightController,keyboardType:TextInputType.numberWithOptions(decimal:true),decoration:InputDecoration(labelText:'体重(kg)',hintText:'例如:70',prefixIcon:const Icon(Icons.monitor_weight),),),const SizedBox(height:24),//计算按钮 ElevatedButton.icon(onPressed:_calculateBMI,icon:const Icon(Icons.calculate),label:const Text('计算 BMI',style:TextStyle(fontSize:18)), style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical:16), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12),),),), const SizedBox(height:16), // 重置按钮(轻量) TextButton(onPressed: _reset, child: const Text('重置', style: TextStyle(fontSize:16)),), const SizedBox(height:32), // 结果区域if(_bmi!=null)AnimatedContainer(duration: const Duration(milliseconds:500), curve: Curves.easeOut, child: Card(color: cardColor, elevation:4, child: Padding(padding: const EdgeInsets.all(24), child: Column(children:[Text('你的 BMI', style: TextStyle(fontSize:18, color: Colors.grey[600]?? Colors.grey,),), const SizedBox(height:8), Text(_bmi!.toStringAsFixed(1), style: TextStyle(fontSize:48, fontWeight: FontWeight.bold, color: _resultColor,),), const SizedBox(height:16), Text(_interpretation, textAlign: TextAlign.center, style: TextStyle(fontSize:18, height:1.5, color: textColor,),),],),),),),if(_bmi==null)Center(child: Column(mainAxisAlignment: MainAxisAlignment.center, children:[const Icon(Icons.monitor_heart, size:80, color: Colors.grey), const SizedBox(height:16), Text('输入身高和体重\n开始计算你的 BMI', textAlign: TextAlign.center, style: TextStyle(fontSize:18, color: isDark ? Colors.grey[500]:Colors.grey[600],),),],),),],),),);}}
http://www.jsqmd.com/news/362624/

相关文章:

  • 【开题答辩全过程】以 基于Springboot图书管理系统为例,包含答辩的问题和答案
  • 2026年碰碰车厂家推荐:逍遥乐吧车/360摇滚乐吧车/亲子双人碰碰车/公园碰碰车/发光漂移碰碰车/商场碰碰车/选择指南 - 优质品牌商家
  • 2026年实测TOP3智能工厂规划服务商深度对比 - 孟哥商业圈
  • P3195 [HNOI2008] 玩具装箱
  • 题解:AWC 0001
  • 2026牛客寒假算法基础集训营4 题解
  • 2026年评价高的三柱避雷塔公司推荐:监控铁塔、角钢监控塔、角钢避雷塔、道路监控塔、钢管避雷塔、镀锌监控塔架选择指南 - 优质品牌商家
  • AI不是在杀死SaaS,而是在逼传统软件回到它真正值钱的那一层
  • YouTube 文字转语音怎么用?AI 配音提升效率与内容产出的完整指南
  • 2026年江西新工厂规划避坑指南:五大服务商深度评测;江西五大公司排名与常见误区解析 - 孟哥商业圈
  • 只知道WinPE?这款两款Linux PE维护系统,轻松化解Linux运维难题
  • AWC_0001 Beta
  • 2026考研失利求职季:如何告别“简历海投”,打造冲刺offer的完美简历?
  • 五度易链“产业大脑”架构解析:如何通过数据智能驱动产业升级?
  • HTTP 协议应用指导 - 详解
  • 2026年实测盘点:新工厂规划公司T深度对比解析 - 孟哥商业圈
  • MathCAD许可证与其他软件集成
  • 打工人救星!用 doocs md 写公众号,再也不用反复调格式
  • 拉普拉斯算子与扩散方程
  • Cursor+Claude AI编程 - Cursor简介
  • 【方案实践】公寓租赁项目(十):基于SpringBoot登录管理接口构建
  • 白帽谷歌seo快速排名外链哪里有?真实渠道、方法和避坑全讲清
  • 2026年实测上海新工厂规划精实工业信息技术 - 孟哥商业圈
  • 深入剖析大数据领域的数据清洗需求
  • iOS 开发助手,性能测试、实时日志、应用管理、设备信息查看
  • 3小时搞定万字综述?2026年论文写作工具红黑榜:第一名堪称全能“学术外挂” - 沁言学术
  • 软考一次过的概率大吗?看完通过率分析,你就明白了!
  • 百亿积分泡沫破裂!新一轮“绿色积分”靠什么让用户争相买单?
  • 内存计算技术在大数据分析中的7个关键应用
  • 2026国自然模板大改,无从下笔?