基于 Harmony 6.0 应用的健康数据监测仪表盘实现

前言

健康仪表盘是这两年智能手机和可穿戴设备发展的一个集中产物——把心率、血氧、睡眠、步数、压力指数、体温等一系列被动采集的健康数据汇集成一张"我今天的身体怎么样"的总图。Harmony 6.0 在这块的能力栈极其成熟——HealthKit 作为系统级健康数据中心,承接来自手机、手表、智能手环、智能体脂秤、血压计等多设备的数据上报,并提供给授权应用统一查询。本文用 Flutter 在 Harmony 6.0 上落地一款健康仪表盘首页,作为本系列第十一组的开篇,整页坚持纯 UI、零依赖。
在这里插入图片描述

背景

健康类应用的视觉关键词是"清晰、专业、可信"——清晰对应"每个指标必须独立成块",专业对应"数值必须大字号 + 单位",可信对应"颜色必须与医学语言一致(绿色正常 / 橙色警示 / 红色异常)“。蓝青色 #06B6D4 配深蓝 #1E40AF 是这类应用的典型主色——既有"医学"又有"科技”。本项目首页 6 个模块:渐变 Header(健康评分 + 大圆环可视化)、6 项核心指标网格(心率 / 血氧 / 步数 / 睡眠 / 压力 / 体温)、本周趋势卡片(折线图)、健康提醒列表、设备连接状态、AI 健康建议。从产品角度,健康类应用最大的复购点是"每日打开看自己怎么样"。Harmony 6.0 的桌面服务卡片让"健康评分"在桌面常驻,用户每次解锁手机就能看到,无需打开 App。

Flutter × Harmony 6.0 跨端开发介绍

