鸿蒙原生应用 HarmonyOS 6.0实战:电子明信片首页分类横滑与模板网格
鸿蒙原生应用 HarmonyOS 6.0实战:电子明信片首页分类横滑与模板网格
App 43「校园电子明信片」首页(HomeTab),主题色
#00B894绿色(green),4 个 Tab 分别为首页(📮)、制作(🎨)、发送(✉️)、我的(👤)。首页采用"Header + 分类横滑 + 模板网格"三区布局——白色双行 Header("电子明信片"22 号加粗 + "把心意寄给远方的TA 💌") + 5 分类横滑胶囊(全部/节日/生日/毕业/风景,选中绿底白字) + 6 个明信片模板的 2 列网格(🎓 毕业季 / 🎂 生日快乐 / 🎄 圣诞祝福 / 🌸 春日物语 / 🏖️ 夏日海滩 / 🍁 秋日私语,每张含 120 高六色渐变卡 + 44 号 emoji 居中 + 名称 + 绿色"制作"入口)。本篇基于43-e-postcard/entry/src/main/ets/pages/HomeTab.ets(共 98 行)逐段拆解,附 4 张实机截图。
一、整体结构:三区"Header + 分类 + 模板网格"布局
首页是"品牌头部 + 分类导航 + 模板展示"的三区布局——3 个 @Builder 块:
build() {
Column() {
this.Header()
this.CatRow()
Scroll() {
Column({ space: 14 }) {
this.TemplateGrid()
}
.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 — 双行品牌头(标题 + 副标题),白底固定
- CatRow — 5 分类横滑胶囊(全部/节日/生日/毕业/风景),白底横条固定在 Header 下方
- TemplateGrid — 6 个模板卡片的 2 列网格,是本页的信息主体
与其他 App 首页"Scroll 内嵌 Banner"不同,本页把分类胶囊独立在 Scroll 之外(紧贴 Header)——因为分类是模板筛选的"主控",需要常驻顶部随时切换,而非随内容滚走。这是"筛选器固定在内容上方"的标准布局决策。

二、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: 4 })
Text('把心意寄给远方的TA 💌').fontSize(12).fontColor(C.textDim).width('100%')
.padding({ left: D.pad, right: D.pad, bottom: 12 })
}.width('100%').backgroundColor(C.card)
}
细节:
- 标题:"电子明信片"22 号加粗,直白点题(明信片的电子化形态)。
- 副标题:"把心意寄给远方的TA 💌"——"TA"不区分性别(与 App 39 同款中立表达),💌 信封 emoji 呼应产品动作(寄出心意)。
- 安全区:
safeTop + 10避让状态栏,双行间距(bottom 4 / 12)层次清晰。 - 白底全宽:与 App 39/42 首页同款双行 Header 范式。
三、CatRow:5 分类横滑胶囊
CatRow() {
Scroll() {
Row({ space: 10 }) {
ForEach(this.cats, (c: string, idx: number) => {
Text(c).fontSize(13)
.fontColor(this.activeCat === idx ? '#FFFFFF' : C.textSub)
.padding({ left: 14, right: 14, top: 7, bottom: 7 })
.backgroundColor(this.activeCat === idx ? C.primary : C.card).borderRadius(16)
.onClick(() => { this.activeCat = idx; })
}, (c: string) => c)
}
}
.scrollable(ScrollDirection.Horizontal).scrollBar(BarState.Off).width('100%')
.padding({ left: D.pad, right: D.pad, top: 8, bottom: 8 }).backgroundColor(C.card)
}
5 个分类(21 行):['全部', '节日', '生日', '毕业', '风景']——"全部"兜底 + 4 个模板场景分类,与 6 个模板的 category 字段(节日/生日/毕业/风景)完全对应。
技术拆解:
- 横滑容器:内层
Scroll设scrollable(ScrollDirection.Horizontal)横向滚动,5 个胶囊超屏宽时可横滑(前 4 个 + 第 5 个部分可见,暗示可滑)。 - 选中态:
@State activeCat驱动——选中绿底白字(C.primary)、未选白底灰字(C.card,与页面底色形成层次),这是"胶囊导航"的标准实现(App 38 同款)。 - 分类筛选语义:当前 Demo 点击分类仅切换高亮(模板列表不过滤)——产品化后
activeCat === 0 ? 全部模板 : templates.filter(t => t.category === cats[activeCat])一行过滤即可。 - 白底横条:容器
padding({ top: 8, bottom: 8 })+backgroundColor(C.card),分类行自带白底横条,与 Header 连成一块完整的顶部区域。
四、TemplateGrid:模板渐变网格
TemplateGrid() {
Grid() {
ForEach(this.templates, (t: Template) => {
GridItem() {
Column() {
Stack({ alignContent: Alignment.Center }) {
Column().width('100%').height(120)
.borderRadius({ topLeft: D.rMd, topRight: D.rMd })
.linearGradient({ angle: 135, colors: [[t.gradient[0], 0.0], [t.gradient[1], 1.0]] })
Text(t.emoji).fontSize(44)
}
Row() {
Text(t.name).fontSize(13).fontWeight(FontWeight.Medium).fontColor(C.text).layoutWeight(1)
Text('制作').fontSize(11).fontColor(C.primary)
}.width('100%').padding(10)
}
.width('100%').backgroundColor(C.card).borderRadius(D.rMd).border({ width: 1, color: C.stroke })
.onClick(() => { promptAction.showToast({ message: '制作: ' + t.name }); })
}
}, (t: Template) => t.id.toString())
}.columnsTemplate('1fr 1fr').columnsGap(12).rowsGap(12).width('100%')
}
6 个模板(22-29 行),每个自带渐变配色:
| 模板 | emoji | 渐变(135°) | 分类 |
|---|---|---|---|
| 毕业季 | 🎓 | #00B894 → #4BC9A8(绿) | 毕业 |
| 生日快乐 | 🎂 | #FF6B9D → #FF9DBA(粉) | 生日 |
| 圣诞祝福 | 🎄 | #E63946 → #F07878(红) | 节日 |
| 春日物语 | 🌸 | #9B51E0 → #BC85E8(紫) | 风景 |
| 夏日海滩 | 🏖️ | #0984E3 → #5BAAEF(蓝) | 风景 |
| 秋日私语 | 🍁 | #F2994A → #F5B974(橙) | 风景 |
技术拆解:
- Grid 两列网格:
columnsTemplate('1fr 1fr')+ 12 间距——与 App 42 话题广场同款两列网格。 - 渐变卡片:
linearGradient({ angle: 135, colors: [[t.gradient[0], 0.0], [t.gradient[1], 1.0]] })——每个模板的渐变颜色写死在数据里,六个模板六种渐变色(绿/粉/红/紫/蓝/橙),视觉上五彩缤纷,直接展示"模板即配色"的产品概念——选模板就是选配色。 - Stack 叠加:渐变底(120 高、只圆上两角)+ 44 号 emoji 居中叠加——
Stack({ alignContent: Alignment.Center })把 emoji 盖在渐变上,形成"模板封面"。 - 信息行:名称 13 号 Medium(
layoutWeight(1)占左)+ "制作"11 号绿色入口(暗示点击开始制作)——与 App 42 话题卡"名称 + 条数"同构,但动作从"条数"换成"制作"。 - 整卡点击:点击弹"制作: XX"Toast——产品化后跳转制作页(App 43 制作 Tab)并预选该模板。
五、跨页数据自洽:模板是全链路的起点
首页模板与制作页、发送页形成完整链路:
- 首页"毕业季"模板 ↔ 制作页默认背景 🎓(
bgs[0])↔ 发送页卡片预览"毕业季明信片 · 已完成制作"——同一个模板贯穿"选模板 → 制作 → 发送"三页,首页是链路的起点。 - 首页 6 模板的渐变 ↔ 制作页 5 个背景 emoji(🎓🎂🌸🏖️🍁)——制作页背景选择正是首页模板的简化版(去掉 🎄),数据同源。
- 分类体系 ↔ 模板的
category字段——"全部/节日/生日/毕业/风景"5 分类 = 4 个真实分类 + 全部兜底。 - 我的页"12 收藏模板" ↔ 首页模板的收藏动作——收藏的模板在我的页"收藏模板"菜单中展示。

