发布时间:2026/9/4 22:09:03
鸿蒙原生应用实战:四色占比进度条驱动的分类记录页三态操作设计 鸿蒙原生应用实战四色占比进度条驱动的分类记录页三态操作设计App 15「智能垃圾分类」分类 TabFunc2Tab是分类历史记录页。整页用 Header 4 个胶囊筛选 Tab全部/已分类/待处理/错误分类 3 栏统计概览 4 类彩色占比进度条可回收 30% 蓝/厨余 48% 绿/有害 12% 红/其他 10% 灰 6 条记录时间线每条记录按状态显示不同操作待处理→立即分类、错误分类→重新分类、已分类→✓ 已正确分类组成。本篇基于15-trash-classify/entry/src/main/ets/pages/Func2Tab.ets约 248 行逐段拆解附 4 张实机截图。一、整体结构筛选 统计 占比 时间线Func2Tab 与 App 14 预约页同构Header TabBar 固定、Scroll 内容流但多了分类占比模块build() { Column() { this.Header() this.TabBar() Scroll() { Column({ space: 16 }) { this.StatsOverview() this.CategoryProgress() this.SectionTitle(分类记录) this.RecordTimeline() } .width(100%) .padding({ left: D.pad, right: D.pad, top: 16, bottom: D.pad this.safeBottom 20 }) } .layoutWeight(1).scrollBar(BarState.Off).align(Alignment.Top) } .width(100%).height(100%).backgroundColor(C.bg) }4 个模块StatsOverview3 栏统计→CategoryProgress4 类占比——本页特色→ SectionTitle(分类记录) → RecordTimeline6 条时间线。与 App 14 预约页的差异App 14 是统计 → 时间线两段App 15 是统计 → 占比 → 时间线三段——多了一层分类构成分析。占比图让用户一眼看到我分类的垃圾都是什么类型是数据可视化的进阶用法。项目源码开源https://gitee.com/codenestFlow/HarmonyOSHub二、Header TabBar4 个胶囊筛选Header 单行标题分类记录TabBar 是 4 个胶囊全部/已分类/待处理/错误分类Builder Header() { Row() { Text(分类记录) .fontSize(20).fontWeight(FontWeight.Bold).fontColor(C.text) } .width(100%).height(this.safeTop 56) .padding({ top: this.safeTop, left: D.pad, right: D.pad }) .backgroundColor(C.card) .alignItems(VerticalAlign.Bottom) } Builder TabBar() { Row() { ForEach(this.tabs, (t: FilterTab) { Text(t.label) .fontSize(13) .fontColor(this.activeTab t.id ? C.primary : C.textSub) .fontWeight(this.activeTab t.id ? FontWeight.Bold : FontWeight.Normal) .padding({ left: 14, right: 14, top: 8, bottom: 8 }) .backgroundColor(this.activeTab t.id ? C.primarySoft : transparent) .borderRadius(16) .onClick(() { this.activeTab t.id; }) }, (t: FilterTab) t.id.toString()) } .width(100%) .padding({ left: D.pad, right: D.pad, top: 12, bottom: 12 }) .backgroundColor(C.card) }4 个 Tab 的 id 与状态值绑定App 14 同款设计private tabs: FilterTab[] [ { id: 0, label: 全部 }, { id: 1, label: 已分类 }, { id: 2, label: 待处理 }, { id: 3, label: 错误分类 } ];id status 值id1 已分类records 里 status1、id2 待处理status2、id3 错误分类status3——筛选逻辑r.status this.activeTab一行搞定。与 App 14 的差异App 14 的 Tab 顺序是全部/待确认/已完成/已取消按待办优先排列App 15 是全部/已分类/待处理/错误分类按数量优先排列已分类 302 条最多放第 2——Tab 顺序反映业务重心。三、StatsOverview3 栏统计StatsOverview 与 App 14 同构3 栏数字 标签Builder StatsOverview() { Row() { ForEach(this.stats, (s: StatItem) { Column({ space: 4 }) { Text(s.value).fontSize(22).fontWeight(FontWeight.Bold).fontColor(C.text) Text(s.label).fontSize(11).fontColor(C.textDim) } .layoutWeight(1) .alignItems(HorizontalAlign.Center) }, (s: StatItem) s.label) } .width(100%) .padding({ top: 16, bottom: 16 }) .backgroundColor(C.card).borderRadius(D.rMd) .border({ width: 1, color: C.stroke }) }数据总记录 328 / 已分类 302 / 待处理 26。302 26 328数据自洽已分类 待处理 总记录错误分类记录在 302 里计数还是单独demo 里错误分类是 status3如果算进已分类口径有歧义——但 328 302 26 至少总 已 待成立。3 栏同色C.text深色——颜色留给状态原则占比进度条和状态标签才是彩色的。四、CategoryProgress四色占比进度条本页特色CategoryProgress 是 4 类垃圾的占比进度条每类一条彩色进度条Builder CategoryProgress() { Column({ space: 12 }) { Text(分类占比).fontSize(15).fontWeight(FontWeight.Bold).fontColor(C.text).width(100%) Row({ space: 8 }) { Text(♻️ 可回收).fontSize(11).fontColor(C.textDim).width(60) Progress({ value: 30, total: 100 }).color(#3B82F6).backgroundColor(C.cardSoft).layoutWeight(1).height(6) Text(30%).fontSize(11).fontColor(C.textSub) } Row({ space: 8 }) { Text( 厨余).fontSize(11).fontColor(C.textDim).width(60) Progress({ value: 48, total: 100 }).color(#22C55E).backgroundColor(C.cardSoft).layoutWeight(1).height(6) Text(48%).fontSize(11).fontColor(C.textSub) } Row({ space: 8 }) { Text(⚠️ 有害).fontSize(11).fontColor(C.textDim).width(60) Progress({ value: 12, total: 100 }).color(#EF4444).backgroundColor(C.cardSoft).layoutWeight(1).height(6) Text(12%).fontSize(11).fontColor(C.textSub) } Row({ space: 8 }) { Text(️ 其他).fontSize(11).fontColor(C.textDim).width(60) Progress({ value: 10, total: 100 }).color(#9CA3AF).backgroundColor(C.cardSoft).layoutWeight(1).height(6) Text(10%).fontSize(11).fontColor(C.textSub) } } .width(100%) .padding(14) .backgroundColor(C.card).borderRadius(D.rMd) .border({ width: 1, color: C.stroke }) }4.1 4 条进度条的数据厨余 48%绿色——占比最高符合厨余垃圾是日常生活产生最多垃圾的事实可回收 30%蓝色有害 12%红色其他 10%灰色30 48 12 10 100%数据完美闭合。占比数据有现实依据厨余最多、有害最少——中国家庭垃圾构成确实如此。4.2 四色进度条的实现Row({ space: 8 }) { Text(♻️ 可回收).fontSize(11).fontColor(C.textDim).width(60) Progress({ value: 30, total: 100 }).color(#3B82F6).backgroundColor(C.cardSoft).layoutWeight(1).height(6) Text(30%).fontSize(11).fontColor(C.textSub) }每行三要素左侧emoji 分类名固定 60vp 宽四行对齐、中间Progress.color(#3B82F6)每类颜色写死、右侧百分比数字。与 App 14 的差异App 14 是一组同色进度条App 15 是四色进度条——颜色与分类一一对应蓝/绿/红/灰延续首页的四色编码系统。四色占比图本质是堆叠条形图的横排版——用 4 条独立进度条表达各部分占总体的比例比一个环形图实现简单得多不用画弧形视觉上也清晰。真实项目可升级为环形占比图ProgressType.CircularProgress({ value: 48, total: 100, type: ProgressType.Circular }) .color(#22C55E).width(80).height(80)但 4 个环形图太占空间4 条横排进度条是构成占比的最佳空间方案一个卡片展示 4 类。每行的百分比 进度条双通道30% 数字 蓝色进度条色弱用户能读数字。五、RecordTimeline三态操作时间线RecordTimeline 是 6 条分类记录的时间线每条记录按状态显示不同操作Builder RecordTimeline() { Column({ space: 0 }) { ForEach(this.filtered(), (r: Record, idx: number) { Column({ space: 0 }) { if (idx 0) { Row().width(2).height(12).backgroundColor(C.stroke).margin({ left: 18 }) } Row({ space: 12 }) { Column() { Row() { Text(r.emoji).fontSize(18) } .width(36).height(36) .backgroundColor(r.catColor 1A).borderRadius(18) .justifyContent(FlexAlign.Center) } .width(36) Column({ space: 8 }) { Row({ space: 8 }) { Text(r.item).fontSize(14).fontWeight(FontWeight.Medium).fontColor(C.text) Text(r.amount).fontSize(11).fontColor(C.textDim) Blank() Text(r.statusText) .fontSize(11).fontColor(r.statusColor) .padding({ left: 8, right: 8, top: 3, bottom: 3 }) .backgroundColor(C.primarySoft).borderRadius(8) } .width(100%) Row({ space: 6 }) { Text(r.category) .fontSize(11).fontColor(r.catColor) .padding({ left: 6, right: 6, top: 2, bottom: 2 }) .backgroundColor(r.catColor 1A).borderRadius(4) Text(r.date r.time).fontSize(12).fontColor(C.textDim) } if (r.status 2) { Row({ space: 8 }) { Button(立即分类) .fontSize(12).fontColor(#FFFFFF).backgroundColor(C.primary) .borderRadius(D.rSm).height(30) .onClick(() { promptAction.showToast({ message: 处理 r.item }); }) Text(待处理).fontSize(11).fontColor(C.warn) } .width(100%) } if (r.status 3) { Row({ space: 8 }) { Button(重新分类) .fontSize(12).fontColor(#FFFFFF).backgroundColor(C.danger) .borderRadius(D.rSm).height(30) .onClick(() { promptAction.showToast({ message: 重新分类 r.item }); }) Text(分类有误).fontSize(11).fontColor(C.danger) } .width(100%) } if (r.status 1) { Text(✓ 已正确分类).fontSize(11).fontColor(C.ok) } } .alignItems(HorizontalAlign.Start).layoutWeight(1) } .width(100%) .padding({ left: 14, right: 14, top: 14, bottom: 14 }) .backgroundColor(C.card).borderRadius(D.rMd) .border({ width: 1, color: C.stroke }) } .width(100%) }, (r: Record) r.id.toString()) } .width(100%) }5.1 数据模型分类色 状态色双通道interface Record { id: number; emoji: string; item: string; category: string; catColor: string; date: string; time: string; status: number; statusText: string; statusColor: ResourceColor; amount: string; }Record 同时携带catColor分类色和statusColor状态色——两类颜色语义分类色catColor垃圾属于哪类蓝/红/绿/灰→ 图标块背景 分类标签状态色statusColor记录处理状态绿已分类/橙待处理/红错误→ 状态标签分类和状态是两个维度用两套颜色表达互不干扰——**多维度信息用多套颜色编码**是数据可视化的关键。5.2 双标签设计Text(r.category) .fontSize(11).fontColor(r.catColor) .padding({ left: 6, right: 6, top: 2, bottom: 2 }) .backgroundColor(r.catColor 1A).borderRadius(4) Text(r.date r.time).fontSize(12).fontColor(C.textDim)一行两个标签左侧分类标签catColor文字 catColor 1A同色浅底如蓝字淡蓝底可回收物 右侧日期时间。分类标签让用户不用点进详情就知道这是什么类型的垃圾。5.3 三态操作区if (r.status 2) { Row({ space: 8 }) { Button(立即分类) .fontSize(12).fontColor(#FFFFFF).backgroundColor(C.primary) .borderRadius(D.rSm).height(30) .onClick(() { promptAction.showToast({ message: 处理 r.item }); }) Text(待处理).fontSize(11).fontColor(C.warn) } .width(100%) } if (r.status 3) { Row({ space: 8 }) { Button(重新分类) .fontSize(12).fontColor(#FFFFFF).backgroundColor(C.danger) .borderRadius(D.rSm).height(30) .onClick(() { promptAction.showToast({ message: 重新分类 r.item }); }) Text(分类有误).fontSize(11).fontColor(C.danger) } .width(100%) } if (r.status 1) { Text(✓ 已正确分类).fontSize(11).fontColor(C.ok) }3 个状态分支3 种操作状态按钮颜色右侧文字待处理status2立即分类绿C.primary待处理 橙错误分类status3重新分类红C.danger分类有误 红已分类status1无按钮—✓ 已正确分类 绿关键差异——错误分类的按钮是红色Button(重新分类) .fontSize(12).fontColor(#FFFFFF).backgroundColor(C.danger)App 14 预约页的所有操作按钮都是主题绿C.primaryApp 15 的重新分类用了危险红——错误用红色强化警示用户看到红按钮知道这条有问题要处理。**操作按钮颜色跟随状态严重性**是状态驱动 UI的进阶——正常操作绿、错误修复红。✓ 已正确分类是完成态标识绿字勾不需要操作按钮——无需操作的状态只显示确认信息。5.4 数据与筛选filtered()与 App 14 同款activeTab 0返回全部否则filter(status activeTab)——真筛选。6 条记录已分类 4 条废电池/旧报纸/香蕉皮/大骨头 待处理 1 条塑料瓶 错误分类 1 条灯泡——三态都有数据切换 Tab 能看到不同列表。6 条记录按日期倒序08-14 → 08-09时间线呈现最近 → 最远顺序。六、与 App 14 预约记录页的对比维度App 14 预约记录App 15 分类记录Tab待确认/已完成/已取消已分类/待处理/错误分类统计3 栏3 栏特色模块无四色占比进度条图标块主题绿同色分类色四色分类标签无有分类色标签状态按钮取消/再次预约绿立即分类绿/重新分类红App 15 的两个进步① 新增占比进度条构成分析② 引入分类色 状态色双色编码系统。记录列表模板在系列中不断进化——每次加一个新能力真筛选→时间线→占比→双色编码。七、四色编码系统在记录页的完整应用App 15 的四色编码系统蓝可回收/红有害/绿厨余/灰其他在本页的 4 处应用占比进度条4 条进度条各用各的颜色时间线图标块r.catColor 1A同色浅底废电池红色浅底、旧报纸蓝色浅底……分类标签catColor文字 同色浅底与首页联动首页入口/指南卡也是四色一个颜色系统贯穿全 App——用户在任何页面看到蓝色♻️就知道是可回收物。跨页颜色一致性是品牌识别度的最高形式。实现catColor字段存数据里#EF4444红渲染时r.catColor 1A拼浅底。颜色进数据让记录页零硬编码。八、扩展建议占比图联动筛选点击厨余 48%进度条 → 自动切换到厨余筛选真实项目可实现环形占比图新增占比总览卡片用ProgressType.Circular环形图展示总量构成分页加载328 条记录应分页.onReachEnd()上滑加载详情页立即分类/重新分类应跳转识别页并预填物品名跨 Tab 联动删除操作记录应支持左滑删除SwipeAction组件记录 占比 操作模板可复用到垃圾分类、记账分类、消费构成、时间统计——任何按类别记录 构成分析 状态操作的场景。九、分类占比的业务价值分类占比模块不只是好看它承载 3 层业务价值1. 反馈层——我的分类构成。用户看到厨余 48%会想我厨余垃圾最多下次多注意可回收。占比图让用户建立我每天都在分类什么的自我认知——这是环保教育的第一步知道自己分类的对象。2. 统计层——社区/城市的分类结构。真实项目里占比数据可以聚合为全校/全小区分类构成厨余 48% 说明该区域餐饮垃圾多辅助环保部门调整垃圾分类设施多放厨余桶还是可回收桶。个人占比 → 群体占比是数据产品的增值路径。3. 激励层——行为引导。如果可回收 30%偏低App 可提示回收利用率低于全国平均试试把纸箱压扁再投递——占比 建议驱动行为改变比单纯记录高级得多。实现注意当前占比是硬编码30/48/12/10真实项目应从分类记录实时聚合records.filter(r r.category 可回收物).length / records.length * 100——占比跟着记录走新增一条记录占比自动更新。**展示数据永远从业务数据推导**是数据架构的铁律。十、时间线的分类色 状态色双通道无障碍本页每一条记录同时携带两个颜色维度分类色 catColor 状态色 statusColor这对色弱用户特别重要分类信息图标块背景色红浅底/蓝浅底… 分类标签文字红字/蓝字…——即使分不清红蓝也能读有害垃圾可回收物文字状态信息状态标签文字待处理橙/分类错误红/已分类绿 按钮文案立即分类重新分类——颜色只是辅助文字才是主通道颜色 文字双通道是本系列反复强调的无障碍原则本页是执行最彻底的分类、状态、数量、时间全部有文字颜色只是锦上添花的强化。色弱用户约 8% 人口不靠颜色也能完整使用本页。对比反例如果只靠图标块颜色深浅区分分类不写可回收物文字色弱用户就完全无法使用。先文字后颜色是数据展示的底线。十一、状态机的待处理 → 已分类 → 错误分类流转本页 3 个状态背后的业务状态机新记录 → 待处理 → 已分类✓ 正确 ↘ 错误分类 → 重新分类 → 已分类待处理status2AI 识别后待人工确认 → 立即分类按钮处理已分类status1人工确认完成 → 显示✓ 已正确分类错误分类status3AI 识别错误 → 重新分类红色按钮纠错待处理 → 立即分类 → 已分类和错误分类 → 重新分类 → 已分类两条路径都通向终态已分类——状态机有汇合convergence是真实业务的常见形态AI 先识别、人工后确认。UI 的操作按钮就是状态机的事件立即分类处理事件、重新分类纠错事件。真实项目应做状态流转校验待处理不能直接变错误分类、错误分类不能变待处理——UI 按钮只是入口状态机逻辑才是真相。十二、小结App 15 分类记录页解析完毕。四色占比进度条构成分析 分类色/状态色双编码 三态操作绿处理/红纠错/绿确认 状态机流转是四大亮点。

