HarmonyOS应用开发( Beta5.0)一杯冰美式的时间“拿捏Grid组件”

常见情形

在很多手机商城的页面中会出现类似网格状一样的情况,例如:

  1. 京东

​这里呢是采用Grid组件中的控制滚动,里面的rowsTemplate属性为一行且不对列的行数属性进行操作,这样的话就可以控制水平滑动了。

2.淘宝

​ 这里就是极其简单的2*4的网格布局。

3.hao123

​ 这里类似淘宝。

基本用法

Grid组件适用于布局由很多的行和列所组成、行列部分需要合并、需要滚动的场景。如下:

组件结构:

复制代码
Grid(){
    GridItem(){
        //展示的内容
    }
    GridItem(){
        //展示的内容
    }
}

说明:1.Grid的子组件必须是GridItem组件,展示的内容放在GridItem中

​ 2.GridItem只有一个子组件,跟初始代码块中build()一样,有且只能有一个子组件

​ 3.Grid组件若是没有设置宽高,会默认适应其父组件的尺寸

样例:

复制代码
@Entry
@Component
struct Index {
  nums: number[] = Array.from({ length: 10 })//定义数组

  build() {
    Column() {
      Grid() {
        ForEach(this.nums, (item: number, index: number) => {//ForEach循环渲染
          GridItem() {
            Text(index.toString())//调用索引对GridItem进行编号
              .fontSize(30)
              .padding(5)
              .backgroundColor(Color.Yellow)
          }
        })
      }
    }
    .width("100%")
    .height("100%")
  }

运行结果:

由于没有对齐进行行列分布,所以所有GridItem()内的内容都展示在一行,下面让我来介绍一下Grid组件中常用的属性

基础属性

1.columnsTemplate 该属性用于设置网格布局的列数量

示例写法: .columnsTemplate('1fr 1fr 2fr')

从中fr出现的次数表示分成了几列,前面的数字则表示当前列所占用的份数

2.rowsTemplate 该属性用于设置网格布局的行数量

示例写法: .rowsTemplate('1fr 1fr 2fr')

从中fr出现的次数表示分成了几行,前面的数字则表示当前行所占用的份数

3.columnsGap 该属性用于控制列与列之间的间距

示例写法: .columnsGap(10)

4.rowsGap 该属性用于控制行与行1之间的间距

示例写法: .rowsGap(10)

练一练:

复制代码
@Entry
@Component
struct TestPage {
  build() {
    Grid() {
      this.GridItemBuilder('1', Color.Blue)
      this.GridItemBuilder('2', Color.Blue)
      this.GridItemBuilder('3', Color.Blue)
      this.GridItemBuilder('4', Color.Blue)
      this.GridItemBuilder('5', Color.Blue)
      this.GridItemBuilder('6', Color.Blue)
    }
    .rowsTemplate('1fr 1fr 1fr')
    .columnsTemplate('1fr 2fr 1fr')
    .rowsGap(10)
    .columnsGap(10)
    .width('100%')
    .height(300)
  }

  @Builder
  GridItemBuilder(title: string, bgColor: ResourceColor) {
    GridItem() {
      Text(title)
        .fontColor(Color.White)
        .fontSize(30)
    }
    .backgroundColor('#0094ff')
  }
}

这边解答采用了@Builder将GridItem进行了封装,这样看起来清晰很多。

合并行列

像下面左边的图片我们可以通过分配列占的份数来让他变宽,但下面右边的图片中的合并应该怎么样来做呢?这边则需要用到一些GridItem属性,让我来为大家讲解。

GridItem属性:

  1. rowStart(number) 指定当前元素的起始行号

  2. rowEnd(number) 指定当前元素的终点行号

  3. columnStart(number) 指定当前元素的起始列号

  4. columnEnd (number) 指定当前元素的终点行号

    !!!这里的起始行号和列号是从1开始,比如你写的是四列,那么列号就是1,2,3,4

首先,我们先对所有元素进行编号,我这里就是直接用forEach中索引标记

然后,我们需要通过索引找到我们需要进行合并网格,这边我拿索引为2和3的网格举个例子。显然易见,这两个网格是列合并,行是没有变化,所以只需要找到其中一个,添加起始列号和终点列号就可以完成合并。

以此类推,索引4和8的网格是行合并,起始和终点行号分别为2,3,索引8,9,10就是类似2,3的列合并,起始和终点列号为2和4。

完整代码:

复制代码
@Entry
@Component
struct GridPage03 {
  nums: number[] = Array.from({ length: 12 })