六、实机截图与交互演示
本节结合 4 张实机截图,逐张还原首页的视觉效果与交互过程。
1. 首页首屏:品牌头 + 分类胶囊 + 模板网格
第一张截图是进入 App 43 后的默认首屏:顶部"电子明信片"标题与"把心意寄给远方的TA 💌"副标题;下方 5 个分类胶囊(全部绿底选中态 / 节日 / 生日 / 毕业 / 风景);再往下是 2 列模板网格——左列 🎓 毕业季(绿色渐变卡)、🎄 圣诞祝福(红色渐变卡),右列 🎂 生日快乐(粉色渐变卡)、🌸 春日物语(紫色渐变卡),四种渐变色交相辉映,模板的"视觉即配色"概念一目了然。
2. 点击"节日":分类胶囊选中切换
第二张截图是点击"节日"分类后的状态:绿色选中态从"全部"切换到"节日"——@State activeCat 由 0 变 2,胶囊切换即时反馈。虽然 Demo 中模板列表未过滤(6 模板共用),但分类切换交互完整,为"按分类筛选模板"预留了数据过滤位置。
3. 点击"毕业季"模板:弹出"制作"Toast
第三张截图是点击左列第一张"🎓 毕业季"模板卡后的反馈:弹出"制作: 毕业季"Toast。每张模板卡独立挂载 onClick 且闭包捕获各自的 t.name,点击哪个模板就弹出"制作: 哪个"——"制作"动作的语义暗示点击即开始制作该模板。
4. 滚动到底:全部模板可见
第四张截图是滚动到底部的视图:第三行模板——左列 🏖️ 夏日海滩(蓝色渐变卡)、右列 🍁 秋日私语(橙色渐变卡)完整可见。6 个模板六种渐变色全部呈现(绿/粉/红/紫/蓝/橙),Scroll 滚动流畅,底部安全区内边距保证 Tab 栏可点。
七、扩展思考:模板系统的产品设计
首页的 6 个模板是明信片产品的核心资产,其设计思路值得展开:
- 模板即配色:模板的差异化核心是"渐变配色 + emoji 意象"(🎓 毕业绿 / 🎂 生日粉 / 🎄 圣诞红)——用户选模板 = 选场景 + 选心情,无需理解设计参数,降低制作门槛。
- 模板的数据模型:
Template接口{ id, emoji, name, gradient[], category }中 gradient 数组承载配色、category 承载分类——真实产品可扩展coverUrl(封面图)、usage(使用次数)、hot(是否热门)。 - 模板的运营:按节日/热点上新模板(开学季、考试周、情人节)——模板是内容的"常青资产",运营中心是模板库而非帖子流。
- 模板与个性化:用户可收藏模板(我的页 12 收藏模板)、基于收藏推荐同类模板——模板推荐是明信片产品的增长引擎。
- 模板的分级:免费模板 + 会员模板(更多渐变/贴纸/字体)——模板是商业化(会员)的天然载体,与字体选择(制作页 4 字体)联动。
八、扩展思考:从模板到完成品的完整链路
首页只是链路的起点,把"选模板 → 制作 → 发送 → 我的"串起来看:
- 选模板(首页):6 模板六色渐变,用户按场景/心情选择——点击"制作"进入制作页。
- 做定制(制作页):默认背景继承所选模板 emoji(🎓)→ 换背景/写祝福/选字体 → 实时预览——制作页的
@State驱动所见即所得。 - 填收件(发送页):接收人(手输或最近联系人)+ 立即/定时发送 → 发送成功。
- 沉淀(我的页):已发送 26 / 已收到 18 张的统计与菜单——明信片的历史归档。
- 闭环数据:发送成功 → 我的页"已发送" +1;对方收到 → "已收到" +1——数据自洽贯穿五步。

