HarmonyOS 应用 · 班级任务首页深度解析:Progress 环形进度与 toggle 勾选刷新
项目编号:48-class-task 技术栈:HarmonyOS ArkTS · ArkUI 声明式 UI · Stage 模型 本篇页面:首页
HomeTab.ets(103 行) 系列导航:(一)首页· (二)任务 · (三)进度 · (四)我的
一、Theme.ets:紫色主题与任务管理产品的色彩语义
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 = '#6C5CE7'; static readonly primarySoft: string = '#ECE8FD'; static readonly accent: string = '#9B8AF5'; static readonly warn: string = '#FF9F1C'; static readonly danger: string = '#FF5A6E'; static readonly ok: string = '#2BB673'; }班级任务的主色是#6C5CE7(深紫),与班费管理的#00A862(翡翠绿)、通讯录的#0984E3(亮蓝)形成区分。紫色传递"任务/协作/管理"的色彩语义——任务管理是协调型应用,紫色比绿色更中性、比蓝色更有调度感。primarySoft(#ECE8FD)是浅紫底色,做头像背景。
二、Index.ets:Tabs 容器与四 Tab 布局
Tabs({ barPosition: BarPosition.End, index: this.current }) { TabContent() { HomeTab() }.tabBar(this.bar('首页', '📋', 0)) TabContent() { Func1Tab() }.tabBar(this.bar('任务', '✏️', 1)) TabContent() { Func2Tab() }.tabBar(this.bar('进度', '📊', 2)) TabContent() { ProfileTab() }.tabBar(this.bar('我的', '👤', 3)) } .barBackgroundColor('#FFFFFF') .barHeight(60 + this.safeBottom) .scrollable(false) .onChange((idx: number) => { this.current = idx; }) .width('100%').height('100%').backgroundColor(C.bg)四个 Tab:首页(📋)/任务(✏️)/进度(📊)/我的(👤)。任务管理的四个环节:查看今日任务 → 创建新任务 → 查看成员进度 → 个人统计。
三、Task interface 与 @State tasks 数组
interface Task { id: number; emoji: string; title: string; owner: string; deadline: string; done: boolean; }六个字段:id是 key 锚点,emoji是任务图标,title是任务标题,owner是负责人,deadline是截止时间,done是"是否完成"的布尔位。done是首页的核心状态字段——驱动勾选符号、标题颜色、删除线三态变化。
@State tasks: Task[] = [ { id: 1, emoji: '📋', title: '收齐班费并登记', owner: '生活委员', deadline: '今天', done: false }, { id: 2, emoji: '📢', title: '发布运动会通知', owner: '宣传委员', deadline: '今天', done: true }, { id: 3, emoji: '📝', title: '统计社会实践报名', owner: '学习委员', deadline: '明天', done: false }, { id: 4, emoji: '🎉', title: '筹备班级团建', owner: '文娱委员', deadline: '本周', done: false } ];@State tasks是@State修饰的数组——与普通private不同,@State让数组引用变化时触发 UI 刷新。四条任务:1 项已完成(发布运动会通知)+ 3 项待完成。
四、doneCount 与 toggle:不可变更新模式
private doneCount(): number { let n = 0; this.tasks.forEach((t: Task) => { if (t.done) { n++; } }); return n; } private toggle(item: Task): void { item.done = !item.done; this.tasks = this.tasks.slice(); }doneCount()遍历tasks统计已完成数——每次调用都重新计算,保证进度始终最新。
toggle(item)是首页的核心交互方法——两步不可变更新:
// 1. 翻转 done 布尔位 item.done = !item.done; // 2. slice() 生成新数组引用,触发 @State 刷新 this.tasks = this.tasks.slice();slice()无参调用返回数组浅拷贝——新引用触发@State重新渲染,ProgressCard 的环形进度和 TaskList 的勾选态同步刷新。这是 ArkUI 中数组状态更新的标准范式。
五、ProgressCard:Progress 环形组件 + 渐变背景
@Builder ProgressCard() { Row({ space: 16 }) { Stack({ alignContent: Alignment.Center }) { Progress({ value: this.doneCount(), total: this.tasks.length, type: ProgressType.Ring }) .width(64).height(64).color('#FFFFFF').style({ strokeWidth: 6 }).backgroundColor('#44FFFFFF') Text(this.doneCount() + '/' + this.tasks.length).fontSize(14).fontWeight(FontWeight.Bold).fontColor('#FFFFFF') } Column({ space: 4 }) { Text('今日任务进度').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#FFFFFF') Text('还有 ' + (this.tasks.length - this.doneCount()) + ' 项待完成').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]] }) }Progress组件——系列首次出现的环形进度:
Progress({ value: this.doneCount(), total: this.tasks.length, type: ProgressType.Ring }) .width(64).height(64).color('#FFFFFF').style({ strokeWidth: 6 }).backgroundColor('#44FFFFFF')ProgressType.Ring环形进度条,value是当前值(doneCount),total是总数(tasks.length)。color('#FFFFFF')白色进度环 +backgroundColor('#44FFFFFF')半透明底环——在紫色渐变背景上白环可见。style({ strokeWidth: 6 })环宽 6px。
Stack 叠加:环形 Progress + 中心文字"1/4"——Alignment.Center让文字居中在环内。右侧"今日任务进度" + "还有 3 项待完成",this.tasks.length - this.doneCount()动态计算待完成数。
六、TaskList:done 驱动的勾选 + 删除线双态
@Builder TaskList() { Column({ space: 10 }) { ForEach(this.tasks, (t: Task) => { Row({ space: 12 }) { Text(t.done ? '✅' : '⬜').fontSize(22).onClick(() => { this.toggle(t); }) Column({ space: 4 }) { Text(t.title).fontSize(14).fontColor(t.done ? C.textDim : C.text) .decoration({ type: t.done ? TextDecorationType.LineThrough : TextDecorationType.None }) Text('负责人: ' + t.owner + ' · ' + t.deadline).fontSize(12).fontColor(C.textDim) }.alignItems(HorizontalAlign.Start).layoutWeight(1) Text(t.emoji).fontSize(20) } .width('100%').padding(14).backgroundColor(C.card).borderRadius(D.rMd).border({ width: 1, color: C.stroke }) }, (t: Task) => t.id.toString()) }.width('100%') }done驱动三元变化——勾选符号、标题颜色、删除线三路分支:
// 勾选符号:✅ vs ⬜ Text(t.done ? '✅' : '⬜') // 标题颜色:灰色 vs 深色 .fontColor(t.done ? C.textDim : C.text) // 删除线:有 vs 无 .decoration({ type: t.done ? TextDecorationType.LineThrough : TextDecorationType.None })done === true时 ✅ + 灰色标题 + 删除线(已完成视觉弱化),done === false时 ⬜ + 深色标题 + 无删除线(待完成视觉突出)。TextDecorationType.LineThrough是 ArkUI 的删除线装饰——已完成任务的经典视觉表达。
勾选符号onClick调this.toggle(t)——点击翻转done+slice()触发刷新,ProgressCard 环形进度和 TaskList 勾选态同步更新。
七、可演进方向
| 方向 | 现状 | 改法 | 收益 |
|---|---|---|---|
| 任务创建 | 静态 4 条 | 接入任务 Tab 创建后追加 | 任务动态新增 |
| 数据持久 | @State 内存 | Preferences 持久化 | 重启不丢失 |
| 过期检测 | 无 | 比对 deadline 与当前日期 | 过期任务标红 |
| 拖拽排序 | 无 | ItemTouchHelper 拖拽 | 任务优先级手动调整 |
| 任务详情 | 无 onClick | 点击进入详情页 | 展示完整描述 |
首页是班级任务的概览——ProgressCard 的环形进度 + TaskList 的done驱动勾选双态。从toggle的不可变更新到TextDecorationType.LineThrough的删除线装饰,每一层都有明确的职责边界。
系列导航:(一)首页· (二)任务 · (三)进度 · (四)我的