[HarmonyOS NEXT 实战案例十四] 任务管理看板网格布局(上)

简介: 本教程将详细讲解如何使用HarmonyOS NEXT的GridRow和GridCol组件实现一个任务管理看板的网格布局。任务管理看板是项目管理中常用的工具,通过网格布局可以清晰地展示任务信息,包括任务名称、状态、优先级和进度等。

项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star

效果演示

image.png

1. 概述

本教程将详细讲解如何使用HarmonyOS NEXT的GridRow和GridCol组件实现一个任务管理看板的网格布局。任务管理看板是项目管理中常用的工具,通过网格布局可以清晰地展示任务信息,包括任务名称、状态、优先级和进度等。

本教程将涵盖以下内容:

  • 任务数据结构设计
  • 整体布局实现
  • 标题和筛选功能
  • 表头设计
  • 任务列表实现
  • 状态和优先级的视觉区分

2. 数据结构设计

首先,我们需要定义任务的数据结构,包含任务的基本信息:

interface TaskType {
   
    title: string;    // 任务名称
    status: string;   // 任务状态
    priority: string; // 优先级
    category: string; // 分类
    progress: number; // 进度
}

这个接口定义了任务的五个基本属性:

  • title:任务名称,如"完成UI设计"、"编写API文档"等
  • status:任务状态,如"已完成"、"进行中"、"待开始"等
  • priority:优先级,如"高"、"中"、"低"等
  • category:分类,如"设计"、"开发"、"测试"等
  • progress:进度,表示任务完成的百分比,范围为0-100

3. 数据准备

接下来,我们准备一些示例任务数据用于展示:

private tasks: TaskType[] = [
    {
    title: '完成UI设计', status: '进行中', priority: '高', category: '设计', progress: 60 },
    {
    title: '编写API文档', status: '待开始', priority: '中', category: '开发', progress: 0 },
    {
    title: '测试登录功能', status: '已完成', priority: '低', category: '测试', progress: 100 },
    {
    title: '准备会议材料', status: '进行中', priority: '高', category: '管理', progress: 30 },
    {
    title: '代码审查', status: '待开始', priority: '中', category: '开发', progress: 0 },
    {
    title: '用户调研', status: '已完成', priority: '低', category: '设计', progress: 100 }
]

这里我们创建了一个包含六个任务的数组,每个任务都包含名称、状态、优先级、分类和进度。

4. 状态管理

为了实现任务筛选功能,我们需要定义一个状态变量来跟踪当前选择的筛选条件:

@State currentFilter: string = '全部'

这个状态变量将用于存储当前选择的任务分类,初始值为"全部",表示显示所有任务。

5. 整体布局结构

任务管理看板的整体布局采用Column容器,内部包含三个主要部分:

build() {
   
    Column() {
   
        // 标题和筛选
        Row() {
   
            // ...
        }
        .margin({
    bottom: 16 })
        .width('100%')

        // 表头
        GridRow({
    columns: 1 }) {
   
            // ...
        }

        // 任务列表
        Scroll() {
   
            GridRow({
    columns: 1 }) {
   
                // ...
            }
        }
        .height('70%')
        .margin({
    top: 8 })
    }
    .width('100%')
    .height('100%')
    .padding(16)
}

这种结构将看板界面分为三个垂直排列的部分:

  1. 顶部的标题和筛选区域
  2. 中间的表头区域
  3. 底部的任务列表区域(可滚动)

整个Column容器设置宽高为100%,内边距为16像素,使内容与屏幕边缘保持适当距离。

6. 标题和筛选功能实现

标题和筛选区域使用Row容器,左侧显示标题,右侧是分类筛选下拉框:

// 标题和筛选
Row() {
   
    Text('任务看板')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .layoutWeight(1)

    Select([
        {
    value: '全部', icon: $r('app.media.01') },
        {
    value: '设计', icon: $r('app.media.02') },
        {
    value: '开发', icon: $r('app.media.03') },
        {
    value: '测试', icon: $r('app.media.04') }
    ])
        .selected(0)
        .onSelect((index: number) => {
   
            this.currentFilter = ['全部', '设计', '开发', '测试'][index]
        })
        .width(120)
}
.margin({
    bottom: 16 })
.width('100%')

在这个部分:

  • 左侧Text显示"任务看板"标题,设置字体大小为20像素,粗体,并使用layoutWeight(1)使其占据剩余空间
  • 右侧Select组件作为分类筛选下拉框,包含四个选项:"全部"、"设计"、"开发"和"测试",每个选项都有对应的图标
  • 下拉框初始选中第一项("全部"),宽度为120像素
  • onSelect事件处理器在用户选择不同选项时更新currentFilter状态变量
  • 整个Row设置下边距为16像素,宽度为100%