相关新闻

2026/9/4 22:09:03

皮肤病变检测数据集 | 2500张YOLO皮肤科数据集

皮肤病变检测数据集 | 2500张YOLO皮肤科数据集 适用于皮肤病变辅助诊断、皮肤癌早期筛查与目标检测研究 一、数据集概述 本数据集基于皮肤镜图像整理为YOLO目标检测格式,以边界框标注病变区域,共包含约2500张高质量标注图像,专为皮肤镜图像…

2026/9/4 22:09:03

大模型测试开发工作流:Claude Code、Skill与pytest实战

最近不少测试同学开始有了新焦虑:接口自动化刚跑稳,行业里已经开始聊大模型测试开发、AI Agent、智能体;性能测试刚学会用 JMeter 写线程组,网上又冒出“让 AI 写性能脚本、自动分析报告”的玩法;车载测试、嵌入式测试…

2026/9/4 22:09:03

超越 cubic-bezier:用 linear() 自定义缓动函数实现弹跳效果

超越 cubic-bezier:用 linear() 自定义缓动函数实现弹跳效果在 CSS 动效开发的历史中,cubic-bezier(x1, y1, x2, y2) 一直是统治级的缓动工具。然而,任何一个对物理手感有严苛追求的前端工程师,迟早都会撞上贝塞尔曲线那道无法逾越…