Harmony 6.0 在健康赛道的能力栈非常完整——HealthKit 作为系统级健康数据中心,开发者通过 @kit.HealthServiceKit 申请权限后即可读取用户授权范围内的所有指标;SensorKit 提供原始传感器数据(加速度计、陀螺仪、心率传感器);超级终端让多设备健康数据自动汇聚;PushKit 提供异常推送。Flutter 嵌入 Harmony 6.0 的方案在这种"重数据 + 重可视化"应用上非常合适——主页用 Flutter 自绘提供丰富 UI,数据采集和聚合通过 ArkTS 端 HealthKit 接入。Skia 引擎对蓝青色(#06B6D4 / #1E40AF / #0EA5E9)的渲染极其通透,配合圆角和大留白,整页氛围既专业又可信。

开发核心代码

代码一:健康评分 Header

Header 必须把"今日健康评分"做成视觉中心——这是用户最关心的"我今天怎么样"的整体回答。我用一个深蓝渐变 Container,中间一个大圆环 + 评分数字,下方一行 chip 显示"较昨日 +3"。

Widget _header() {
  return Container(
    padding: const EdgeInsets.all(20),
    decoration: BoxDecoration(
      gradient: const LinearGradient(
        colors: [_primary, _primaryDark],
        begin: Alignment.topLeft, end: Alignment.bottomRight),
      borderRadius: BorderRadius.circular(24),
    ),
    child: Column(children: [
      const Row(children: [
        Icon(Icons.favorite, color: Colors.white, size: 22),
        SizedBox(width: 8),
        Text('健康仪表盘',
            style: TextStyle(color: Colors.white,
                fontSize: 18, fontWeight: FontWeight.w800)),
        Spacer(),
        Icon(Icons.watch, color: Colors.white, size: 22),
      ]),
      const SizedBox(height: 18),
      Stack(alignment: Alignment.center, children: [
        SizedBox(width: 160, height: 160,
          child: CircularProgressIndicator(
            value: 0.86, strokeWidth: 14,
            backgroundColor: Colors.white.withValues(alpha: 0.22),
            valueColor: const AlwaysStoppedAnimation(Colors.white),
          ),
        ),
        const Column(children: [
          Text('健康评分',
              style: TextStyle(color: Colors.white70, fontSize: 13)),
          SizedBox(height: 4),
          Text('86',
              style: TextStyle(color: Colors.white,
                  fontSize: 48, fontWeight: FontWeight.w900)),
          Text('良好',
              style: TextStyle(color: Colors.white,
                  fontSize: 13, fontWeight: FontWeight.w700)),
        ]),
      ]),
      const SizedBox(height: 14),
      Container(padding: const EdgeInsets.symmetric(
          horizontal: 12, vertical: 6),
        decoration: BoxDecoration(
          color: Colors.white.withValues(alpha: 0.22),
          borderRadius: BorderRadius.circular(20)),
        child: const Row(mainAxisSize: MainAxisSize.min,
          children: [
            Icon(Icons.trending_up, color: Colors.white, size: 14),
            SizedBox(width: 4),
            Text('较昨日 +3 · 一周内最佳',
                style: TextStyle(color: Colors.white,
                    fontSize: 12, fontWeight: FontWeight.w700)),
          ],
        ),
      ),
    ]),
  );
}

健康评分在生产业务里通过 HealthKit 拿到当日各项数据后,按预设权重综合计算得到——心率稳定性占 25%、睡眠质量占 25%、运动量占 20%、压力指数占 15%、其他占 15%。整个计算可以在 ArkTS 端完成,再通过 MethodChannel 把分值推给 Flutter UI 渲染。
在这里插入图片描述

从「健康评分 Header」的数据驱动可视化与情感激励设计角度再补一段。健康仪表盘类应用的 Header 必须把「我今天健康吗」这件事在一眼内交代清楚。这段 Header 用主蓝色到深蓝的渐变背景,配合大字号评分数字 + 评级 chip + 趋势文字的三段式排版,让用户在 0.3 秒内识别核心健康状态。把「看得见的数字」放在视觉中心比抽象的「良好」更直观。如果未来要扩展支持「分项展开」(点击评分可展开看到睡眠 90 / 运动 85 / 心率 92 等明细),可以做一个折叠面板,鸿蒙 6.0 端的 AnimatedContainer 让折叠动画丝滑无丢帧。

代码二:6 项核心指标网格

健康指标用 2x3 网格展示——心率、血氧、步数、睡眠、压力、体温。每项一个图标 + 大字号数据 + 状态 chip。状态用绿橙红三色表示"正常 / 注意 / 异常",是医学领域通用的色彩语言。

Widget _metrics() {
  final items = const [
    [Icons.favorite, '心率', '72', 'bpm', '正常', _green],
    [Icons.bloodtype, '血氧', '98', '%', '正常', _green],
    [Icons.directions_walk, '步数', '6,832', '步', '加油', _amber],
    [Icons.bedtime, '睡眠', '7.2', '小时', '良好', _green],
    [Icons.psychology, '压力', '中度', '', '注意', _amber],
    [Icons.thermostat, '体温', '36.6', '°C', '正常', _green],
  ];
  return GridView.count(
    crossAxisCount: 2, shrinkWrap: true,
    physics: const NeverScrollableScrollPhysics(),
    mainAxisSpacing: 10, crossAxisSpacing: 10,
    childAspectRatio: 1.6,
    children: items.map((it) {
      final c = it[5] as Color;
      return Container(padding: const EdgeInsets.all(14),
        decoration: BoxDecoration(color: _card,
            borderRadius: BorderRadius.circular(14)),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(children: [
              Icon(it[0] as IconData, color: c, size: 20),
              const SizedBox(width: 6),
              Text(it[1] as String,
                  style: const TextStyle(color: _sub,
                      fontSize: 12)),
              const Spacer(),
              Container(width: 6, height: 6,
                decoration: BoxDecoration(color: c,
                    shape: BoxShape.circle)),
            ]),
            const Spacer(),
            Row(crossAxisAlignment: CrossAxisAlignment.end,
                children: [
              Text(it[2] as String,
                  style: const TextStyle(color: _ink,
                      fontSize: 22,
                      fontWeight: FontWeight.w900)),
              const SizedBox(width: 4),
              Padding(padding: const EdgeInsets.only(bottom: 4),
                child: Text(it[3] as String,
                    style: const TextStyle(
                        color: _sub, fontSize: 11))),
              const Spacer(),
              Text(it[4] as String,
                  style: TextStyle(color: c, fontSize: 11,
                      fontWeight: FontWeight.w700)),
            ]),
          ],
        ),
      );
    }).toList(),
  );
}

每项指标在生产业务里通过 HealthKit 异步获取,建议用 StreamBuilder 包裹整个 GridView 让数据更新自动重绘。鸿蒙 6.0 的 HealthKit 提供数据订阅 API,开发者可以监听某项指标的变化事件,无需轮询。
在这里插入图片描述

从「6 项核心指标网格」的医学色彩语言与多维数据可视化角度再补一段。健康指标用 2x3 网格展示是医学专业 App 的最优范式——既能容纳 6 项关键数据又不会让单项数据被边缘化。每项数据用「图标 + 数值 + 单位 + 状态 chip」四件套呈现,状态用绿橙红三色编码(正常 / 注意 / 异常)——这是全球医学界通用的色彩语言,无需文字解释用户也能理解。每项指标的图标用对应主题色(心率红、血氧蓝、步数橙、睡眠紫、压力青、体温黄)做识别。如果未来要扩展支持「指标趋势图」(点击单项数据展开 7 天折线图),可以用 GestureDetector 包一层卡片实现,鸿蒙 6.0 的 Skia 自绘对小折线图渲染极其高效。

