[HarmonyOS NEXT 实战案例十八] 日历日程视图网格布局(上)

简介: 日历是许多应用程序中常见的UI组件,用于展示日期和相关事件。在本教程中,我们将学习如何使用HarmonyOS NEXT的GridRow和GridCol组件实现一个简洁、美观的日历日程视图网格布局。

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

效果演示

image.png

1. 概述

日历是许多应用程序中常见的UI组件,用于展示日期和相关事件。在本教程中,我们将学习如何使用HarmonyOS NEXT的GridRow和GridCol组件实现一个简洁、美观的日历日程视图网格布局。

本教程将涵盖以下内容:

  • 日历数据结构设计
  • 整体布局实现
  • 星期标题行实现
  • 日期网格实现
  • 事件标记显示
  • GridRow和GridCol组件配置详解
  • 布局效果分析

2. 日历数据结构设计

首先,我们需要定义日历数据的结构。对于日历视图,我们需要两种数据:星期标题和日期数据。

interface dateType {
   
    date: string;   // 日期字符串
    hasEvent: boolean; // 是否有事件标记
}

这个接口定义了日期的基本结构,包含两个属性:

  • date:字符串类型,表示日期
  • hasEvent:布尔类型,表示该日期是否有事件

3. 数据准备

接下来,我们准备日历所需的数据:

private days: string[] = ['日', '一', '二', '三', '四', '五', '六']
private dates: dateType[] = [
    {
    date: '1', hasEvent: false },
    {
    date: '2', hasEvent: true },
    {
    date: '3', hasEvent: false },
    {
    date: '4', hasEvent: false },
    {
    date: '5', hasEvent: true },
    {
    date: '6', hasEvent: false },
    {
    date: '7', hasEvent: false },
    {
    date: '8', hasEvent: false },
    {
    date: '9', hasEvent: false },
    {
    date: '10', hasEvent: false },
    {
    date: '11', hasEvent: false },
    {
    date: '12', hasEvent: false },
    {
    date: '13', hasEvent: false },
    {
    date: '14', hasEvent: false },
    {
    date: '15', hasEvent: false },
    {
    date: '16', hasEvent: false },
]

在这个示例中,我们创建了两个数组:

  1. days:包含星期几的标题(日、一、二、三、四、五、六)
  2. dates:包含16天的日期数据,其中第2天和第5天标记为有事件

4. 整体布局实现

现在,我们开始实现日历日程视图的整体布局:

build() {
   
    Column() {
   
        // 月份标题
        GridRow({
    columns: 1 }) {
   
            GridCol({
    span: 1 }) {
   
                Text('2023年11月')
                    .fontSize(18)
                    .fontWeight(FontWeight.Bold)
                    .margin({
    bottom: 16 })
                    .width('100%')
                    .textAlign(TextAlign.Center)
            }
        }

        // 星期标题
        GridRow({
    columns: 7 }) {
   
            // 星期标题内容
        }

        // 日期网格
        GridRow({
    columns: 7, gutter: 4 }) {
   
            // 日期网格内容
        }
    }
    .width('100%')
    .padding(16)
}

整体布局使用一个Column组件作为容器,包含三个主要部分:

  1. 月份标题:显示当前月份(2023年11月)
  2. 星期标题行:显示星期几的标题
  3. 日期网格:显示日期和事件标记

整个Column容器设置了100%的宽度和16的内边距,确保内容在屏幕上有适当的边距。

5. 月份标题实现

月份标题使用单列的GridRow和GridCol组件,确保标题居中显示:

// 月份标题
GridRow({
    columns: 1 }) {
   
    GridCol({
    span: 1 }) {
   
        Text('2023年11月')
            .fontSize(18)
            .fontWeight(FontWeight.Bold)
            .margin({
    bottom: 16 })
            .width('100%')
            .textAlign(TextAlign.Center)
    }
}

在这个实现中:

  • GridRow的columns设置为1,表示只有一列
  • GridCol的span设置为1,表示占据整个列宽
  • Text组件显示月份标题,使用18的字体大小和粗体样式,使其在视觉上更加突出
  • 设置底部边距为16,与下方的星期标题行保持适当的间距
  • 设置文本居中对齐,使标题在视觉上更加平衡

