【HarmonyOS 6】今日统计卡片实战:运动记录数据概览

一、案例背景

在移动端"运动记录"页面里,用户最先关心的是今天运动了多久、消耗了多少热量。与其把这些数据隐藏在列表里,不如用一张"今日统计卡"直接放在顶部,形成清晰的视觉焦点。

本案例面向 HarmonyOS 6 初学者,聚焦一个细化功能:今日统计卡 + 空状态提示。实现目标如下:

  • 顶部两列指标卡,展示"运动时长"和"消耗热量"
  • 下方列表为空时显示友好的空状态
  • 有记录时显示运动列表

二、完整代码实现

2.1 今日统计卡

typescript 复制代码
        // 今日统计
        Row() {
          Column() {
            Text(this.getTotalDuration().toString())
              .fontSize(this.getStatNumberSize())
              .fontWeight(FontWeight.Bold)
              .fontColor($r('app.color.exercise_orange'))
            Text('运动时长(分钟)')
              .fontSize(this.getStatLabelSize())
              .fontColor($r('app.color.text_secondary'))
          }
          .layoutWeight(1)

          Column() {
            Text(this.getTotalCalories().toString())
              .fontSize(this.getStatNumberSize())
              .fontWeight(FontWeight.Bold)
              .fontColor($r('app.color.exercise_orange'))
            Text('消耗热量(kcal)')
              .fontSize(this.getStatLabelSize())
              .fontColor($r('app.color.text_secondary'))
          }
          .layoutWeight(1)
        }
        .width('100%')
        .padding(this.getCardPadding() as Padding)
        .backgroundColor($r('app.color.card_background'))
        .borderRadius(this.getCardRadius())
        .margin({ left: this.getPagePaddingValue(), right: this.getPagePaddingValue() } as Padding)

关键点:

  • Row + 两个 Column 实现左右两列指标
  • layoutWeight(1) 让两列均分宽度
  • 卡片样式通过背景色和圆角形成"统计卡"的视觉块

2.2 今日记录列表与空状态

typescript 复制代码
        // 今日记录列表
        Text('今日运动')
          .fontSize(this.getSectionTitleSize())
          .fontWeight(FontWeight.Medium)
          .fontColor($r('app.color.text_primary'))
          .width('100%')
          .padding({ left: this.getPagePaddingValue(), top: this.getSectionGap(), bottom: this.getItemGap() } as Padding)

        if (this.exerciseRecords.length === 0) {
          Column() {
            Text('🏃')
              .fontSize(this.getEmptyIconSize())
              .fontColor($r('app.color.text_secondary'))
            Text('今天还没有运动记录')
              .fontSize(this.getBodyTextSize())
              .fontColor($r('app.color.text_primary'))
              .margin({ top: this.getItemGap() } as Padding)
          }
          .width('100%')
          .layoutWeight(1)
          .justifyContent(FlexAlign.Center)
        } else {
          List() {
            ForEach(this.exerciseRecords, (record: ExerciseRecordData) => {
              ListItem() {
                Row() {
                  Text(record.icon)
                    .fontSize(this.getItemIconSize())

                  Column() {
                    Text(record.typeName)
                      .fontSize(this.getBodyTextSize())
                      .fontColor($r('app.color.text_primary'))
                    Text(`${record.duration}分钟 · ${record.calories}kcal`)
                      .fontSize(this.getSmallTextSize())
                      .fontColor($r('app.color.text_secondary'))
                      .margin({ top: 2 } as Padding)
                  }
                  .alignItems(HorizontalAlign.Start)
                  .margin({ left: 12 } as Padding)

                  Blank()

                  Text(record.time)
                    .fontSize(this.getSmallTextSize())
                    .fontColor($r('app.color.text_secondary'))
                }
                .width('100%')
                .padding(this.getItemPadding() as Padding)
                .backgroundColor($r('app.color.card_background'))
                .borderRadius(getValueByBreakpoint(this.currentBreakpoint, new BreakpointValue<number>(8, 10, 12)))
              }
              .margin({ left: this.getPagePaddingValue(), right: this.getPagePaddingValue(), bottom: this.getItemGap() } as Padding)
              .swipeAction({
                end: this.ExerciseDeleteButton(record.id)
              })
            })
          }
          .padding({ bottom: getFloatingNavSafePadding(this.currentBreakpoint) } as Padding)
          .layoutWeight(1)
        }

这里包含两个关键体验:

  • 无记录时:显示图标 + 引导文字,避免页面空白
  • 有记录时:展示列表项,补充时长、热量与时间

空状态截图:

三、总结

本文实现了一个完整的移动端"今日统计卡 + 空状态"方案,核心要点包括:

  1. Row + layoutWeight 实现左右两列指标
  2. 卡片式背景与圆角增强视觉聚焦
  3. 空状态提升体验,有记录时自然过渡到列表

掌握这个案例后,你可以迁移到饮水、睡眠、打卡等模块,快速搭建可视化的日统计卡片。

相关推荐
Python私教21 小时前
鸿蒙 NEXT 也能接 MCP?用 ArkTS 跑通 AI Agent 工具链
人工智能·华为·harmonyos
极客范儿1 天前
华为HCIP网络工程师认证—OSPF
网络·华为·智能路由器
Swift社区1 天前
分布式能力在鸿蒙 PC 上到底怎么用?
分布式·华为·harmonyos
曾响铃1 天前
制造跃升:传统产业正迈入数智化转型的价值兑现期
华为
therese_100861 天前
客户端架构:为什么、什么时候、怎么做
设计模式·安卓·鸿蒙
nashane1 天前
HarmonyOS 6学习:外接键盘CapsLock与长截图功能的实战调试与完整解决方案
学习·华为·计算机外设·harmonyos
aqi002 天前
一文理清 HarmonyOS 6.0.2 涵盖的十个升级点
android·华为·harmonyos·鸿蒙·harmony
环信即时通讯云2 天前
环信Flutter UIKit适配鸿蒙实战指南
flutter·华为·harmonyos