鸿蒙应用开发之家庭应急物资首页深度实践:环形进度准备度卡与充足偏少双态列表布局

1、引言

打开任何一款应用,第一屏决定了用户的第一印象。我们的家庭应急物资管理应用也不例外——用户点开图标,最想看到的不是菜单、不是设置,而是一个直击灵魂的问题:我家应急准备得怎么样?

这个问题的答案,需要两个层次的信息来回答:第一层是一个数字——准备度百分比,用环形进度直观呈现"还差多少";第二层是一张清单——哪些物资充足、哪些偏少,逐条列出来让用户心里有数。一层宏观指标,一层微观明细,缺一不可。

在传统的移动端开发中,这种"指标卡 + 状态列表"的组合布局,往往需要用 CardView 嵌套 RecyclerView,环形进度要自定义 View 手绘 Canvas,状态胶囊的颜色逻辑散落在 Adapter 里,改一个状态色要翻三个文件。

幸运的是,在 HarmonyOS 的 ArkUI 声明式开发范式中,@Builder 装饰器给了我们一种极其优雅的方案:将首页拆分为三个独立的构建块(Header、ReadyCard、SupplyList),环形进度用原生 Progress 组件一行搞定,物资状态通过数据模型的 statusColor 字段动态注入,整页代码不到 100 行。

这篇实战手记,我们将从 60-emergency-kit/entry/src/main/ets/pages/HomeTab.ets(共 95 行)切入,不仅教你如何用 @Builder 拆解首页的三区结构,更重要的是,借此机会彻底拆解橙棕渐变准备度卡的环形进度呈现机制,以及充足/偏少双态胶囊在物资列表中的颜色编码设计。我们不背文档,不讲空话,直接看真实场景下的解法。

2、效果展示与页面结构

在正式深入代码之前,我们先看看最终的页面表现和工程底座。直观的视觉冲击能让你瞬间明白我们在解决什么问题。

首页是"品牌头部 + 应急准备度 + 物资库存"的三区布局,整体由 3 个 @Builder 块构成:

build() {
  Column() {
    this.Header()
    Scroll() {
      Column({ space: 14 }) {
        this.ReadyCard()
        this.SectionTitle('物资库存')
        this.SupplyList()
      }
      .width('100%')
      .padding({ left: D.pad, right: D.pad, top: 14, bottom: D.pad + this.safeBottom + 20 })
    }
    .layoutWeight(1).scrollBar(BarState.Off).align(Alignment.Top)
  }
  .width('100%').height('100%').backgroundColor(C.bg)
}

这个结构的设计初衷是明确划分"总览"和"明细"的职责边界:

  1. Header — 单行品牌头(“应急物资”),白底固定,22 号加粗,点明应用主题
  2. ReadyCard — 橙棕渐变准备度卡(环形进度 75% + “2 项物资需要补充”)
  3. SupplyList — "物资库存"标题 + 4 条物资卡片列表(充足绿/偏少橙双态胶囊)

首页回答的核心问题是"家庭应急准备得怎么样、还缺什么"——准备度卡给结论(75% 环形进度 + 2 项需补充),列表给明细(4 种关键物资的库存与状态),一屏完成"水平评估 → 缺口定位"的认知闭环。

首页整体布局

3、Header:单行品牌头的标准范式
Header() {
  Column() {
    Text('应急物资').fontSize(22).fontWeight(FontWeight.Bold).fontColor(C.text)
      .width('100%').padding({ top: this.safeTop + 10, left: D.pad, right: D.pad, bottom: 12 })
  }.width('100%').backgroundColor(C.card)
}

首页 Header 的标准范式:22 号加粗大字、safeTop + 10 避让状态栏、底部 12 内边距、白底全宽。"应急物资"直白点题——管理家庭应急物资的工具,与系列工具型首页(App 45 签到墙 / App 59 用药提醒)同款单行标题范式。

这里有一个极其关键的细节:padding({ top: this.safeTop + 10 }) 将状态栏安全区纳入 Header 内边距。如果不做这层处理,在刘海屏设备上"应急物资"四个字会被状态栏遮挡——这是鸿蒙开发中最容易忽略的适配坑之一。