6. 星期标题行实现

星期标题行使用7列的GridRow和GridCol组件,每列显示一个星期几的标题:

// 星期标题
GridRow({
    columns: 7 }) {
   
    ForEach(this.days, (day: string) => {
   
        GridCol({
    span: 1 }) {
   
            Text(day)
                .fontSize(14)
                .textAlign(TextAlign.Center)
                .padding(8)
        }
    })
}

在这个实现中:

  • GridRow的columns设置为7,表示有7列,对应一周7天
  • 使用ForEach循环遍历days数组,为每个星期几创建一个GridCol
  • 每个GridCol的span设置为1,表示占据一列的宽度
  • Text组件显示星期几的标题,使用14的字体大小和居中对齐
  • 设置内边距为8,确保文本有足够的空间

7. 日期网格实现

日期网格也使用7列的GridRow和GridCol组件,但添加了间距和更复杂的内容:

// 日期网格
GridRow({
    columns: 7, gutter: 4 }) {
   
    ForEach(this.dates, (date: dateType) => {
   
        GridCol({
    span: 1 }) {
   
            Column() {
   
                Text(date.date)
                    .fontSize(16)
                    .textAlign(TextAlign.Center)

                if (date.hasEvent) {
   
                    Circle()
                        .width(6)
                        .height(6)
                        .fill('#FF5722')
                        .margin({
    top: 4 })
                }
            }
            .padding(8)
            .backgroundColor('#FFFFFF')
            .borderRadius(4)
            .height(60)
            .justifyContent(FlexAlign.Center)
        }
    })
}

在这个实现中:

  • GridRow的columns设置为7,表示有7列,对应一周7天
  • GridRow的gutter设置为4,表示列之间的间距为4
  • 使用ForEach循环遍历dates数组,为每个日期创建一个GridCol
  • 每个GridCol的span设置为1,表示占据一列的宽度
  • 在每个GridCol中,使用Column组件创建垂直布局,包含以下元素:
    • Text组件显示日期,使用16的字体大小和居中对齐
    • 如果日期有事件(hasEvent为true),则显示一个小圆点作为事件标记
  • 为Column添加样式:
    • 内边距为8,提供足够的内容间距
    • 白色背景色,使日期在视觉上更加突出
    • 4的圆角,使日期格子看起来更加现代化
    • 固定高度为60,确保所有日期格子大小一致
    • 使用justifyContent(FlexAlign.Center)使内容垂直居中

8. GridRow和GridCol组件配置详解

在这个日历日程视图布局中,我们使用了GridRow和GridCol组件的多种配置:

8.1 月份标题的GridRow配置

GridRow({
    columns: 1 })
  • columns: 1:设置网格为单列布局,这意味着标题将占据整个行宽

8.2 星期标题行的GridRow配置

GridRow({
    columns: 7 })
  • columns: 7:设置网格为7列布局,对应一周7天

8.3 日期网格的GridRow配置

GridRow({
    columns: 7, gutter: 4 })
  • columns: 7:设置网格为7列布局,对应一周7天
  • gutter: 4:设置列之间的间距为4,使日期格子之间有适当的分隔

8.4 GridCol配置

在所有三个部分中,GridCol的配置都很简单:

GridCol({
    span: 1 })
  • span: 1:设置列跨度为1,表示每个元素占据一列的宽度

这种配置在日历视图中非常合适,因为每个星期几和每个日期都应该占据相等的空间。

9. 布局效果分析

这种日历日程视图的网格布局具有以下特点:

  1. 清晰的层次结构:月份标题、星期标题行和日期网格形成明确的视觉层次,使用户能够快速理解页面结构

  2. 均匀的网格布局:7列的网格布局完美对应一周7天,创建了一个直观的日历视图

  3. 事件标记:通过小圆点标记有事件的日期,使用户能够一目了然地看到哪些日期有安排

  4. 适当的间距和分隔:日期格子之间的间距和每个格子的内边距确保了内容不会过于拥挤,提高了可读性

  5. 一致的视觉样式:所有日期格子使用相同的大小、背景色和圆角,创建一致的视觉体验

