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开发必备

​​

总结

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

相关推荐
幺零九零零37 分钟前
【计算机网络】TCP协议面试常考(一)
服务器·tcp/ip·计算机网络
云飞云共享云桌面2 小时前
8位机械工程师如何共享一台图形工作站算力?
linux·服务器·网络
逐·風2 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫2 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦3 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
SoraLuna3 小时前
「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
macos·ui·harmonyos
GIS程序媛—椰子3 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山4 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享4 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
ClkLog-开源埋点用户分析4 小时前
ClkLog企业版(CDP)预售开启,更有鸿蒙SDK前来助力
华为·开源·开源软件·harmonyos