九、开发者视角:首页的调试与验证技巧
- 渐变数据驱动的验证:模板渐变来自
t.gradient[0]/[1]——若数据缺失(undefined)渐变会崩溃,调试时确保所有模板都配齐两个渐变色。 - 分类过滤的边界:
activeCat切换后若实现过滤,需测试"全部"(显示 6 个)与各分类(毕业 1 个/风景 3 个/生日 1 个/节日 1 个)的列表长度——当前 4 分类中风景最多(3 个),过滤逻辑正确性一目了然。 - Stack 叠加的对齐:
Stack({ alignContent: Alignment.Center })把 emoji 居中在 120 高渐变上——若 emoji 字号过大(44 号在窄卡上)会溢出卡片,窄屏需降字号。 - 分类胶囊的横滑:5 个胶囊超屏宽,最后一个(风景)部分可见是"可滑"暗示——验证横向滑动不触发页面纵向滚动(正交嵌套)。
- 模板卡点击与"制作"入口:整卡点击弹"制作: 名称"——若未来"制作"文字单独挂事件跳转制作页,需避免与整卡点击冲突(冒泡处理)。
十、系列横向对比:模板/素材类首页的四种形态
App 43 首页是"素材库首页",与系列其他内容型首页对比可看清模板类产品的设计特点:
| 首页类型 | 代表 App | 内容单元 | 核心动作 | 视觉特征 |
|---|---|---|---|---|
| 模板库 | App 43 明信片 | 渐变模板卡 | 制作 | 六色渐变 |
| 话题目录 | App 42 树洞 | 话题网格 | 浏览 | 四行信息 |
| 相册瀑布 | App 40 照片 | 相册卡 | 查看 | 高度错落 |
| 帖子流 | App 41 表白墙 | 文字帖 | 点赞 | 全文卡片 |
模板库的差异点:
- 内容即工具:模板是"素材"而非"内容"——用户看模板不是"消费"而是"准备制作",所以卡片的核心动作是"制作"(而非点赞/浏览),点击语义直接导向生产流程。
- 视觉是卖点:模板卡用渐变 + emoji 直接展示"做出来长什么样"——模板的预览即产品力,六色渐变让首页五彩缤纷(对比内容型首页的单色卡片),这是素材类页面的视觉特色。
- 分类即场景:分类"节日/生日/毕业/风景"是使用场景(不是内容类型)——用户按"要送给谁、什么场合"选模板,分类的出发点是"用途"而非"形态"。
与 App 42 话题网格的对比:同为 2 列网格,话题卡是"emoji + 名称 + 描述 + 条数"(信息型),模板卡是"渐变 + emoji + 名称 + 制作"(视觉型)——话题靠信息说服(条数)、模板靠视觉吸引(渐变),两代网格页展示了 Grid 在不同内容类型下的适配。
十一、开发者视角:首页的调试与验证技巧
- 渐变数据的完整性:
t.gradient[0]/[1]是模板渐变的数据源——6 个模板必须都配两个渐变色,否则渲染崩溃;新增模板时检查gradient数组长度,可加构建期校验。 - 分类过滤的测试用例:若实现按 category 过滤,测试各分类的模板数量(全部 6/毕业 1/生日 1/节日 1/风景 3)——风景最多(3 个)最能验证过滤正确性;"全部"应显示全部 6 个。
- Stack 的 emoji 溢出:44 号 emoji 在窄屏(卡片约 580 宽)内居中无碍;若卡片更窄(改三列),emoji 需降号——布局改动后重点回归。
- 横滑与网格的嵌套滚动:分类胶囊横向 Scroll 在外层纵向 Scroll 之外(不是嵌套),无滚动冲突;若未来把分类放进内容区形成嵌套,需确认方向正交。
- 模板点击的动作语义:整卡点击弹"制作: 名称"——若产品化后点击跳制作页,需处理"从首页到制作页的模板参数传递"(模板 id),当前 Toast 占位已暗示跳转方向。