2026/9/4 23:14:13

卡尔曼滤波硬件化:从算法到FPGA的Verilog实现

简介:本资源是一套面向数字电路设计与嵌入式信号处理领域的卡尔曼滤波器Verilog硬件实现方案,适用于FPGA开发工程师、控制算法硬件化实践者及高年级本科生/研究生。资源完整呈现了线性卡尔曼滤波核心逻辑的RTL级设计,涵盖状态预测、测量更新、…

2026/9/4 23:14:13

微信聊天记录导出成HTML、Word、CSV:WeChatMsg 三步搞定

微信聊天记录导出成HTML、Word、CSV:WeChatMsg 三步搞定 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeC…

2026/9/4 23:14:13

集成光隔离器如何保障多激光器宽带稳定运行

集成光隔离器这几年的进展速度,明显比传统工艺时代的预期要快。以前大家觉得隔离器只能做成分立器件,激光器与隔离器之间靠光纤跳线或者微光学元件连接,光谱范围往往固定在某个通信窗口上。最近在宽带、多激光器同时工作这个方向上&#xff0…

2026/9/4 23:14:13

Taichi 完整入门指南:让 Python 免费用上 GPU 并行算力

Taichi 完整入门指南:让 Python 免费用上 GPU 并行算力 【免费下载链接】taichi Productive, portable, and performant GPU programming in Python. 项目地址: https://gitcode.com/GitHub_Trending/ta/taichi Taichi 是一款嵌入 Python 的开源并行编程语言…