4、ReadyCard:橙棕渐变准备度卡与环形进度
ReadyCard() {
  Row({ space: 16 }) {
    Stack({ alignContent: Alignment.Center }) {
      Progress({ value: 75, total: 100, type: ProgressType.Ring })
        .width(66).height(66).color('#FFFFFF').style({ strokeWidth: 6 }).backgroundColor('#44FFFFFF')
      Text('75%').fontSize(15).fontWeight(FontWeight.Bold).fontColor('#FFFFFF')
    }
    Column({ space: 4 }) {
      Text('应急准备度').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#FFFFFF')
      Text('2 项物资需要补充').fontSize(12).fontColor('#FFFFFF').opacity(0.9)
    }.alignItems(HorizontalAlign.Start).layoutWeight(1)
  }
  .width('100%').padding(18).borderRadius(D.rLg)
  .linearGradient({ angle: 135, colors: [[C.primary, 0.0], [C.accent, 1.0]] })
}

这段代码中有几处极其精妙的设计,是我们在多次迭代后沉淀出来的:

第一,橙棕渐变的品牌语义linearGradient({ angle: 135, colors: [[C.primary, 0.0], [C.accent, 1.0]] })——从 #D35400 橙棕渐变到 #E88050 浅橙,135 度对角线方向。橙色 = 应急/安全警示的语义色(救生、警惕的联想),与 App 57 加油的活力橙不同,本页橙棕更沉稳,应急场景用橙色传达"关注准备"。这张卡不是独立组件,而是品牌视觉体系的一环——用户看到橙棕渐变就联想到"应急物资"。

第二,环形进度的白色呈现策略Progress({ value: 75, total: 100, type: ProgressType.Ring })——66×66 白色圆环(color('#FFFFFF') 白环 + strokeWidth(6) 粗环 + backgroundColor('#44FFFFFF') 白色 27% 透明底环)。ArkUI 原生 Ring 进度组件,白色圆环在橙棕渐变上高对比(深底白环最清晰),底环用 27% 透明白形成"已填/未填"的环段对比。若用主题色环(橙)在橙底上会糊成一片,白环是"深底进度"的标准配色。

第三,环内百分比文字的叠放Stack({ alignContent: Alignment.Center }) 叠放环 + “75%” 15 号 Bold 白字——进度数字居中在环内(标准环形进度形态),白字与白环呼应,用户扫一眼就抓到核心数字。

第四,主副文案的信息层次。16 号 Bold"应急准备度"是首页第一信息(家庭应急准备的水平指标),12 号 90% 透明"2 项物资需要补充"是待办量(还有 2 种物资不足),与列表"偏少"状态对应。主文案给水平、副文案给缺口,两级信息完成"水平到缺口"的引导。

第五,数据自洽的加权逻辑。75% 准备度 ↔ 4 种物资中 2 种充足(饮用水/手电筒)、2 种偏少(罐头/急救包)——充足率 50% 但按物资重要性加权为 75%(饮用水/急救包等关键物资权重高)。准备度不是简单的充足占比,而是"关键物资权重"的综合指标。

5、SupplyList:充足/偏少双态物资列表
SupplyList() {
  Column({ space: 10 }) {
    ForEach(this.supplies, (s: Supply) => {
      Row({ space: 12 }) {
        Row() { Text(s.emoji).fontSize(24) }
        .width(48).height(48).backgroundColor(C.primarySoft).borderRadius(D.rSm).justifyContent(FlexAlign.Center)
        Column({ space: 3 }) {
          Text(s.name).fontSize(14).fontWeight(FontWeight.Medium).fontColor(C.text)
          Text('库存 ' + s.count + ' 件').fontSize(12).fontColor(C.textDim)
        }.alignItems(HorizontalAlign.Start).layoutWeight(1)
        Text(s.status).fontSize(11).fontColor(s.statusColor)
          .padding({ left: 8, right: 8, top: 3, bottom: 3 }).backgroundColor(s.statusColor + '22').borderRadius(6)
      }
      .width('100%').padding(12).backgroundColor(C.card).borderRadius(D.rMd).border({ width: 1, color: C.stroke })
      .onClick(() => { promptAction.showToast({ message: s.name }); })
    }, (s: Supply) => s.id.toString())
  }.width('100%')
}

4 条物资数据(21-26 行):

物资 库存 状态 颜色
💧 瓶装饮用水 24 件 充足 绿
🥫 罐头食品 6 件 偏少
🔦 手电筒 2 件 充足 绿
🩹 医药急救包 1 件 偏少