代码三:本周趋势卡片

本周趋势用一个折线图模拟——纯 Container 实现,不引图表库。把 7 天的数据点按相对位置排布。

Widget _trendCard() {
  final week = const [82, 78, 85, 80, 88, 84, 86];
  final maxVal = week.reduce((a, b) => a > b ? a : b);
  return Container(
    padding: const EdgeInsets.all(16),
    decoration: BoxDecoration(color: _card,
        borderRadius: BorderRadius.circular(16)),
    child: Column(crossAxisAlignment: CrossAxisAlignment.start,
        children: [
      const Row(children: [
        Text('本周健康评分趋势',
            style: TextStyle(color: _ink, fontSize: 14,
                fontWeight: FontWeight.w700)),
        Spacer(),
        Text('查看详情',
            style: TextStyle(color: _primary, fontSize: 12)),
      ]),
      const SizedBox(height: 14),
      SizedBox(height: 110,
        child: Row(crossAxisAlignment: CrossAxisAlignment.end,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: List.generate(7, (i) {
          final h = week[i] / maxVal * 80;
          final days = ['一', '二', '三', '四', '五', '六', '日'];
          return Column(children: [
            Text('${week[i]}',
                style: const TextStyle(color: _primary,
                    fontSize: 11, fontWeight: FontWeight.w700)),
            const SizedBox(height: 4),
            Container(width: 14, height: h,
              decoration: BoxDecoration(
                gradient: const LinearGradient(
                  colors: [_primary, _primaryDark],
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter),
                borderRadius: BorderRadius.circular(4)),
            ),
            const SizedBox(height: 6),
            Text(days[i],
                style: const TextStyle(color: _sub, fontSize: 11)),
          ]);
        })),
      ),
    ]),
  );
}

7 根柱子的归一化非常简单——week[i] / maxVal * 80,把最大值映射到 80 像素高。鸿蒙 6.0 的 Skia 渲染对这种小区域柱状图开销极低,单帧绘制不到 1ms。如果要做得更高级,可以接入 ArkUI 的 LineChart 组件原生绘制折线,性能更好。

从「本周趋势卡片」的时间序列可视化与健康洞察设计角度再补一段。健康类应用的「本周趋势」让用户看到「数据是变好还是变差」。这段卡片用 7 根渐变柱子表示一周的数据变化,每根柱子顶端显示当日数值,底部显示星期标签。柱子用主题色渐变填充(顶部浅、底部深),形成立体感。如果某天数据特别低或特别高,可以让那根柱子变红色高亮,让用户一眼识别异常日。如果未来要扩展支持「按指标切换」(柱状图可以切换显示步数、心率、睡眠等不同指标),可以在卡片顶部加 chip 切换栏,配合 AnimatedContainer 让柱子高度切换有平滑过渡,鸿蒙 6.0 的动画 vsync 对齐让这种数据切换丝滑无卡顿。

心得

健康仪表盘类 App 的视觉灵魂是"清晰 + 可信"——蓝青色给科技感,绿橙红三色状态指示给医学可信感。开发时最容易犯的错是把每项指标都做成相同尺寸的纯文字,反而让用户看不出"哪项最关键"。我的策略是用大圆环把"健康评分"放到 Header 视觉中心,让一张图回答"我今天怎么样"。从能力扩展角度,健康类应用最值得在鸿蒙端打造的是"HealthKit 系统级健康档案 + 多设备数据汇聚 + AI 健康建议"三件套——HealthKit 让数据可信、超级终端让多设备数据自动汇聚、AI 助手让"今天该多走 1000 步"成为可对话能力。

总结

本篇实现了 Harmony 6.0 端的健康仪表盘首页,6 个模块、纯 UI、零依赖、约 360 行代码。骨架可直接迁移到老人健康监护、慢病管理、孕期监测等多种场景。从扩展角度建议生产业务里:把数据接入 HealthKit;把异常告警接入 PushKit;把"健康评分"做成 FormExtensionAbility 桌面卡片;把多设备数据汇聚接入超级终端;把 AI 健康建议接入 AI 助手能力。下一篇是第十一组的第二块——瑜伽教学应用。

在这里插入图片描述

Logo

一站式 AI 云服务平台

更多推荐