2026/9/4 23:14:13

基于STM32的太阳能MPPT控制器设计:从升降压拓扑到算法实现

简介:本资源是一套基于STM32的太阳能MPPT控制器完整工程实现,面向嵌入式开发工程师、新能源方向本科生及毕业设计实践者,解决光伏系统中最大功率点动态追踪与智能电池充电管理的核心问题。项目采用升降压(Buck-Boost)拓…

2026/9/3 18:28:26

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/9/3 14:29:47

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/9/3 14:30:35

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/9/4 0:00:58

STM32H743 SPI从机DMA双缓冲通信实战

简介:本资源是面向嵌入式开发工程师与STM32进阶学习者的SPI DMA双机通信从机端完整实现方案,聚焦STM32H743高性能Cortex-M7单片机在工业控制与高速数据交互场景下的从机通信开发痛点。压缩包含1355个文件,主体为599个C源码与321个头文件&…

2026/9/4 0:00:58

CPU开盖降温教程:20元成本让温度直降30度的原理与实践

最近很多朋友都在抱怨,自己的电脑一到夏天就变成"烤箱",玩游戏时CPU温度动不动就飙到90度以上,风扇噪音堪比直升机。更让人头疼的是,明明配置不错,却因为高温降频导致性能大打折扣。如果你也遇到了类似问题&…

2026/9/4 0:00:58

ArkTS 表单工程:场地预约页的三态场次 Grid 与校验

ArkTS 表单工程:场地预约页的三态场次 Grid 与校验 App 14「运动场地预约」场地 Tab(Func1Tab),是整 App 交互最丰富的页面——场地横向切换 三色图例 渐变预约预览卡 快捷模板 今日场次 Grid(可选/已选/已满三态&…

2026/9/3 20:43:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/3 17:51:43

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/3 21:06:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…