  build() {
    Grid() {
      ForEach(this.nums, (item: number, index: number) => {
        if (index === 2) {
          GridItem() {
            Text(index + '')
              .fontColor(Color.White)
              .fontSize(30)
          }
          .backgroundColor('#9dc3e6')
          .columnStart(3)
          .columnEnd(4)
        } else if (index === 3) {
          GridItem() {
            Text(index + '')
              .fontColor(Color.White)
              .fontSize(30)
          }
          .backgroundColor('#9dc3e6')
          .rowStart(2)
          .rowEnd(3)
        } else {
          GridItem() {
            Text(index + '')
              .fontColor(Color.White)
              .fontSize(30)
          }
          .backgroundColor('#9dc3e6')
        }

      })
    }
    .columnsTemplate('1fr 1fr 1fr 1fr')
    .rowsTemplate('1fr 1fr 1fr')
    .width('100%')
    .height(260)
    .rowsGap(10)
    .columnsGap(10)
    .padding(10)
  }
}

第二种方法:GridLayoutOptions

这个接口非常的新,也是刚更新不久,官方文档:developer.huawei.com/consumer/cn...

我们先来看下最常用的两个参数吧!

  1. regularSize[number,number] 大小规则的GridItem在Grid中所占的行数和列数 ,目前呢只支持一行一列,也就是[1,1]

  2. onGetRectByIndex 类型:(index:number)=>[rowStart,columnStart,rowSpan,columnSpan]

    这里就是先通过索引找对应的GridItem,然后通过中括号里的四个参数来进行合并行列。

    1. rowStart 表达的含义跟第一种方法一样,表示当前元素行起始位置
    2. columnStart 也是如此,表示当前元素列起始位置
    3. rowSpan 这里Span表示跨度的意思,所以就是占用的行数
    4. columnSpan 表示占用的列数

完整代码:

复制代码
@Entry
@Component
struct Index {
  @State nums: string[] = ['0', '1', '2', '3', '4', '5']
  layoutOption: GridLayoutOptions = {
    regularSize: [1, 1],
    onGetRectByIndex: (index: number) => {
      if (index == 0) {
        return [0, 0, 1, 1]
      } else if (index == 1) {
        return [0, 1, 2, 2]
      } else if (index == 2) {
        return [0, 3, 3, 3]
      } else if (index == 3) {
        return [3, 0, 3, 3]
      } else if (index == 4) {
        return [4, 3, 2, 2]
      } else {
        return [4, 5, 2, 1]
      }
    }
  }

  build() {
    Grid(undefined, this.layoutOption) {
      ForEach(this.nums, (item: string) => {
        GridItem() {
          Text(item)
            .fontSize(16)
            .backgroundColor('#f9ce93')
            .width('100%')
            .height("100%")
            .textAlign(TextAlign.Center)
        }
        .height("100%")
        .width('100%')
      })
    }
    .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr')
    .rowsTemplate('1fr 1fr 1fr 1fr 1fr 1fr')
    .columnsGap(10)
    .rowsGap(10)
    .width('90%')
    .backgroundColor('#fcf0e2')
    .height(300)
  }
}

设置滚动

像文案开头京东那种就是可以滑动的网格布局,这里原理也是非常的简单,Grid中滑动不需要用到scroller控制器,只需要以下操作。

  1. 水平滚动:设置的是rowsTemplate,Grid的滚动方向为水平方向。
  2. 垂直滚动:设置的是columnsTemplate,Grid的滚动方向为垂直方向。

!!!这两不要同时设置,不然就滑动不了了

试一试:

复制代码
@Entry
@Component
struct Day01_09_Grid05 {
  // 长度为 10 每一项都为 undefined 的数组
  list: string[] = Array.from({ length: 30 })

  build() {
    Column() {
      Grid() {
        ForEach(this.list, (item: string, index) => {
          GridItem() {
            Text((index + 1).toString())
              .newExtend()
          }
          .padding(5)
          .height('30%')
          .width('25%')
        })

      }
      .columnsTemplate('1fr 1fr 1fr') // 竖向滚动
      // .rowsTemplate('1fr 1fr 1fr') // 横向滚动
      .rowsGap(10)
      .width('100%')
      .height(300)
      .border({ width: 1 })
      .padding(5)
    }
    .width('100%')
    .height('100%')
  }
}

@Extend(Text)
function newExtend() {
  .backgroundColor('#0094ff')
  .width('100%')
  .height('100%')
  .fontSize(30)
  .fontColor(Color.White)
  .textAlign(TextAlign.Center)
}

当然大家会发现我们的滚动条有点丑,先别急我下面会讲!!

用代码控制滚动

这里很明显是用控制器和按钮来控制滑动了,先讲一下核心步骤吧。

  1. 创建 Scroller 对象

  2. 设置给 Grid

  3. 调用 Scroller 对象的 scrollPage 方法

