鸿蒙原生应用 ArkUI 实战:红色渐变告警卡 + 临期双条件渲染 —— 续费提醒首页的扣款预警架构
鸿蒙原生应用 ArkUI 实战:红色渐变告警卡 + 临期双条件渲染 —— 续费提醒首页的扣款预警架构
App 55「自动续费提醒」首页(HomeTab),主题色
#FF6B6B珊瑚红,4 个 Tab 分别为首页(⏰)、添加(➕)、日历(📅)、我的(👤)。本篇基于55-renewal-reminder/entry/src/main/ets/pages/HomeTab.ets(共 92 行)逐段拆解,附 4 张实机截图。

一、整体结构:三区"Header + 告警卡 + 列表"布局
首页是"品牌头部 + 扣款告警 + 近期扣款列表"的三区布局——3 个 @Builder 块:
build() {
Column() {
this.Header()
Scroll() {
Column({ space: 14 }) {
this.AlertCard()
this.SectionTitle('即将扣款')
this.ItemList()
}
.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)
}
3 块结构:Header(单行品牌头)→ AlertCard(红色渐变告警卡)→ ItemList(4 条扣款列表)。与 App 52/53/54 的"汇总卡"不同,本页第一卡是告警卡——不展示统计数字,而是直接喊出"2 天后有扣款"。续费提醒的核心不是"看账"而是"防偷袭",首页第一屏就要把最近的扣款威胁推到用户眼前。
二、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)
}
22 号加粗、safeTop + 10 避让状态栏、白底全宽。与系列工具型首页(App 52/53/54)同款单行标题范式。
三、AlertCard:红色渐变告警卡
AlertCard() {
Row({ space: 14 }) {
Text('⏰').fontSize(40)
Column({ space: 4 }) {
Text('2 天后有扣款').fontSize(17).fontWeight(FontWeight.Bold).fontColor('#FFFFFF')
Text('视频VIP会员将扣费 ¥25').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从#FF6B6B珊瑚红渐变到#FFB0B0浅红——红色在语义上是"警示/注意",与续费提醒"防漏扣"的产品气质契合(对比 App 53 生态绿 = 安全在保,55 珊瑚红 = 扣款预警)。 - 横排布局而非纵排:
Row({ space: 14 })——40 号 ⏰ 大图标居左 + 文字区layoutWeight(1)撑满右侧。与 App 52/54 的纵排汇总卡(Column)不同,告警卡是"图标 + 文案"的横向横幅,更接近系统通知的视觉形态。 - 两级文案:17 号 Bold"2 天后有扣款"(结论)+ 12 号 90% 透明"视频VIP会员将扣费 ¥25"(细节)——先抛威胁等级,再给具体对象,一句话说清"谁、什么时候、扣多少"。
- 数据取自列表首项:告警内容与
items[0](视频VIP 2 天后 ¥25)完全一致——告警卡 = 最紧急项的放大呈现,产品化后应由"daysLeft 最小的未过期待扣款项"动态生成。
四、RenewItem 数据模型 + SectionTitle
interface RenewItem {
id: number;
emoji: string;
name: string;
amount: number;
daysLeft: number;
}
private items: RenewItem[] = [
{ id: 1, emoji: '🎬', name: '视频VIP会员', amount: 25, daysLeft: 2 },
{ id: 2, emoji: '🎵', name: '音乐会员', amount: 15, daysLeft: 5 },
{ id: 3, emoji: '☁️', name: '云存储服务', amount: 6, daysLeft: 8 },
{ id: 4, emoji: '💻', name: '设计软件年费', amount: 688, daysLeft: 15 }
];
RenewItem 五字段:daysLeft(距扣款天数)是本页的核心驱动字段——列表按它升序(2→5→8→15,最紧急置顶),颜色与临期标签都由它判定。注意设计软件年费 688 元夹在列表末尾——金额最大但时间最远,按时间排序而非金额排序,续费提醒的正确姿势。
SectionTitle(title: string) {
Row() { Text(title).fontSize(16).fontWeight(FontWeight.Bold).fontColor(C.text) }.width('100%')
}
纯标题无"全部 >"入口——与 App 53 保修页同款(首页列表即全部近期项,无需跳转)。
五、ItemList:临期双条件渲染列表
ItemList() {
Column({ space: 10 }) {
ForEach(this.items, (r: RenewItem) => {
Row({ space: 12 }) {
Row() { Text(r.emoji).fontSize(24) }
.width(48).height(48).backgroundColor(C.primarySoft).borderRadius(D.rSm).justifyContent(FlexAlign.Center)
Column({ space: 4 }) {
Text(r.name).fontSize(14).fontWeight(FontWeight.Medium).fontColor(C.text)
Text(r.daysLeft + ' 天后扣款 ¥' + r.amount).fontSize(12)
.fontColor(r.daysLeft <= 3 ? C.danger : C.textDim)
}.alignItems(HorizontalAlign.Start).layoutWeight(1)
if (r.daysLeft <= 3) {
Text('临期').fontSize(11).fontColor(C.danger)
.padding({ left: 8, right: 8, top: 3, bottom: 3 }).backgroundColor('#FDEAEA').borderRadius(6)
}
}
.width('100%').padding(12).backgroundColor(C.card).borderRadius(D.rMd).border({ width: 1, color: C.stroke })
.onClick(() => { promptAction.showToast({ message: r.name }); })
}, (r: RenewItem) => r.id.toString())
}.width('100%')
}
逐点拆解:
- 48×48 主色软底图标块:
C.primarySoft(#FFE8E8淡红)圆角底 + 24 号 emoji——与主题红同色系,品牌统一。 - 副文案条件变色(79-80 行):
r.daysLeft <= 3 ? C.danger : C.textDim——≤3 天的扣款副文案变红("2 天后扣款 ¥25"红字),其余保持淡灰,文字本身即告警。 - 临期胶囊条件渲染(82-85 行):
if (r.daysLeft <= 3)才渲染"临期"胶囊(红字粉底#FDEAEA圆角 6)——胶囊是条件存在的,不是变色切换。与 App 53 的"三态胶囊恒在(在保/临期/过保)"不同,本页是"有威胁才出现"——列表中只有视频VIP(2 天)带临期标签,其余三条干净无标,视觉噪音最小化。 - 双条件同源:副文案变色与临期胶囊共用同一阈值
daysLeft <= 3——红字 + 红胶囊双重告警,一处判定两处呈现,不会出现"字红了但胶囊没出"的不一致。

六、跨页数据自洽:扣款预警的全局闭环
{ id: 1, emoji: '🎬', name: '视频VIP会员', amount: 25, daysLeft: 2 },
{ id: 1, emoji: '🎬', name: '视频VIP会员', month: 9, day: 1, amount: 25 },
- 首页"视频VIP 25 元 2 天后" ↔ 日历页"视频VIP会员 9月1日 ¥25"——同一项扣款,金额一致,首页按"还剩几天"呈现、日历按"几月几日"呈现。
- 首页 4 项 ↔ 日历页 5 项——首页是"近期即将扣款"的重点列表(4 项),日历是全年时间轴(含 10 月新闻订阅、1 月设计软件年费),近期 vs 全年的范围差异。
- 首页"设计软件年费 688 元" ↔ 日历页"1月20日 ¥688" + 我的页"¥746 年度支出"——年费 688 是年度总额的最大单项。
- 首页"临期 ≤3 天" ↔ 添加页"提前提醒 1/3/7 天"(
remindDays = 3默认)——告警阈值与提醒天数默认值一致,告警与提醒共用同一时间尺度。

七、珊瑚红主题的视觉策略
export class C {
static readonly bg: string = '#F2F5FB';
static readonly card: string = '#FFFFFF';
static readonly cardSoft: string = '#F4F6FB';
static readonly stroke: string = '#EAEEF6';
static readonly text: string = '#1C2333';
static readonly textSub: string = '#5A6483';
static readonly textDim: string = '#9AA3BC';
static readonly primary: string = '#FF6B6B';
static readonly primarySoft: string = '#FFE8E8';
static readonly accent: string = '#FFB0B0';
static readonly warn: string = '#FF9F1C';
static readonly danger: string = '#FF5A6E';
static readonly ok: string = '#2BB673';
}
逐点拆解:
primary = #FF6B6B:珊瑚红是系列中首个"红色系主色"应用——红色天然传达"警示/紧急",续费提醒用红色表达"你的钱即将被扣"的紧迫感。primarySoft = #FFE8E8:淡红用于图标块底色——主红的低浓度变体。- 双红分工:
primary #FF6B6B(主题红,告警卡/图标底)与danger #FF5A6E(危险红,临期文字/胶囊)色值接近——主色与警示色同色系,整页红色语言统一,不会出现"红配绿"的冲突。
八、系列横向对比:首页第一卡的四种形态
| 首页 | 代表 App | 第一卡类型 | 核心信息 | 主题色 |
|---|---|---|---|---|
| 告警卡 | App 55 续费 | 红色渐变告警卡 | "2 天后有扣款" | #FF6B6B 珊瑚红 |
| 汇总卡 | App 54 订阅 | 紫色渐变汇总卡 | 月度支出 53.30 | #9B51E0 梦幻紫 |
| 三列汇总 | App 53 保修 | 绿色渐变三列卡 | 8/2/1 三态统计 | #00A862 生态绿 |
| 金额汇总 | App 52 票据 | 蓝色渐变金额卡 | 本月总额 1010 | #0066CC 科技蓝 |
差异点:App 55 是系列中唯一用"告警卡"打头阵的首页——52/53/54 的第一卡都是"统计数字"(金额/数量),55 的第一卡是"即将发生的事件"(2 天后扣款)。统计卡回答"现在是什么状况",告警卡回答"马上要发生什么",后者的时间紧迫感是续费提醒场景的核心体验。

九、开发者视角:调试与验证技巧
- 列表排序依据:
items按daysLeft升序硬编码(2→5→8→15)——产品化后必须动态排序(sort((a,b) => a.daysLeft - b.daysLeft)),否则新增项目插入数组末尾会破坏"最紧急置顶"的信息架构。 - 双条件同源:副文案变色与临期胶囊共用
daysLeft <= 3——若后续调整阈值(如改为 5 天),两处必须同时改,建议提取常量URGENT_DAYS = 3统一管理。 - 告警卡数据联动:告警卡"2 天后有扣款"硬编码——产品化应从列表取
daysLeft最小项动态生成,无待扣款时告警卡应切换为"近期无扣款"的安全态,避免空数据渲染出错误的告警。 - 条件渲染 vs 条件样式:临期胶囊用
if条件渲染(不存在于组件树),副文案用三元条件样式(恒在只变色)——"出现/消失"用 if,"变色"用三元,两种条件策略各司其职,混用会造成布局抖动。
十、演进方向
| 方向 | 当前状态 | 产品化演进 |
|---|---|---|
| 告警动态化 | 硬编码"2 天后" | 取 daysLeft 最小项动态生成 |
| 列表排序 | 数组声明顺序 | 按 daysLeft 升序动态排序 |
| 天数计算 | 硬编码 2/5/8/15 | 扣款日 - 今日 实时计算 |
| 临期阈值 | 固定 3 天 | 跟随添加页的提醒天数设置 |
| 卡片详情 | Toast 项目名 | 跳详情页(扣款历史/关闭续费入口) |
十一、一句话总结
首页以"红色渐变告警卡 + 临期双条件渲染列表"完成了续费扣款的预警总览。linearGradient 珊瑚红告警卡(⏰40 号横排横幅 + 两级文案)、daysLeft <= 3 同源双条件(副文案变红 + 临期胶囊条件渲染)、48×48 淡红底图标块、列表按剩余天数升序(最紧急置顶)——92 行代码,一个"先喊威胁 → 再列明细"的扣款预警页,也是"事件驱动"型首页的标准范式。

更多推荐




所有评论(0)