这段代码中有几处极其精妙的设计:

第一,主色软底图标的品牌统一backgroundColor(C.primarySoft)#FDE8DC 浅橙棕)+ 24 号 emoji——浅橙圆角底,每物专属 emoji(💧🥫🔦🩹),应急物资类型一眼可辨。首页的图标底用主题色软底(品牌统一),与检查页的"问题色透明底"形成区分——首页是"库存总览"用品牌色、检查页是"问题导向"用问题色。

第二,物资名与库存件数的信息组合。14 号 Medium 物资名 + 12 号淡灰"库存 24 件"——名称 + 数量layoutWeight(1) 撑开,用户一眼看到"什么物资、有多少"。

第三,双态状态胶囊的颜色编码。右侧 s.status(充足/偏少)——字色 + 透明底色胶囊statusColor + '22' ≈ 13% 透明底),充足绿(#2BB673)、偏少橙(#FF9F1C)。两态红绿灯式状态(充足绿/偏少橙,无红色=最紧急,因为首页是"库存总览"、紧急项在检查页)。用户扫列表时,橙色偏少标最先被注意,定位缺口。

第四,库存量的梯度设计。24/6/2/1 件——覆盖"充足到偏少"的梯度(饮用水 24 最充足、急救包 1 最偏少),偏少项(罐头 6、急救包 1)对应准备度卡"2 项需补充"。

第五,整卡点击的交互预留。点击 Toast 物资名(“瓶装饮用水”)——产品化后跳物资详情/编辑页,整卡可点击扩大热区。

点击物资卡片弹出提示

6、跨页数据自洽:应急物资的全局闭环

首页不是孤岛——它与物资页、检查页、我的页形成四页数据闭环:

  • 首页"4 种物资" ↔ 物资页"3 分类 8 种物品"——首页展示 4 种"关键应急物资"(饮用水/罐头/手电筒/急救包),物资页按 3 分类展示 8 种全部物品,首页是关键项、物资页是全集
  • 首页"罐头食品 偏少 6 件" ↔ 物资页"罐头 6"、检查页"罐头食品 库存仅剩 6 件"——数量完全一致(6 件),首页标"偏少"、物资页显示数量、检查页标"库存不足"建议去补充,三页同源
  • 首页"医药急救包 偏少 1 件" ↔ 检查页"医药急救包 库存仅剩 1 个 库存不足"——数量一致(1 件),首页偏少 → 检查页库存不足(更紧急),检查页是首页偏少项的"处理页"。
  • 首页"2 项物资需要补充" ↔ 检查页"2 库存不足"——数量一致(2 项:罐头 + 急救包),准备度卡的待办量 = 检查页的库存不足数。
  • 首页"75% 准备度" ↔ 我的页"75% 准备度"——数值完全一致,首页环形进度 = 我的页统计"准备度 75%"。

这套闭环的核心是统一数据源——四页共享同一份物资数据模型,首页做"准备度总览"、物资页做"库存管理"、检查页做"问题处理"、我的页做"提醒配置",各司其职但数据同源。改一处库存,四页同步刷新。

7、多维度方案选型对比:环形进度首页的系列差异

在实际的架构研讨中,有同学曾经发出过极其尖锐的质疑:“首页为什么要用环形进度?用数字不就行了?”

为了彻底解答这个选型问题,我们将系列中"指标卡"型首页对比:

维度 App 60 应急物资 App 39 兴趣匹配 App 57 加油记录 App 55 续费提醒
核心指标 准备度 75% 匹配度 95% 油耗 支出预警
指标呈现 环形进度 环形进度 油耗卡 预警卡
列表内容 4 条物资(充足/偏少) 标签 快查统计 临期列表
主题色 橙棕 #D35400 #FF6B9D #FF6B35 #FF6B6B

60 与 39 都用"环形进度"(39 的 95% 匹配度、60 的 75% 准备度),但场景不同:39 是"兴趣匹配"(软性社交)、60 是"应急准备"(刚性安全)。60 的差异化在于**“环形进度 + 双态物资”**:白色环形进度在橙棕渐变卡上醒目(应急准备度的核心指标),物资列表的充足/偏少双态胶囊(绿/橙)让"还缺什么"一目了然,且"2 项需补充"直接对接检查页的处理列表——"准备度 → 缺口 → 去补充"的完整引导链路是应急场景独有的。

首页列表与交互

8、避坑指南:应急首页的四个防翻车细节

在将这套看起来优雅的首页设计推向真实生产环境时,我们踩过了几个深浅不一的暗坑。以下是内部复盘后沉淀的防翻车铁律:

第一,准备度计算必须动态化。75% 是写死的——产品化应由物资状态动态计算(充足物资占比加权,关键物资权重更高:饮用水/急救包权重 > 电池),物资补足后准备度自动上升,首页环形进度与我的页统计联动(同一计算函数)。如果写死,物资补足了但准备度不变,用户会完全失去信任。

第二,状态判定阈值必须统一。充足/偏少写死——产品化按"库存 vs 建议量"判定(饮用水建议 24 件充足、罐头建议 12 件则 6 件偏少),每种物资有自己的"建议库存",低于建议量 50% 标偏少、接近 0 标不足,阈值由物资建议量驱动。首页与检查页必须用同一状态机,避免"首页偏少但检查页没列"的不一致。

第三,环形进度的可访问性。环形进度(75%)只有数字 75% 在环内——读屏用户无法感知进度,产品化应给环形进度加无障碍描述(“应急准备度百分之七十五”),且环的颜色对比(白环橙底)在强光下需保持清晰。

第四,物资与检查页的联动。首页偏少(罐头/急救包)与检查页库存不足是两处数据——产品化统一状态判定(同一库存值在首页标偏少、在检查页标不足,由同一"状态机"驱动),避免"首页偏少但检查页没列"或反之的不一致。

滚动查看全部物资库存

9、常见问题 FAQ

问:75% 的应急准备度是怎么算出来的?

答:演示数据设定家庭应急准备度为 75%(写死),产品化后由物资充足情况综合计算——4 种关键物资中 2 种充足(饮用水/手电筒)、2 种偏少(罐头/急救包),若按"充足率"是 50%,但关键物资(饮用水、急救包)权重高、且偏少不是没有(罐头 6 件、急救包 1 件仍可用),综合加权为 75%。准备度是"家庭应急物资完整度的综合指标"。

问:为什么首页没有"已过期"这种红色状态?

答:因为首页是"库存总览"(看物资够不够)——充足(绿)/偏少(橙)两态已覆盖"够不够"的问题;“已过期/即将过期"是"还能不能用"的问题,属于检查页的职责(检查页有已过期红、即将过期橙、库存不足橙三态)。首页管"量”、检查页管"质(效期)+ 量"的分工,避免首页信息过载。

问:准备度卡"2 项物资需要补充"和列表的"偏少"是什么关系?

答:完全对应——列表中 2 项"偏少"(罐头食品 6 件、医药急救包 1 件)就是准备度卡说的"2 项物资需要补充",准备度卡给"有几项要补"、列表给"哪几项、缺多少",检查页进一步给"去补充"的入口——首页 → 检查页的"缺口引导链路"贯穿三处。

问:应急准备度 75% 算高还是低?

答:75% 属于"良"的区间(60-80%)——主要物资(饮用水、手电筒)充足、次要物资(罐头、急救包)偏少,整体准备尚可但"2 项需补充"提醒还有改进空间。应急准备的目标是 80% 以上(关键物资全部充足),75% 提示用户"该补罐头和急救包了",是"够用但不够完美"的中等偏上水平。

10、总结

纵观本篇对 60-emergency-kit 首页(HomeTab,95 行)的逐块拆解,@Builder 三区拆解范式绝对不是大家在走马观花浏览 ArkUI 文档时所以为的"仅仅只是把代码拆成几个函数"那么简单。

首页用三个 @Builder 块完成了"准备度总览 + 物资明细"的组合布局:Header 点明主题、ReadyCard 给出准备度指标(75% 环形进度 + 2 项需补充)、SupplyList 给出库存明细(4 种物资充足/偏少双态)。整页的视觉语言围绕"准备"展开——环形进度 75% 是核心指标、偏少橙标是缺口提示、物资卡片是库存明细,三层表达让用户既看到"准备得怎么样"也看到"还缺什么"。

从演示到产品,首页的进化方向清晰:准备度动态计算、状态按建议量判定、物资按场景分组、临期主动预警。环形进度与双态胶囊是本页的核心,让家庭应急物资的准备"水平可见、缺口可定位"。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