即时做APP开发实战(十七)-待办置顶与颜色标记
本文将介绍如何实现待办列表的置顶显示和颜色标记功能,提升用户体验。
一、功能需求
1.1 需求分析
【图1:待办列表置顶显示】

┌─────────────────────────────────────┐
│ 及时做 │
├─────────────────────────────────────┤
│ ┌─────────────────────────────┐ │
│ │ 进行中 已完成 全部 │ │
│ └─────────────────────────────┘ │
│ │
│ ┌─────────────────────────────┐ │
│ │🔴 学习ArkTS基础 │ │ ← 未完成(红色标记)
│ │ 2024-01-15 │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │?开发即时做APPPP │ │ ← 未完成(红色标记)
│ │ 2024-01-15 🍅 × 2 │ │
│ └─────────────────────────────┘ │
│ ┌─────────────────────────────┐ │
│ │🟢 写博客文档 │ │ ← 已完成(绿色标记)
│ │ 2024-01-14 │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
1.2 功能点
| 功能 | 说明 |
|——|——未完成置顶显示完成置顶 | 未完成的待办排在列表最前面 |
| 颜色标记 | 左侧显示状态颜色条 |
| 排序规则 | 同状态按创建时间倒序 |
二、排序算法
2.1 排序规则
【图2:颜色标记效果】