十二、扩展思考:明信片模板的节日运营与情感设计
首页模板库是明信片产品的情感入口,其运营设计值得展开:
- 节日模板节奏:按日历运营模板——毕业季(6 月)推 🎓 毕业季、圣诞(12 月)推 🎄 圣诞祝福、春节推生肖模板——模板库随节日换血,用户每逢佳节"想寄一张"时有对味模板可用,是明信片产品的核心运营节奏。
- 模板的情感场景库:除节日外,日常情感场景更丰富——道歉(对不起)、加油(考试祝福)、告白(喜欢你)、生日(生日快乐)——模板分类可增加"情感场景"维度(当前 5 分类中的节日/生日/毕业已隐含场景),让"想表达什么"直接对应模板。
- 模板的收藏与推荐:用户收藏模板(我的页 12 收藏模板)后,推荐"同风格模板"(同渐变系/同场景)——收藏数据是模板推荐引擎的输入。
- 模板的限量与会员:节日限定模板(限量)、高级模板(会员专属渐变/贴纸)——模板是明信片商业化(会员)的天然载体。
- 模板的 UGC 扩展:允许用户上传自制模板(自定义渐变 + 贴纸)——模板库从运营供给走向 UGC 共创,是社区化的方向。
十三、FAQ 与一句话总结
Q1:为什么模板用渐变而不是图片? 渐变是代码生成的(linearGradient),零资源、零加载、任意机型一致,且 6 模板六种配色在 Demo 阶段足以展示"模板即配色"的概念。真实产品用运营设计的封面图,布局代码零改动(把渐变 Column 换成 Image)。
Q2:分类胶囊切换后模板为什么不变? Demo 为演示简洁共用 6 模板列表。产品化后按 category 过滤(一行 filter),"风景"分类会只剩 3 个模板、"毕业"只剩 1 个——过滤逻辑已就绪。
Q3:"制作"和整卡点击有什么区别? 当前都是弹 Toast(整卡点击"制作: 名称")。产品化后整卡点击跳转制作页并预选该模板,"制作"文字是强化的动作暗示——两者指向同一跳转。
Q4:为什么只有 6 个模板? 6 个恰好覆盖"毕业/生日/节日/风景"4 类场景且一屏半展示完整,信息量适中。模板库可无限扩展(6 → 60),Grid 自动排布无需改布局。
Q5:模板的渐变配色有什么讲究? 每个模板的配色贴合场景意象——毕业用代表青春的青绿、生日用甜蜜的粉、圣诞用喜庆的红、夏海用清凉的蓝、秋日用温暖的橙——配色即情绪,用户扫一眼就能找到"想寄的那种感觉"。
一句话总结:首页用"双行品牌头 + 分类横滑 + 模板渐变网格"三区结构完成了明信片模板的展示与导航,6 个模板六种渐变配色的"模板即配色"设计让首页五彩缤纷、识别度极高。分类胶囊的横滑与选中态、Grid 两列模板卡、渐变 + emoji 的 Stack 叠加,都是模板库类页面的标准手法——98 行代码,一个让用户"看到就想做一张"的明信片首页。
最后从验收视角确认:四张实机截图覆盖了首屏(品牌头+分类胶囊+四模板)、分类切换(节日选中)、模板点击(制作: 毕业季 Toast)、滚动底部(全部 6 模板六色渐变可见)四个状态,分类横滑的正交滚动、Grid 两列布局、渐变 + emoji 的 Stack 叠加、模板整卡点击均验证正常。6 模板的分类字段与 5 个分类胶囊(全部/节日/生日/毕业/风景)匹配。整页 98 行代码完成"模板库 + 分类导航"的完整结构,验收通过,可作为模板/素材类产品首页的参考范本。
补充开发问答:Q1 为什么分类胶囊用白底而非浅底?——与 Header 连成完整白色顶部区域,未选胶囊白底融入背景、选中绿底跳出,层级更清晰。Q2 模板渐变与 App 主题色的关系?——主题绿是"品牌色",模板六色是"内容色",品牌色用于 UI 控件(胶囊/按钮)、内容色用于模板卡片,二者互不干扰。Q3 Grid 两列模板卡高度会参差吗?——渐变区固定 120 高 + 信息行固定高度,同列高度一致、跨列整齐,无参差问题。Q4 模板点击后的"制作"流程如何衔接?——点击模板应携带模板 id 跳转制作页并预选背景(🎓 对应 bgs[0]),当前 Toast 占位已暗示跳转方向。Q5 分类"全部"的设计价值?——默认展示全部模板(6 个),分类是筛选入口,用户不分类也能浏览,"全部"兜底降低认知负担。这些细节共同保证了模板库首页的可用性与视觉完成度。
最后以一句收尾:模板库的首页,让每一份心意都有了好看的载体。 回望整页,从双行品牌头到六色渐变模板网格,从分类横滑到制作入口,每个设计都在引导用户迈出"寄出心意"的第一步——这就是明信片首页的全部使命,也是本页完成度最高的地方。 把心意做成明信片,让距离不再是心意的阻隔。 模板库的故事,从这里开始,也将在每一次制作与寄送中延续。

更多推荐





所有评论(0)