
#积分挑战#鸿蒙开发案例分享:任务增加小案例
鸿蒙开发案例分享:任务增加小案例
效果
一、代码
先给出所有代码:
// 任务类
class Task {
//静态变量是所有对象共享的变量,是单例模式
static id: number = 1
// 任务名称
name: string = `任务${Task.id++}`
//任务状态:是否完成
finished: boolean = false
}
// 统一的卡片样式(用在row组件)
@Styles
function card() {
.width('95%')
.padding(20)
.backgroundColor(Color.White)
.borderRadius(15)
.shadow({
radius: 6,
color: '#1F000000',
offsetX: 2,
offsetY: 4
})
}
// 任务完成的文本样式
@Extend(Text)
function finishedTask() {
.decoration({ type: TextDecorationType.LineThrough })
.fontColor('#B1B2B1')
}
@Entry
@Component
struct PropPage {
// 总任务数量
@Provide totalTask: number = 0
// 已完成任务数量
@Provide finishedTask: number = 0;
// 任务数组
@Provide tasks: Task[] = []
build() {
Column({ space: 10 }) {
// 1.任务卡片
TaskStatistics()
// 2.任务列表
TaskList()
.layoutWeight(1)
}
.width('100%')
.height('100%')
.backgroundColor('#F1F2F3')
}
}
// 任务列表
@Component
struct TaskList {
// 总任务数量
@Consume totalTask: number
// 已完成任务数量
@Consume finishedTask: number
// 任务数组
@Consume tasks: Task[]
handleTaskChange() {
// 更新任务总数量
this.totalTask = this.tasks.length
// 更新已完成的任务数量
this.finishedTask = this.tasks.filter(item => item.finished).length
}
build() {
Column({space: 10}) {
Button('新增任务')
.width(200)
.onClick(() => {
// 新增任务数据
this.tasks.push(new Task())
this.handleTaskChange()
})
// 3.任务列表
List({ space: 10 }) {
ForEach(
this.tasks,
(item: Task, index: number) => {
ListItem() {
Row() {
Text(item.name)
.fontSize(20)
Checkbox()
.onChange(value => {
// 更新当前任务状态
item.finished = value
this.handleTaskChange()
})
}
.card()
.justifyContent(FlexAlign.SpaceBetween)
}
.swipeAction({ end: this.DeleteButton(index) })
}
)
}
.width('100%')
// 设置list中的元素左右居中
.alignListItem(ListItemAlign.Center)
.layoutWeight(1)
}
}
@Builder
DeleteButton(index: number) {
Button() {
Image($r('app.media.ic_public_delete_filled'))
.fillColor(Color.White)
.width(20)
}
.width(40)
.height(40)
.backgroundColor(Color.Red)
.margin(5)
.onClick(() => {
// 删除任务数组中对应下标的数据
this.tasks.splice(index, 1)
this.handleTaskChange()
})
}
}
// 任务统计组件
@Component
struct TaskStatistics {
// 总任务数量
@Consume totalTask: number
// 已完成任务数量
@Consume finishedTask: number
build() {
Row() {
Text('任务进度:')
.fontSize(30)
.fontWeight(FontWeight.Bold)
// 堆叠容器,可以覆盖,组件按照顺序依次入栈,后一个子组件覆盖前一个子组件
Stack() {
//进度条
Progress({
value: this.finishedTask, //当前进度数
total: this.totalTask, // 总数
type: ProgressType.Ring // 进度条类型
})
.width(100)
Row() {
Text(this.finishedTask.toString())
.fontSize(24)
.fontColor('#36D')
Text(' / ' + this.totalTask.toString())
.fontSize(24)
}
}
}
.card()
.margin({ top: 20, bottom: 10 })
.justifyContent(FlexAlign.SpaceEvenly)
}
}
接下来我将一步一步分析代码。
二、分析代码
2.1 类 Task
我们要定义一个类用来存放每一个任务的具体信息,将任务抽象出来,方便将数据用于展示。
class Task {
static id: number = 1 // 静态变量,用于生成任务的唯一标识
name: string = `任务${Task.id++}` // 每个任务的名称,默认以任务序号命名
finished: boolean = false // 标识任务是否完成
}
每个变量具体解释如下:
1、静态变量 id:共享的变量,所有任务对象共用,用于生成唯一的任务名称。
2、属性 name:任务的名称,默认格式为 "任务X"。
3、属性 finished:任务状态,标识任务是否完成,默认为 false。
2.2 样式声明
因为每个卡片样式是统一的,所以我们将卡片的样式统计定义。
// 统一的卡片样式(用在row组件)
@Styles
function card() {
.width('95%')
.padding(20)
.backgroundColor(Color.White)
.borderRadius(15)
.shadow({
radius: 6,
color: '#1F000000',
offsetX: 2,
offsetY: 4
})
}
2.3 页面入口组件 PropPage
每一个页面都有一个入口文件,用@Entry和@Component装饰器来装饰,负责整体布局的组织和逻辑的控制。
@Entry
@Component
struct PropPage {
// 总任务数量
@Provide totalTask: number = 0
// 已完成任务数量
@Provide finishedTask: number = 0;
// 任务数组
@Provide tasks: Task[] = []
build() {
Column({ space: 10 }) {
// 1.任务卡片
TaskStatistics()
// 2.任务列表
TaskList()
.layoutWeight(1)
}
.width('100%')
.height('100%')
.backgroundColor('#F1F2F3')
}
}
1、属性:@Provide 修饰符:允许子组件访问共享的状态,包括任务总数、完成的任务数、任务数组。
2、UI 结构:
(1)使用 Column 容器将页面分为两部分:
(2)任务统计(TaskStatistics 组件)。
(3)任务列表(TaskList 组件,占用大部分页面空间)。
2.4 任务列表组件 TaskList
因为每个任务的结构和样式是一模一样的,所以我们直接将任务列表封装成一个组件,通过父组件传递任务数组,通过ForEach函数来遍历任务列表,将所有任务动态生成。
// 任务列表
@Component
struct TaskList {
// 总任务数量
@Consume totalTask: number
// 已完成任务数量
@Consume finishedTask: number
// 任务数组
@Consume tasks: Task[]
handleTaskChange() {
// 更新任务总数量
this.totalTask = this.tasks.length
// 更新已完成的任务数量
this.finishedTask = this.tasks.filter(item => item.finished).length
}
build() {
Column({space: 10}) {
Button('新增任务')
.width(200)
.onClick(() => {
// 新增任务数据
this.tasks.push(new Task())
this.handleTaskChange()
})
// 3.任务列表
List({ space: 10 }) {
ForEach(
this.tasks,
(item: Task, index: number) => {
ListItem() {
Row() {
Text(item.name)
.fontSize(20)
Checkbox()
.onChange(value => {
// 更新当前任务状态
item.finished = value
this.handleTaskChange()
})
}
.card()
.justifyContent(FlexAlign.SpaceBetween)
}
.swipeAction({ end: this.DeleteButton(index) })
}
)
}
.width('100%')
// 设置list中的元素左右居中
.alignListItem(ListItemAlign.Center)
.layoutWeight(1)
}
}
@Builder
DeleteButton(index: number) {
Button() {
Image($r('app.media.ic_public_delete_filled'))
.fillColor(Color.White)
.width(20)
}
.width(40)
.height(40)
.backgroundColor(Color.Red)
.margin(5)
.onClick(() => {
// 删除任务数组中对应下标的数据
this.tasks.splice(index, 1)
this.handleTaskChange()
})
}
}
1、@Consume 修饰符:
允许组件从父组件接收共享的数据,包括 totalTask、finishedTask、tasks。
2、功能:
(1)新增任务:
Button('新增任务')
.onClick(() => { ... })
每次点击新增任务按钮时,创建一个新的 Task 对象并添加到任务数组。
调用 handleTaskChange 更新任务统计信息。
(2)显示任务列表:
// 3.任务列表
List({ space: 10 }) {
ForEach(
this.tasks,
(item: Task, index: number) => {
ListItem() {
Row() {
Text(item.name)
.fontSize(20)
Checkbox()
.onChange(value => {
// 更新当前任务状态
item.finished = value
this.handleTaskChange()
})
}
.card()
.justifyContent(FlexAlign.SpaceBetween)
}
.swipeAction({ end: this.DeleteButton(index) })
}
)
}
.width('100%')
// 设置list中的元素左右居中
.alignListItem(ListItemAlign.Center)
.layoutWeight(1)
遍历任务数组,用 ForEach 动态渲染每个任务项。
每个任务项是一个 ListItem,包含任务名称和状态切换按钮(Checkbox)。
(3)任务状态更新:
Checkbox()
.onChange(value => {
// 更新当前任务状态
item.finished = value
this.handleTaskChange()
})
}
.card()
.justifyContent(FlexAlign.SpaceBetween)
监听 Checkbox 状态切换,更新对应任务的 finished 属性。
更新统计信息。
(4)删除任务:
@Builder
DeleteButton(index: number) {
Button() {
Image($r('app.media.ic_public_delete_filled'))
.fillColor(Color.White)
.width(20)
}
.width(40)
.height(40)
.backgroundColor(Color.Red)
.margin(5)
.onClick(() => {
// 删除任务数组中对应下标的数据
this.tasks.splice(index, 1)
this.handleTaskChange()
})
}
使用滑动操作附加删除按钮,点击后根据任务索引移除任务。
调用 handleTaskChange 更新统计信息。
2.5 任务统计组件 TaskStatistics
// 任务统计组件
@Component
struct TaskStatistics {
// 总任务数量
@Consume totalTask: number
// 已完成任务数量
@Consume finishedTask: number
build() {
Row() {
Text('任务进度:')
.fontSize(30)
.fontWeight(FontWeight.Bold)
// 堆叠容器,可以覆盖,组件按照顺序依次入栈,后一个子组件覆盖前一个子组件
Stack() {
//进度条
Progress({
value: this.finishedTask, //当前进度数
total: this.totalTask, // 总数
type: ProgressType.Ring // 进度条类型
})
.width(100)
Row() {
Text(this.finishedTask.toString())
.fontSize(24)
.fontColor('#36D')
Text(' / ' + this.totalTask.toString())
.fontSize(24)
}
}
}
.card()
.margin({ top: 20, bottom: 10 })
.justifyContent(FlexAlign.SpaceEvenly)
}
}
1、@Consume 修饰符:接收任务总数(totalTask)和已完成任务数(finishedTask)。
2、UI:
(1)使用 Row 布局:显示任务进度和任务统计信息。
(2)进度条:
Progress({
value: this.finishedTask,
total: this.totalTask,
type: ProgressType.Ring
})
显示任务完成进度,类型为环形(Ring)。
(3)统计文本:
任务完成数 finishedTask 和总任务数 totalTask 动态显示。
三、功能点解析
-
任务新增
点击 新增任务 按钮,新增一个任务到任务数组中,动态更新页面。 -
任务完成状态切换
通过 Checkbox 切换任务完成状态,同时更新统计数据。 -
任务删除
滑动任务项出现删除按钮,点击后移除任务并更新统计数据。 -
任务统计
TaskStatistics 显示任务总数和完成任务数,并通过环形进度条直观显示完成比例。
更多推荐
所有评论(0)