排序规则:
┌─────────────────────────────────────┐
│ 1. 未完成的待办排在前面 │
│ 2. 已完成的待办排在后面 │
│ 3. 同状态按创建时间倒序 │
└─────────────────────────────────────┘
示例:
┌─────────────────────────────────────┐
│ 原始顺序: │
│ ✓ 写博客(已完成,01-14) │
│ ☐ 学习ArkTS(未完成,01-15) │
│ ☐ 开发APP(未完成,01-15) │
│ ✓ 代码优化(已完成,01-13) │
│ │
│ 排序后: │
│ ☐ 开发APP(未完成,01← 置顶显示← 置顶 │
│ ☐ 学习ArkTS(未完成,01-15) │
│ ✓ 写博客(已完成,01-14) │
│ ✓ 代码优化(已完成,01-13) │
└─────────────────────────────────────┘
2.2 实现代码
getFilteredList(): TodoItem[] {
let filteredList: TodoItem[];
// 根据Tab过滤
if (this.activeTab === 0) {
filteredList = […this.todoList];
} else if (this.activeTab === 1) {
filteredList = this.todoList.filter(item => !item.completed);
} else {
filteredList = this.todoList.filter(item => item.completed);
} // 未完成项置顶显示(按创建时间倒序)间倒序)
return filteredList.sort((a, b) => {
if (a.completed !== b.completed) {
return a.completed ? 1 : -1; // 未完成的排前面
}
return b.createdAt – a.createdAt; // 同状态按创建时间倒序
});
}
2.3 排序逻辑详解
┌─────────────────────────────────────┐
│ 排序逻辑 │
├─────────────────────────────────────┤
│ sort((a, b) => { │
│ // 1. 先比较完成状态 │
│ if (a.completed !== b.completed) │
│ return a.completed ? 1 : -1; │
│ // a已完成 → 返回1(a排后面) │
│ // a未完成 → 返回-1(a排前面) │
│ } │
│ │
│ // 2. 同状态比较创建时间 │
│ return b.createdAt – a.createdAt // 时间戳大的排前(倒序) │ │
│ }) │
└─────────────────────────────────────┘
三、颜色标记实现
3.1 标记颜色设计
颜色方案:
┌─────────────────────────────────────┐
│ 未完成:#FF6B6B(红色) │
│ 已完成:#4CAF50(绿色) │
└─────────────────────────────────────┘
视觉效果:
┌─────────────────────────────┐
│▌ 学习ArkTS基础 │ ← 红色条
│▌ 2024-01-15 │
└─────────────────────────────┘
┌─────────────────────────────┐
│▌ 写博客文档 │ ← 绿色条
│▌ 2024-01-14 │
└─────────────────────────────┘
3.2 实现代码
@Builder
TodoItem(todo: TodoItem) {
Row() {
// 标记颜色条
Column()
.width(4)
.height('100%')
.backgroundColor(todo.completed ? '#4CAF50' : '#FF6B6B')
.borderRadius({ topLeft: 4, bottomLeft: 4 })
Column() {
Row() {
// 完成状态复选框
Checkbox()
.select(todo.completed)
.selectedColor('#4CAF50')
.width(24)
.height(24)
.margin({ right: 12 })
.onChange((isChecked: boolean) => {
this.toggleTodo(todo.id);
})
// 待办内容
Column() {
Text(todo.text)
.fontSize(16)
.fontColor(todo.completed ? '#999999' : '#333333')
.decoration({
type: todo.completed ?
TextDecorationType.LineThrough :
TextDecorationType.None
})
Row() {
Text(DateTimeUtil.formatDate(todo.createdAt))
.fontSize(12)
.fontColor('#999999')
if (todo.pomodoroCount > 0) {
Text(`🍅 × ${todo.pomodoroCount}`)
.fontSize(12)
.fontColor('#FF6B6B')
.margin({ left: 10 })
}
}
.margin({ top: 5 })
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
// 删除按钮
Button('删除')
.fontSize(12)
.height(28)
.backgroundColor('#FF4444')
.fontColor('#FFFFFF')
.borderRadius(14)
.onClick(() => {
this.deleteTodo(todo.id);
})
}
.width('100%')
}
.layoutWeight(1)
.padding({ left: 12, right: 15, top: 15, bottom: 15 })
}
.width('100%')
.backgroundColor('#FFFFFF')
.borderRadius(8)
.clip(true)
.shadow({ radius: 2, color: '#E0E0E0', offsetX: 0, offsetY: 2 })
}
3.3 关键属性
| width(4) | 标记条宽度 |
| height(‘100%’) | 标记条高度撑满 |
| backgroundColor | 根据状态设置颜色 |
| borderRadius | 左侧圆角 |
| clip(true) | 裁剪圆角 |
四、布局结构
4.1 组件结构
┌──────────────────────────────────│ Row(容器) │ │
├──────────────────────────────────│ ┌────┬───────────────────────┐ │┐│ │标记│ Column(内容) │ │││ │条 │ ┌─────────────────┐ │ │││ │ │ │ Row(主体) │ │ ││ │
│ │ │ │ ☐ 待办内容 删除 │ │ │
│ │ │ └──────────────────┘ │ │
│ └────┴────────────────────────┘ │
└─────────────────────────────────────┘
4.2 布```tscript
Row // 左侧标记区左侧标记条
Column()
.width(4)
.height(‘100%’)
.backgroundColor(…)
// 右侧内容区
Column() {
Row() {
Checkbox() // Column() { // 待办事项内容 待办内容
Text() / Row() // 日期与番茄钟数量和番茄钟数
}
Button() // 删除按钮
}
}
.layoutWeight(1)
.padding(…)
}
.borderRadiu.clip(true) // 裁剪超出圆角区域的内容 裁剪圆角
## 五、效果对比
### 5.1 修改前
┌─────────────────────────────────────┐
│ ☐ 学习ArkTS基础 │
│ 2024-01-15 │
├─────────────────────────────────────┤
│ ✓ 写博客文档 │
│ 2024-01-14 │
├─────────────────────────────────────┤
│ ☐ 开发APP │
│ 2024-01-15 │
├─────────────────────────────────────┤
│ ✓ 代码优化 │
│ 2024-01-13 │
└──────────────────────────────────❌ 已完成和未完成的任务混在一起
❌ 缺少视觉区分有视觉区分
### 5.2 修改后
┌─────────────────────────────────────┐
│▌ 开发APP 删除 │ ← 红色标记
│▌ 2024-01-15 │
├─────────────────────────────────────┤
│▌ 学习ArkTS基础 删除 │ ← 红色标记
│▌ 2024-01-15 │
├─────────────────────────────────────┤
│▌ 写博客文档 删除 │ ← 绿色标记
│▌ 2024-01-14 │
├─────────────────────────────────────┤
│▌ 代码优化 删除 │ ← 绿色标记
│▌ 2024-01-13 │
└──────────────────────────────────✅ 未完成的任务置顶显示成置顶显示
✅ 颜色标记清晰区分
## 六、最佳实践
### 6.1 排序原则
┌─────────────────────────────────────┐
│ 排序原则 │
├──────────────────────────────────│ □ 重要项置顶显示 │ │
│ □ 同类项按时间排序 │
│ □ 保持用户预期 │
│ □ 避免频繁变化 │
└─────────────────────────────────────┘
### 6.2 颜色设```
┌─────────────────────────────────────┐
│ 颜色设计原则 │
├─────────────────────────────────────┤
│ □ 含义明确 │
│ □ 对比度适中 │
│ □ 符合用户认知 │
│ □ 考虑色觉障碍用户 │
└─────────────────────────────────────┘
常用颜色含义:
– 红色:未完成、重要、警告
– 绿色:已完成、成功、安全
– 蓝色:信息、链接
– 黄色:提醒、注意
```意