    复制代码
    // 创建 Scroller 对象
    scroller: Scroller = new Scroller()
    
    // 设置给 Grid
     Grid(this.scroller) {
       // ...
     }
    
    // 通过代码控制
    this.scroller.scrollPage({
      next:true // 下一页
      next:false // 上一页
    })

    练一练:

​ 答案:

复制代码
复制代码
@Entry
@Component
struct Index {
  nums:number[]=Array.from({length:200})
  scroller:Scroller=new Scroller()
  build() {
    Column(){
      Grid(this.scroller){
        ForEach(this.nums,(item:number,index:number)=>{
          GridItem(){
            Text((index+1).toString())
          }
          .backgroundColor('#0094ff')
          .width("25%")
        })
      }
      .padding(10)
      .rowsTemplate('1fr 1fr 1fr 1fr')
      .rowsGap(10)
      .columnsGap(10)
      .height(450)
      Row(){
        Button('上一页')
          .width(100)
          .onClick(()=>{
            this.scroller.scrollPage({
              next:false
            })
          })
        Button('下一页')
          .width(100)
          .onClick(()=>{
            this.scroller.scrollPage({
              next:true
            })
          })
      }
      .width("100%")
      .justifyContent(FlexAlign.SpaceAround)
    }
    .width("100%")
    .height("100%")
  }
}

自定义滚动条

使用属性调整

  1. scrollBar 设置滚动条状态

    BarState.off 关闭

    BarState.on 常驻

    BarState.auto 按需显示

  2. scrollBarColor 设置滚动条的颜色

    .scrollBarWidth(20) // 宽度 .scrollBarColor(Color.Orange) // 滚颜色
    .scrollBar(BarState.Off) // 关闭

自定义组件

主要就是三个参数如下:

  1. scroller 可控制组建的控制器

  2. direction:ScrollBarDirection.Vertical/Horizontal 滚动条的方向

  3. state 滚动条的状态

    // 和 Grid 共用同一个 Scroller
    scroller: Scroller = new Scroller()

    // 和 Grid 共用同一个 Scroller
    Grid(this.scroller){
    // 略
    }

    // 和 Grid 共用同一个 Scroller
    // 创建 ScrollBar 组件并设置属性
    ScrollBar({
    scroller: this.scroller,
    direction: ScrollBarDirection.Horizontal // 方向
    }) {
    // 滚动内容 设置外观即可
    Text()
    }
    // 设置外观

最后

小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,不同的角度的问了一些问题,我明显感觉到一点,那就是许多人参与鸿蒙开发,但是又不知道从哪里下手,因为体系杂乱无章,教授的人也多,无从选择。有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)文档用来跟着学习是非常有必要的。

为了确保高效学习,建议规划清晰的学习路线,涵盖以下关键阶段:

希望这一份鸿蒙学习文档能够给大家带来帮助~

GitCode - 全球开发者的开源社区,开源代码托管平台


鸿蒙(HarmonyOS NEXT)最新学习路线

该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案

路线图适合人群:

IT开发人员: 想要拓展职业边界
零基础小白: 鸿蒙爱好者,希望从0到1学习,增加一项技能。
**技术提升/进阶跳槽:**发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术

2.视频教程+学习PDF文档

(鸿蒙语法ArkTS、TypeScript、ArkUI教程......)

纯血版鸿蒙全套学习文档(面试、文档、全套视频等)

鸿蒙APP开发必备

​​

总结

参与鸿蒙开发,你要先认清适合你的方向,如果是想从事鸿蒙应用开发方向的话,可以参考本文的学习路径,简单来说就是:为了确保高效学习,建议规划清晰的学习路线

相关推荐
C_心欲无痕12 小时前
ts - 类型收窄
前端·typescript
小雨下雨的雨12 小时前
Flutter 框架跨平台鸿蒙开发 —— Row & Column 布局之轴线控制艺术
flutter·华为·交互·harmonyos·鸿蒙系统
笔COOL创始人12 小时前
requestAnimationFrame 动画优化实践指南
前端·javascript·面试
少云清12 小时前
【性能测试】3_性能测试基础 _指标
运维·服务器·数据库·性能测试·性能测试指标
sophie旭12 小时前
性能监控之首屏性能监控小实践
前端·javascript·性能优化
Amumu1213812 小时前
React 前端请求
前端·react.js·okhttp
行走的bug...12 小时前
cmake总结
linux·运维·服务器
凌波粒12 小时前
Linux 面试题篇
linux·运维·服务器
小雨下雨的雨12 小时前
Flutter 框架跨平台鸿蒙开发 —— Center 控件之完美居中之道
flutter·ui·华为·harmonyos·鸿蒙
虾..12 小时前
Linux 线程控制
linux·运维·服务器