10. 完整代码

以下是日历日程视图网格布局的完整代码:

// 日历日程视图网格布局
interface dateType {
   
    date: string;
    hasEvent: boolean;
}

@Component
export struct CalendarGrid {
   
    private days: string[] = ['日', '一', '二', '三', '四', '五', '六']
    private dates: dateType[] = [
        {
    date: '1', hasEvent: false },
        {
    date: '2', hasEvent: true },
        {
    date: '3', hasEvent: false },
        {
    date: '4', hasEvent: false },
        {
    date: '5', hasEvent: true },
        {
    date: '6', hasEvent: false },
        {
    date: '7', hasEvent: false },
        {
    date: '8', hasEvent: false },
        {
    date: '9', hasEvent: false },
        {
    date: '10', hasEvent: false },
        {
    date: '11', hasEvent: false },
        {
    date: '12', hasEvent: false },
        {
    date: '13', hasEvent: false },
        {
    date: '14', hasEvent: false },
        {
    date: '15', hasEvent: false },
        {
    date: '16', hasEvent: false },
    ]

    build() {
   
        Column() {
   
            // 月份标题
            GridRow({
    columns: 1 }) {
   
                GridCol({
    span: 1 }) {
   
                    Text('2023年11月')
                        .fontSize(18)
                        .fontWeight(FontWeight.Bold)
                        .margin({
    bottom: 16 })
                        .width('100%')
                        .textAlign(TextAlign.Center)
                }
            }

            // 星期标题
            GridRow({
    columns: 7 }) {
   
                ForEach(this.days, (day: string) => {
   
                    GridCol({
    span: 1 }) {
   
                        Text(day)
                            .fontSize(14)
                            .textAlign(TextAlign.Center)
                            .padding(8)
                    }
                })
            }

            // 日期网格
            GridRow({
    columns: 7, gutter: 4 }) {
   
                ForEach(this.dates, (date: dateType) => {
   
                    GridCol({
    span: 1 }) {
   
                        Column() {
   
                            Text(date.date)
                                .fontSize(16)
                                .textAlign(TextAlign.Center)

                            if (date.hasEvent) {
   
                                Circle()
                                    .width(6)
                                    .height(6)
                                    .fill('#FF5722')
                                    .margin({
    top: 4 })
                            }
                        }
                        .padding(8)
                        .backgroundColor('#FFFFFF')
                        .borderRadius(4)
                        .height(60)
                        .justifyContent(FlexAlign.Center)
                    }
                })
            }
        }
        .width('100%')
        .padding(16)
    }
}

11. 日历网格布局的技巧

11.1 使用固定列数

日历视图是使用固定列数(7列)的绝佳例子,因为一周恰好有7天。这种自然的对应关系使得网格布局非常适合日历视图。

11.2 使用gutter属性分隔日期格子

在日期网格中,我们使用了gutter属性来添加列之间的间距:

GridRow({
    columns: 7, gutter: 4 })

这种方法比使用margin更加简洁,因为gutter会自动应用于所有列之间,确保间距的一致性。

11.3 使用条件渲染显示事件标记

我们使用条件渲染来显示事件标记:

if (date.hasEvent) {
   
    Circle()
        .width(6)
        .height(6)
        .fill('#FF5722')
        .margin({
    top: 4 })
}

这种方法只在有事件的日期下方显示小圆点,使界面更加清晰,不会因为过多的视觉元素而显得混乱。

11.4 使用固定高度确保一致性

为日期格子设置固定高度可以确保所有格子大小一致,即使某些格子有事件标记,而其他格子没有:

.height(60)

这种方法创造了一个整齐、均匀的网格,提升了整体美感。

12. 总结

在本教程中,我们学习了如何使用HarmonyOS NEXT的GridRow和GridCol组件实现日历日程视图的网格布局。这个例子展示了网格布局系统在创建规则、均匀的UI结构时的强大功能。

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

热门文章

最新文章