7. 表头实现

表头区域使用单列的GridRow和GridCol,内部包含一个Row容器,显示各列的标题:

// 表头
GridRow({
    columns: 1 }) {
   
    GridCol({
    span: 1 }) {
   
        Row() {
   
            Text('任务名称')
                .fontSize(14)
                .fontWeight(FontWeight.Bold)
                .width('40%')

            Text('状态')
                .fontSize(14)
                .fontWeight(FontWeight.Bold)
                .width('15%')

            Text('优先级')
                .fontSize(14)
                .fontWeight(FontWeight.Bold)
                .width('15%')

            Text('进度')
                .fontSize(14)
                .fontWeight(FontWeight.Bold)
                .width('30%')
        }
        .padding(12)
        .backgroundColor('#F5F5F5')
        .borderRadius(8)
    }
}

在这个部分:

  • GridRow设置为单列布局(columns: 1),GridCol占据整个行宽(span: 1
  • 内部Row容器包含四个Text组件,分别显示"任务名称"、"状态"、"优先级"和"进度"列标题
  • 每个Text组件设置字体大小为14像素,粗体,并设置不同的宽度百分比,使各列按比例分配空间
  • 整个Row设置内边距为12像素,背景色为浅灰色(#F5F5F5),边框圆角为8像素

8. 任务列表实现

任务列表区域使用Scroll容器包裹单列的GridRow,通过ForEach循环遍历筛选后的任务数组:

// 任务列表
Scroll() {
   
    GridRow({
    columns: 1 }) {
   
        ForEach(this.tasks.filter(task =>
        this.currentFilter === '全部' || task.category === this.currentFilter
        ), (task: TaskType) => {
   
            GridCol({
    span: 1 }) {
   
                Row() {
   
                    Text(task.title)
                        .fontSize(14)
                        .width('40%')
                        .textAlign(TextAlign.Start)

                    Text(task.status)
                        .fontSize(14)
                        .fontColor(this.getStatusColor(task.status))
                        .width('15%')
                        .textAlign(TextAlign.Center)

                    Text(task.priority)
                        .fontSize(14)
                        .fontColor(this.getPriorityColor(task.priority))
                        .width('15%')
                        .textAlign(TextAlign.Center)

                    Progress({
    value: task.progress, total: 100, type: ProgressType.Linear })
                        .width('30%')
                        .height(8)
                        .color('#4CAF50')
                }
                .padding(12)
                .backgroundColor('#FFFFFF')
                .borderRadius(8)
                .margin({
    bottom: 8 })
            }
        })
    }
}
.height('70%')
.margin({
    top: 8 })

在这个部分:

  • Scroll容器使任务列表可滚动,设置高度为父容器的70%,顶部边距为8像素
  • 内部GridRow设置为单列布局(columns: 1
  • ForEach循环遍历经过筛选的任务数组,筛选条件是:当前筛选为"全部"或任务分类与当前筛选相匹配
  • 每个任务项使用GridCol包裹,占据整个行宽(span: 1
  • 每个任务项内部使用Row容器,包含四个组件,分别显示任务名称、状态、优先级和进度
  • 任务名称使用Text组件,宽度为40%,左对齐
  • 状态使用Text组件,宽度为15%,居中对齐,文本颜色根据状态动态设置
  • 优先级使用Text组件,宽度为15%,居中对齐,文本颜色根据优先级动态设置
  • 进度使用Progress组件,宽度为30%,高度为8像素,颜色为绿色
  • 整个Row设置内边距为12像素,背景色为白色,边框圆角为8像素,底部边距为8像素

9. 辅助方法实现

为了根据任务状态和优先级设置不同的颜色,我们实现了两个辅助方法:

private getStatusColor(status: string): string {
   
    switch (status) {
   
        case '已完成': return '#4CAF50'
        case '进行中': return '#2196F3'
        case '待开始': return '#9E9E9E'
        default: return '#000000'
    }
}

private getPriorityColor(priority: string): string {
   
    switch (priority) {
   
        case '高': return '#F44336'
        case '中': return '#FF9800'
        case '低': return '#4CAF50'
        default: return '#000000'
    }
}

这些方法根据任务的状态和优先级返回不同的颜色代码:

  • 状态颜色:已完成(绿色)、进行中(蓝色)、待开始(灰色)
  • 优先级颜色:高(红色)、中(橙色)、低(绿色)

这种颜色编码使用户可以通过颜色快速识别任务的状态和优先级。

10. 完整代码

下面是任务管理看板网格布局的完整代码:

// 任务管理看板网格布局
interface TaskType {
   
    title: string;
    status: string;
    priority: string;
    category: string;
    progress: number;
}

@Component
export struct TaskBoardGrid {
   
    private tasks: TaskType[] = [
        {
    title: '完成UI设计', status: '进行中', priority: '高', category: '设计', progress: 60 },
        {
    title: '编写API文档', status: '待开始', priority: '中', category: '开发', progress: 0 },
        {
    title: '测试登录功能', status: '已完成', priority: '低', category: '测试', progress: 100 },
        {
    title: '准备会议材料', status: '进行中', priority: '高', category: '管理', progress: 30 },
        {
    title: '代码审查', status: '待开始', priority: '中', category: '开发', progress: 0 },
        {
    title: '用户调研', status: '已完成', priority: '低', category: '设计', progress: 100 }
    ]

    @State currentFilter: string = '全部'

    build() {
   
        Column() {
   
            // 标题和筛选
            Row() {
   
                Text('任务看板')
                    .fontSize(20)
                    .fontWeight(FontWeight.Bold)
                    .layoutWeight(1)

                Select([
                    {
    value: '全部', icon: $r('app.media.01') },
                    {
    value: '设计', icon: $r('app.media.02') },
                    {
    value: '开发', icon: $r('app.media.03') },
                    {
    value: '测试', icon: $r('app.media.04') }
                ])
                    .selected(0)
                    .onSelect((index: number) => {
   
                        this.currentFilter = ['全部', '设计', '开发', '测试'][index]
                    })
                    .width(120)
            }
            .margin({
    bottom: 16 })
            .width('100%')

            // 表头
            GridRow({
    columns: 1 }) {
   
                GridCol({
    span: 1 }) {
   
                    Row() {
   
                        Text('任务名称')
                            .fontSize(14)
                            .fontWeight(FontWeight.Bold)
                            .width('40%')

                        Text('状态')
                            .fontSize(14)
                            .fontWeight(FontWeight.Bold)
                            .width('15%')

                        Text('优先级')
                            .fontSize(14)
                            .fontWeight(FontWeight.Bold)
                            .width('15%')

                        Text('进度')
                            .fontSize(14)
                            .fontWeight(FontWeight.Bold)
                            .width('30%')
                    }
                    .padding(12)
                    .backgroundColor('#F5F5F5')
                    .borderRadius(8)
                }
            }

            // 任务列表
            Scroll() {
   
                GridRow({
    columns: 1 }) {
   
                    ForEach(this.tasks.filter(task =>
                    this.currentFilter === '全部' || task.category === this.currentFilter
                    ), (task: TaskType) => {
   
                        GridCol({
    span: 1 }) {
   
                            Row() {
   
                                Text(task.title)
                                    .fontSize(14)
                                    .width('40%')
                                    .textAlign(TextAlign.Start)

                                Text(task.status)
                                    .fontSize(14)
                                    .fontColor(this.getStatusColor(task.status))
                                    .width('15%')
                                    .textAlign(TextAlign.Center)

                                Text(task.priority)
                                    .fontSize(14)
                                    .fontColor(this.getPriorityColor(task.priority))
                                    .width('15%')
                                    .textAlign(TextAlign.Center)

                                Progress({
    value: task.progress, total: 100, type: ProgressType.Linear })
                                    .width('30%')
                                    .height(8)
                                    .color('#4CAF50')
                            }
                            .padding(12)
                            .backgroundColor('#FFFFFF')
                            .borderRadius(8)
                            .margin({
    bottom: 8 })
                        }
                    })
                }
            }
            .height('70%')
            .margin({
    top: 8 })
        }
        .width('100%')
        .height('100%')
        .padding(16)
    }

    private getStatusColor(status: string): string {
   
        switch (status) {
   
            case '已完成': return '#4CAF50'
            case '进行中': return '#2196F3'
            case '待开始': return '#9E9E9E'
            default: return '#000000'
        }
    }

    private getPriorityColor(priority: string): string {
   
        switch (priority) {
   
            case '高': return '#F44336'
            case '中': return '#FF9800'
            case '低': return '#4CAF50'
            default: return '#000000'
        }
    }
}

11. GridRow和GridCol组件详解

在本案例中,我们使用了单列的GridRow和GridCol组件来实现表头和任务列表的布局:

GridRow({
    columns: 1 }) {
   
    GridCol({
    span: 1 }) {
   
        // 内容
    }
}

这种配置使内容在水平方向上占据整个可用宽度,适合用于列表式布局。

11.1 GridRow组件

GridRow是HarmonyOS NEXT提供的网格行容器组件,用于创建网格布局。它具有以下主要属性:

属性 类型 描述
columns number \ { xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?: number } 设置布局列数
gutter number \ { x?: number, y?: number } 栅格间隔
breakpoints { value: string[], reference: BreakpointsReference } 设置断点值的断点数列以及基于窗口或容器尺寸的相应参照
direction GridRowDirection 栅格布局排列方向

11.2 GridCol组件

GridCol是HarmonyOS NEXT提供的网格列容器组件,用于在GridRow中创建网格列。它具有以下主要属性:

属性 类型 描述
span number \ { xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?: number } 列宽度
offset number \ { xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?: number } 列偏移量
order number \ { xs?: number, sm?: number, md?: number, lg?: number, xl?: number, xxl?: number } 列顺序

12. 布局效果分析

本案例中的任务管理看板布局具有以下特点:

  1. 垂直分区明确:整体布局分为三个垂直区域(标题和筛选、表头、任务列表),结构清晰
  2. 水平对齐一致:表头和任务项的各列宽度保持一致,使内容垂直对齐
  3. 视觉区分明显:通过不同的颜色标识任务状态和优先级,提高信息的可读性
  4. 交互功能实用:通过筛选下拉框可以按分类筛选任务,提高用户体验
  5. 滚动区域合理:任务列表区域可滚动,适合显示大量任务

这种布局设计使任务管理看板界面既美观又实用,用户可以轻松地查看和筛选任务信息。

13. 总结

本教程详细讲解了如何使用HarmonyOS NEXT的GridRow和GridCol组件实现任务管理看板的网格布局。通过合理的数据结构设计和布局规划,我们创建了一个功能完整、界面美观的任务管理看板。

主要内容包括:

  • 任务数据结构设计和数据准备
  • 整体布局结构的实现
  • 标题和筛选功能的详细实现
  • 表头和任务列表的设计与实现
  • 状态和优先级的视觉区分

通过本教程,你应该已经掌握了如何使用GridRow和GridCol组件实现列表式布局,以及如何结合其他组件(如Select、Scroll、Progress等)创建功能丰富的界面。这些技能可以应用到各种需要列表展示和数据筛选的场景中,如任务管理、数据分析、信息展示等。

在下一篇教程中,我们将进一步探讨如何优化任务管理看板,添加更多功能和交互效果,使其更加实用和吸引人。

相关文章
|
5月前
|
监控 JavaScript 编译器
从“天书”到源码:HarmonyOS NEXT 崩溃堆栈解析实战指南
本文详解如何利用 hiAppEvent 监控并获取 sourcemap、debug so 等核心产物,剖析了 hstack 工具如何将混淆的 Native 与 ArkTS 堆栈还原为源码,助力开发者掌握异常分析方法,提升应用稳定性。
677 72
|
6月前
|
开发者 容器
鸿蒙应用开发从入门到实战(十四):ArkUI组件Column&Row&线性布局
ArkUI提供了丰富的系统组件,用于制作鸿蒙原生应用APP的UI,本文主要讲解Column和Row组件的使用以及线性布局的方法。
543 12
|
6月前
|
API 数据处理
鸿蒙应用开发从入门到实战(十三):ArkUI组件Slider&Progress
ArkUI提供了丰富的系统组件,用于制作鸿蒙原生应用APP的UI,本文主要讲解滑块Slider和进度条Progress组件的使用。
270 1
|
6月前
|
JavaScript 开发者 索引
鸿蒙应用开发从入门到实战(九):ArkTS渲染控制
ArkTS拓展了TypeScript,可以结合ArkUI进行渲染控制,是的界面设计具有可编程性。本文简要描述鸿蒙应用开发中的条件渲染和循环渲染。
282 5
|
5月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
878 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
5月前
|
移动开发 JavaScript 应用服务中间件
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
737 5
【06】优化完善落地页样式内容-精度优化-vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
5月前
|
移动开发 Rust JavaScript
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
948 4
【01】首页建立-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
|
6月前
|
数据安全/隐私保护 开发者
鸿蒙应用开发从入门到实战(十一):ArkUI组件Text&TextInput
ArkUI提供了丰富的系统组件,用于制作鸿蒙原生应用APP的UI,本文主要讲解文本组件Text和TextInput的使用。
416 3
|
6月前
|
存储 缓存 5G
鸿蒙 HarmonyOS NEXT端云一体化开发-云存储篇
本文介绍用户登录后获取昵称、头像的方法,包括通过云端API和AppStorage两种方式,并实现上传头像至云存储及更新用户信息。同时解决图片缓存问题,添加上传进度提示,支持自动登录判断,提升用户体验。
274 1
|
5月前
|
移动开发 Android开发
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【03】建立隐私关于等相关页面和内容-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
283 0

热门文章

最新文章