【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. 空状态提升体验,有记录时自然过渡到列表

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

相关推荐
Hstar_chen6 小时前
开源一款 HarmonyOS 服务器监控客户端:星辰云巡 1.0.3
服务器·华为·harmonyos
2501_9197490313 小时前
华为鸿蒙免费视频播放器APP—小羊免费播放器
华为·harmonyos·鸿蒙
2501_9197490314 小时前
华为鸿蒙免费背书背课文背稿子APP—小羊背诵
华为·harmonyos·鸿蒙
OH_TPC14 小时前
HarmonyOS APP开发---"随手画"白板涂鸦App,需要用到这个库
harmonyos
lilian23316 小时前
HarmonyOS 7 新特性(二十六)|LazyLayoutAlgorithm 自定义懒布局
华为·harmonyos
lilian23317 小时前
HarmonyOS 7 新特性(二十九)|游戏伴随服务:悬浮协作与质量降级
游戏·语音识别·harmonyos
王二蛋与他的张大花17 小时前
让小艺替我回答“还有多久下班“——摸鱼鸭的 HarmonyOS 7 Skill 接入实战
harmonyos
hunterandroid17 小时前
[鸿蒙从零到一] HarmonyOS 冷启动瀑布图分析与关键路径裁剪实战
前端·华为
用户09340777351418 小时前
HarmonyOS WPS Open SDK 实践:把水印与修订收成打开策略层
android·typescript·harmonyos
Veer Han19 小时前
DevEco CLI 实战:鸿蒙 App「宝贝日程表」从 0 开发到正式上架
华为·harmonyos