资讯动态

HarmonyOS ArkTS实战:一种动态一种颜色 —— ACG 我的动态页的多状态时间轴着色法

发布时间:2026/9/6 9:29:35 来源:尧图企业网站定制
HarmonyOS ArkTS实战一种动态一种颜色 —— ACG 我的动态页的多状态时间轴着色法应用背景12 ACG 社区acg-community第三个 Tab 是作品对应源码Func2Tab.ets共 207 行页面标题「我的动态」。它是用户回溯自己在社区里一切行为的流水账玫红主题#DB2777。本文逐行拆解TabBar 动态类型分类、OverviewCard 社区数据概览、TimelineList 多状态动态时间轴三大模块重点讲解一种动态一种颜色的多状态着色体系以及个人动态时间轴与物流时间轴的本质差异。如果说首页是看别人的内容那我的动态就是看自己的足迹。社区用户会在意我发过什么、评论过什么、收藏过什么、点赞过什么这些分散的行为需要一条时间轴串起来形成我在社区的完整轨迹。与 11 号快递的取件记录相比这一页的动态类型更丰富、状态色更多元——取件记录只有待取/已取两态而社区动态有发帖/评论/收藏/点赞/审核五种。读懂这一页你就掌握了多类型动态流这一社区高频 UI 的声明式实现。一、数据模型三种结构我的动态页定义了三个接口其中TimelineItem最能体现社区动态的数据特征interface TimelineItem { id: number; emoji: string; title: string; date: string; author: string; status: string; statusColor: string; progress: number; } interface StatCard { label: string; value: string; emoji: string; } interface TabItem { label: string; count: number; }TimelineItem与 11 号取件页的同名接口高度相似但把code单号换成了author作者statusColor从三态色扩展为多态色。author字段在 demo 里固定为我语义是这条动态是谁做的——个人动态页里作者恒为我但真实项目里若是关注的人动态作者就会是他人。这个字段的预留暗示了这一页的可扩展方向把我的动态改成关注动态只需换author数据UI 不用动。statusColor被设计成数据字段而非渲染时计算这是本页最值得注意的设计决策。它意味着每条动态的颜色由数据直接指定UI 只负责读出来画上去不写任何三元判断。这个决策的利弊后面会展开。项目源码开源https://gitee.com/codenestFlow/HarmonyOSHub二、页面骨架build() { Column() { this.Header() this.TabBar() Scroll() { Column({ space: 14 }) { this.OverviewCard() this.TimelineList() } .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) }Header TabBar Scroll三段式与取件页一致。TabBar是吸顶的动态类型筛选条永远停在 Header 下方。Header标题是「我的动态」TabBar的四类全部/帖子/评论/收藏正是动态的四种类型维度。三、Header 与 TabBar 动态类型分类Header 与系列统一写法.height(safeTop 56)alignItems(Bottom)。重点是 TabBar——它的分类从取件页的状态变成了动态类型// TabBar — 动态类型分类 Builder TabBar() { Row({ space: 6 }) { ForEach(this.tabs, (t: TabItem, idx: number) { Row({ space: 4 }) { Text(t.label).fontSize(13).fontColor(this.tabIdx idx ? #FFFFFF : C.textSub) Text(t.count.toString()).fontSize(10).fontColor(this.tabIdx idx ? #FFFFFF : C.textDim) .padding({ left: 5, right: 5, top: 1, bottom: 1 }) .backgroundColor(this.tabIdx idx ? #33FFFFFF : C.cardSoft) .borderRadius(8) } .padding({ left: 14, right: 14, top: 8, bottom: 8 }) .backgroundColor(this.tabIdx idx ? C.primary : C.card) .borderRadius(18) .border({ width: 1, color: this.tabIdx idx ? C.primary : C.stroke }) .onClick(() { this.tabIdx idx; }) }, (t: TabItem) t.label) } .width(100%).padding({ left: D.pad, right: D.pad, top: 12, bottom: 12 }) .backgroundColor(C.card) }四个标签「全部 28 / 帖子 15 / 评论 8 / 收藏 5」选中项玫红底白字 半透明白计数徽标。注意计数徽标在选中时用#33FFFFFF半透明白底未选中用C.cardSoft浅灰底——选中态的徽标融进玫红底里视觉更统一。分类维度是动态类型而非状态取件页按待取/已取/退回分状态这里按帖子/评论/收藏分类型。因为社区用户关心的不是我的动态完成没而是我发的帖子有哪些、我的评论有哪些、我收藏了什么——类型是内容社区的第一分类维度状态只是帖子内部的子属性。这个差异再次说明筛选标签的维度选择取决于业务的核心关切。四、OverviewCard 社区数据概览概览卡用 3 格统计 一行明细呈现用户的社区影响力// OverviewCard — 数据概览 Builder OverviewCard() { Column({ space: 14 }) { Row() { ForEach(this.statCards, (s: StatCard) { Column({ space: 4 }) { Text(s.emoji).fontSize(22) Text(s.value).fontSize(18).fontWeight(FontWeight.Bold).fontColor(C.text) Text(s.label).fontSize(11).fontColor(C.textDim) } .layoutWeight(1).alignItems(HorizontalAlign.Center) }, (s: StatCard) s.label) }.width(100%) Divider().color(C.stroke).strokeWidth(0.5) Row({ space: 12 }) { Column({ space: 2 }) { Text(本周发帖).fontSize(11).fontColor(C.textDim) Text(7 帖).fontSize(14).fontColor(C.text).fontWeight(FontWeight.Medium) } .alignItems(HorizontalAlign.Start).layoutWeight(1) Column({ space: 2 }) { Text(平均点赞).fontSize(11).fontColor(C.textDim) Text(42 赞).fontSize(14).fontColor(C.text).fontWeight(FontWeight.Medium) } .alignItems(HorizontalAlign.Start).layoutWeight(1) Column({ space: 2 }) { Text(活跃排名).fontSize(11).fontColor(C.textDim) Text(Top 8%).fontSize(14).fontColor(C.text).fontWeight(FontWeight.Medium) } .alignItems(HorizontalAlign.Start).layoutWeight(1) }.width(100%) } .width(100%).padding(16) .backgroundColor(C.card).borderRadius(D.rLg) .border({ width: 1, color: C.stroke }) }三格统计「我的帖子 15 / 获赞总数 1.2k / 粉丝 286」用 emoji/❤️/ 数值 标签。下方明细「本周发帖 7 帖 / 平均点赞 42 赞 / 活跃排名 Top 8%」用Divider隔开。这些指标共同回答我在社区有多活跃、多受欢迎——对比取件页的平均取件时长/代取费/退回率社区指标从服务效率转向影响力帖子数、点赞、粉丝、排名这是社区类应用衡量用户价值的核心维度。活跃排名 Top 8%是一个很有社区味的指标——用百分位排名而非绝对名次既能激励用户你超过 92% 的人又避免了第 286 名这种尴尬的绝对名次。这种相对排名的展示手法在游戏、社交、内容社区里都很常见是产品设计的巧思。五、TimelineList 多状态动态时间轴核心这是全页的灵魂。时间轴用圆节点 条件竖线串起六条动态每条动态根据类型使用不同的状态色// TimelineList — 动态时间轴 Builder TimelineList() { Column({ space: 0 }) { ForEach(this.timeline, (item: TimelineItem, idx: number) { Column() { Row({ space: 12 }) { Column({ space: 0 }) { Row() { Text(item.emoji).fontSize(18) } .width(36).height(36) .backgroundColor(C.primarySoft).borderRadius(18) .justifyContent(FlexAlign.Center) if (idx this.timeline.length - 1) { Column().width(2).height(28).backgroundColor(C.stroke) } } .alignItems(HorizontalAlign.Center) Column({ space: 8 }) { Row() { Text(item.title).fontSize(13).fontColor(C.text).fontWeight(FontWeight.Medium).layoutWeight(1) }.width(100%) Row() { Text(item.date).fontSize(11).fontColor(C.textDim).layoutWeight(1) Text(item.status).fontSize(10).fontColor(item.statusColor) .padding({ left: 8, right: 8, top: 2, bottom: 2 }) .backgroundColor(C.cardSoft).borderRadius(4) }.width(100%) Progress({ value: item.progress, total: 100 }).color(item.statusColor).width(100%) } .alignItems(HorizontalAlign.Start).layoutWeight(1) } .width(100%).alignItems(VerticalAlign.Top) } .width(100%).padding({ bottom: 4 }) .onClick(() { promptAction.showToast({ message: item.title }); }) }, (item: TimelineItem) item.id.toString()) } .width(100%).padding(14) .backgroundColor(C.card).borderRadius(D.rLg) .border({ width: 1, color: C.stroke }) }时间轴的节点 竖线结构与取件页完全一致36×36 圆节点 if (idx length-1)条件竖线 竖线height(28)固定高但右侧信息区的语义与取件页显著不同其一title是动词短语而非名词。取件页的 title 是顺丰速运 · 待取件快递公司名这里是发表了帖子「夏番追番清单」行为 对象。社区动态的 title 天然是我做了什么用动词 宾语的句式用户扫一眼就知道这是发帖/评论/收藏/点赞哪种行为。其二状态色四态化。取件页只有待取黄/已取绿/退回红三态这里的状态色扩展到四种已发布绿C.ok、已收藏玫红C.primary、审核中黄C.warn、已点赞红C.danger。四种颜色对应四种动态类型让用户通过颜色就能快速区分这是发帖、收藏、待审核还是点赞。其三Progress的颜色也跟随item.statusColor。进度条颜色和状态标签颜色绑定同一个字段——审核中的帖子进度 50%、进度条是黄色已发布的进度 100%、进度条是绿色。颜色语义贯穿标签 进度条视觉高度统一。这里有个值得深挖的设计决策statusColor是数据字段不是渲染时算出来的。取件页是fontColor(item.statusColor)同样读字段但状态色只有三态、且可以简单三元算出而社区动态有四种类型、且颜色与类型强绑定用数据字段直接指定比写三元/映射更直白。不过更工程化的做法是类型字段 颜色映射表数据存type渲染时查TYPE_COLOR[type]这样颜色统一维护、数据不冗余。两种方案各有取舍字段直存颜色省事但把表现混进了数据类型 映射表干净但多一层查表。demo 选了前者读者可自行权衡。六、动态类型的数据样本六条动态数据本身也值得一读private timeline: TimelineItem[] [ { id: 1, emoji: , title: 发表了帖子「夏番追番清单」, date: 2小时前, author: 我, status: 已发布, statusColor: C.ok, progress: 100 }, { id: 2, emoji: , title: 评论了「原神5.0攻略」, date: 5小时前, author: 我, status: 已发布, statusColor: C.ok, progress: 100 }, { id: 3, emoji: ⭐, title: 收藏了「同人画作精选」, date: 8小时前, author: 我, status: 已收藏, statusColor: C.primary, progress: 100 }, { id: 4, emoji: , title: 发表了帖子「游戏推荐」, date: 昨天, author: 我, status: 审核中, statusColor: C.warn, progress: 50 }, { id: 5, emoji: ❤️, title: 点赞了「轻小说推荐」, date: 昨天, author: 我, status: 已点赞, statusColor: C.danger, progress: 100 }, { id: 6, emoji: , title: 发表了帖子「杂谈讨论」, date: 2天前, author: 我, status: 已发布, statusColor: C.ok, progress: 100 } ];六条动态覆盖了五种行为发帖//、评论、收藏⭐、点赞❤️、以及审核中这一中间态。emoji 与行为强关联 追番帖、 评论、⭐ 收藏、❤️ 点赞status 与 statusColor 一一对应已发布绿、已收藏玫红、审核中黄、已点赞红。审核中的进度 50、绿色之外的三色点缀让这条时间轴比取件页的待取/已取单调配色生动得多。审核中这个状态是社区内容审核机制的体现——社区帖子发布后需经审核才能公开这是内容社区与物流业务的本质区别物流是物理流程运输进度线性推进社区是内容流程发布 → 审核 → 公开可能打回。时间轴因此承载了内容生命周期的可视化而不只是运输进度。七、交互类型筛选与状态驱动与取件页一样tabIdx是唯一的State当前只驱动 TabBar 高亮。源码里timeline写死点击帖子/评论/收藏标签并不会真正过滤列表——这是留给读者的扩展点。真实实现只需维护private allTimeline全量 按tabIdx过滤出timelinetabIdx0全部不过滤tabIdx1帖子filter(t t.status 已发布 || t.status 审核中)tabIdx2评论filter(t t.title.includes(评论))tabIdx3收藏filter(t t.status 已收藏)。关键点动态的类型信息需要先建模进数据如加一个type字段否则只能靠字符串includes这种脆弱的做法过滤。这也是为什么接口设计时就要想清楚筛选维度有哪些、用什么字段承载。demo 里author字段被预留、type字段缺失正是数据建模不完整的典型反面教材——真实接数据前务必补上type字段。八、与取件记录页的物流 vs 内容对比把 12 号我的动态与 11 号取件记录并排看两者共享TabBar OverviewCard TimelineList的骨架但业务差异鲜明分类维度取件页按状态待取/已取/退回动态页按类型帖子/评论/收藏时间轴语义取件页是物流轨迹运输进度线性推进动态页是行为轨迹发帖/评论/收藏/点赞的行为流状态色取件页三态黄/绿/红动态页四态绿/玫红/黄/红概览指标取件页是服务效率取件时长/代取费/退回率动态页是影响力帖子/点赞/粉丝/排名。这些差异浓缩成一句话同一条时间轴组件承载的是两种完全不同的流——物流的流和内容的流。学会区分流程型时间轴物流、订单、审批与行为型时间轴动态、足迹、操作记录你就能判断任何时间轴该用什么数据、什么分类、什么配色。九、本章小结与工程经验模块核心技术学习价值TabBar类型分类 计数徽标动态类型筛选OverviewCardemoji 统计 影响力指标社区数据概览TimelineList圆节点 条件竖线 四态色多状态行为时间轴statusColor数据字段驱动颜色多态着色体系我的动态页最值得迁移的是多状态行为时间轴范式圆节点 条件竖线搭骨架title用动词 宾语描述行为statusColor按类型赋予不同颜色发帖绿、收藏玫红、审核黄、点赞红Progress颜色跟随状态。这套范式能覆盖一切用户行为流动态、足迹、通知、操作记录。其次要牢记流程型 vs 行为型时间轴的区分流程型物流/订单状态线性推进、颜色少行为型动态/足迹类型多样、颜色多。最后筛选维度要提前建模进数据——动态页的type字段缺失是典型教训接真实数据前务必补全否则筛选只能靠脆弱的字符串匹配。十、可扩展方向这一页有很强的扩展潜力读者可自行尝试把author从我扩展为真实用户这一页就变成关注动态流给TimelineItem加type字段就能实现真正的类型筛选把progress语义从审核进度扩展为内容生命周期草稿/审核中/已发布/已下架时间轴就变成了内容管理流。同一条时间轴改数据、改字段、改颜色就能演化出动态流、通知流、审批流——这正是行为型时间轴作为通用组件的价值。十一、竖线高度固定值 vs 跟随内容本页时间轴的竖线用的是.height(28)固定值这与 11 号取件页一致。固定高度有个隐含假设每条动态的右侧内容高度恰好约 28vp。当动态只有一行 title 一行 date 一条进度条时28 刚好衔接上下节点但如果某条动态标题换行成两行右侧内容变高28 的竖线就会出现短线悬空的缝隙。更健壮的做法是让竖线layoutWeight(1)跟随右侧内容高度——把竖线放进一个与右侧内容等高的容器里用弹性高度而非固定 28。这需要把左列和右列包进一个等高 RowalignItems(VerticalAlign.Top)已保证顶部对齐竖线用layoutWeight(1)撑满剩余高度。demo 用固定 28 是因为数据都精心控制在单行真实项目若内容高度不定务必改成自适应否则时间轴会断线。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价