首页 > 其他分享 >List组件和Grid组件的使用

List组件和Grid组件的使用

时间:2024-01-21 20:34:54浏览次数:29  
标签:Tabs 100% List 1fr 列表 Grid 组件

简介

在我们常用的手机应用中,经常会见到一些数据列表,如设置页面、通讯录、商品列表等。下图中两个页面都包含列表,“首页”页面中包含两个网格布局,“商城”页面中包含一个商品列表。

上图中的列表中都包含一系列相同宽度的列表项,连续、多行呈现同类数据,例如图片和文本。常见的列表有线性列表(List列表)和网格布局(Grid列表):

为了帮助开发者构建包含列表的应用,ArkUI提供了List组件和Grid组件,开发者使用List和Grid组件能够很轻松的完成一些列表页面。

List组件的使用

List组件简介

List是很常用的滚动类容器组件,一般和子组件ListItem一起使用,List列表中的每一个列表项对应一个ListItem组件。

使用ForEach渲染列表

列表往往由多个列表项组成,所以我们需要在List组件中使用多个ListItem组件来构建列表,这就会导致代码的冗余。使用循环渲染(ForEach)遍历数组的方式构建列表,可以减少重复代码,示例代码如下:

   
  1. @Entry
  2. @Component
  3. struct ListDemo {
  4. private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  5. build() {
  6. Column() {
  7. List({ space: 10 }) {
  8. ForEach(this.arr, (item: number) => {
  9. ListItem() {
  10. Text(`${item}`)
  11. .width('100%')
  12. .height(100)
  13. .fontSize(20)
  14. .fontColor(Color.White)
  15. .textAlign(TextAlign.Center)
  16. .borderRadius(10)
  17. .backgroundColor(0x007DFF)
  18. }
  19. }, item => item)
  20. }
  21. }
  22. .padding(12)
  23. .height('100%')
  24. .backgroundColor(0xF1F3F5)
  25. }
  26. }

效果图如下:

设置列表分割线

List组件子组件ListItem之间默认是没有分割线的,部分场景子组件ListItem间需要设置分割线,这时候您可以使用List组件的divider属性。divider属性包含四个参数:

  • strokeWidth: 分割线的线宽。
  • color: 分割线的颜色。
  • startMargin:分割线距离列表侧边起始端的距离。
  • endMargin: 分割线距离列表侧边结束端的距离。

List列表滚动事件监听

List组件提供了一系列事件方法用来监听列表的滚动,您可以根据需要,监听这些事件来做一些操作:

  • onScroll:列表滑动时触发,返回值scrollOffset为滑动偏移量,scrollState为当前滑动状态。
  • onScrollIndex:列表滑动时触发,返回值分别为滑动起始位置索引值与滑动结束位置索引值。
  • onReachStart:列表到达起始位置时触发。
  • onReachEnd:列表到底末尾位置时触发。
  • onScrollStop:列表滑动停止时触发。

使用示例代码如下:

   
  1. List({ space: 10 }) {
  2. ForEach(this.arr, (item) => {
  3. ListItem() {
  4. Text(`${item}`)
  5. ...
  6. }
  7. }, item => item)
  8. }
  9. .onScrollIndex((firstIndex: number, lastIndex: number) => {
  10. console.info('first' + firstIndex)
  11. console.info('last' + lastIndex)
  12. })
  13. .onScroll((scrollOffset: number, scrollState: ScrollState) => {
  14. console.info('scrollOffset' + scrollOffset)
  15. console.info('scrollState' + scrollState)
  16. })
  17. .onReachStart(() => {
  18. console.info('onReachStart')
  19. })
  20. .onReachEnd(() => {
  21. console.info('onReachEnd')
  22. })
  23. .onScrollStop(() => {
  24. console.info('onScrollStop')
  25. })

设置List排列方向

List组件里面的列表项默认是按垂直方向排列的,如果您想让列表沿水平方向排列,您可以将List组件的listDirection属性设置为Axis.Horizontal。

listDirection参数类型是Axis,定义了以下两种类型:

  • Vertical(默认值):子组件ListItem在List容器组件中呈纵向排列。

  • Horizontal:子组件ListItem在List容器组件中呈横向排列。

Grid组件的使用

Grid组件简介

Grid组件为网格容器,是一种网格列表,由“行”和“列”分割的单元格所组成,通过指定“项目”所在的单元格做出各种各样的布局。Grid组件一般和子组件GridItem一起使用,Grid列表中的每一个条目对应一个GridItem组件。

使用ForEach渲染网格布局

和List组件一样,Grid组件也可以使用ForEach来渲染多个列表项GridItem,我们通过下面的这段示例代码来介绍Grid组件的使用。

   
  1. @Entry
  2. @Component
  3. struct GridExample {
  4. // 定义一个长度为16的数组
  5. private arr: string[] = new Array(16).fill('').map((_, index) => `item ${index}`);
  6. build() {
  7. Column() {
  8. Grid() {
  9. ForEach(this.arr, (item: string) => {
  10. GridItem() {
  11. Text(item)
  12. .fontSize(16)
  13. .fontColor(Color.White)
  14. .backgroundColor(0x007DFF)
  15. .width('100%')
  16. .height('100%')
  17. .textAlign(TextAlign.Center)
  18. }
  19. }, item => item)
  20. }
  21. .columnsTemplate('1fr 1fr 1fr 1fr')
  22. .rowsTemplate('1fr 1fr 1fr 1fr')
  23. .columnsGap(10)
  24. .rowsGap(10)
  25. .height(300)
  26. }
  27. .width('100%')
  28. .padding(12)
  29. .backgroundColor(0xF1F3F5)
  30. }
  31. }

示例代码中创建了16个GridItem列表项。同时设置columnsTemplate的值为'1fr 1fr 1fr 1fr',表示这个网格为4列,将Grid允许的宽分为4等分,每列占1份;rowsTemplate的值为'1fr 1fr 1fr 1fr',表示这个网格为4行,将Grid允许的高分为4等分,每行占1份。这样就构成了一个4行4列的网格列表,然后使用columnsGap设置列间距为10vp,使用rowsGap设置行间距也为10vp。示例代码效果图如下:

上面构建的网格布局使用了固定的行数和列数,所以构建出的网格是不可滚动的。然而有时候因为内容较多,我们通过滚动的方式来显示更多的内容,就需要一个可以滚动的网格布局。我们只需要设置rowsTemplate和columnsTemplate中的一个即可。

将示例代码中GridItem的高度设置为固定值,例如100;仅设置columnsTemplate属性,不设置rowsTemplate属性,就可以实现Grid列表的滚动:

   
  1. Grid() {
  2. ForEach(this.arr, (item: string) => {
  3. GridItem() {
  4. Text(item)
  5. .height(100)
  6. ...
  7. }
  8. }, item => item)
  9. }
  10. .columnsTemplate('1fr 1fr 1fr 1fr')
  11. .columnsGap(10)
  12. .rowsGap(10)
  13. .height(300)

此外,Grid像List一样也可以使用onScrollIndex来监听列表的滚动。

列表性能优化

开发者在使用长列表时,如果直接采用循环渲染方式,会一次性加载所有的列表元素,从而导致页面启动时间过长,影响用户体验,推荐通过以下方式来进行列表性能优化:

使用数据懒加载

设置list组件的宽高

参考链接

  1. List组件的相关API参考:List组件
  2. Grid组件的相关API参考:Grid组件
  3. 循环渲染(ForEach):循环渲染

 

Tabs组件的使用  

概述

在我们常用的应用中,经常会有视图内容切换的场景,来展示更加丰富的内容。比如下面这个页面,点击底部的页签的选项,可以实现“首页”和“我的”

两个内容视图的切换。

ArkUI开发框架提供了一种页签容器组件Tabs,开发者通过Tabs组件可以很容易的实现内容视图的切换。页签容器Tabs的形式多种多样,不同的页面设计页签不一样,可以把页签设置在底部、顶部或者侧边。

本文将详细介绍Tabs组件的使用。

Tabs组件的简单使用

Tabs组件仅可包含子组件TabContent,每一个页签对应一个内容视图即TabContent组件。下面的示例代码构建了一个简单的页签页面:

   
  1. @Entry
  2. @Component
  3. struct TabsExample {
  4. private controller: TabsController = new TabsController()
  5. build() {
  6. Column() {
  7. Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
  8. TabContent() {
  9. Column().width('100%').height('100%').backgroundColor(Color.Green)
  10. }
  11. .tabBar('green')
  12. TabContent() {
  13. Column().width('100%').height('100%').backgroundColor(Color.Blue)
  14. }
  15. .tabBar('blue')
  16. TabContent() {
  17. Column().width('100%').height('100%').backgroundColor(Color.Yellow)
  18. }
  19. .tabBar('yellow')
  20. TabContent() {
  21. Column().width('100%').height('100%').backgroundColor(Color.Pink)
  22. }
  23. .tabBar('pink')
  24. }
  25. .barWidth('100%') // 设置TabBar宽度
  26. .barHeight(60) // 设置TabBar高度
  27. .width('100%') // 设置Tabs组件宽度
  28. .height('100%') // 设置Tabs组件高度
  29. .backgroundColor(0xF5F5F5) // 设置Tabs组件背景颜色
  30. }
  31. .width('100%')
  32. .height('100%')
  33. }
  34. }

效果图如下:

上面示例代码中,Tabs组件中包含4个子组件TabContent,通过TabContent的tabBar属性设置TabBar的显示内容。使用通用属性width和height设置了Tabs组件的宽高,使用barWidth和barHeight设置了TabBar的宽度和高度。

  说明
  • TabContent组件不支持设置通用宽度属性,其宽度默认撑满Tabs父组件。
  • TabContent组件不支持设置通用高度属性,其高度由Tabs父组件高度与TabBar组件高度决定。
 

设置TabBar布局模式

因为Tabs的布局模式默认是Fixed的,所以Tabs的页签是不可滑动的。当页签比较多的时候,可能会导致页签显示不全,将布局模式设置为Scrollable的话,可以实现页签的滚动。

Tabs的布局模式有Fixed(默认)和Scrollable两种:

  • BarMode.Fixed:所有TabBar平均分配barWidth宽度(纵向时平均分配barHeight高度),页签不可滚动,效果图如下:

  • BarMode.Scrollable:每一个TabBar均使用实际布局宽度,超过总长度(横向Tabs的barWidth,纵向Tabs的barHeight)后可滑动。

  • 当页签比较多的时候,可以滑动页签,下面的示例代码将barMode设置为BarMode.Scrollable,实现了可滚动的页签:
   
  1. @Entry
  2. @Component
  3. struct TabsExample {
  4. private controller: TabsController = new TabsController()
  5. build() {
  6. Column() {
  7. Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
  8. TabContent() {
  9. Column()
  10. .width('100%')
  11. .height('100%')
  12. .backgroundColor(Color.Green)
  13. }
  14. .tabBar('green')
  15. TabContent() {
  16. Column()
  17. .width('100%')
  18. .height('100%')
  19. .backgroundColor(Color.Blue)
  20. }
  21. .tabBar('blue')
  22. ...
  23. }
  24. .barMode(BarMode.Scrollable)
  25. .barWidth('100%')
  26. .barHeight(60)
  27. .width('100%')
  28. .height('100%')
  29. }
  30. }
  31. }

设置TabBar位置和排列方向

Tabs组件页签默认显示在顶部,某些场景下您可能希望Tabs页签出现在底部或者侧边,您可以使用Tabs组件接口中的参数barPosition设置页签位置。此外页签显示位置还与vertical属性相关联,vertical属性用于设置页签的排列方向,当vertical的属性值为false(默认值)时页签横向排列,为true时页签纵向排列。

barPosition的值可以设置为BarPosition.Start(默认值)和BarPosition.End:

  • BarPosition.Start vertical属性方法设置为false(默认值)时,页签位于容器顶部。    
    1. Tabs({ barPosition: BarPosition.Start }) {
    2. ...
    3. }
    4. .vertical(false)
    5. .barWidth('100%')
    6. .barHeight(60)

    效果图如下:

    vertical属性方法设置为true时,页签位于容器左侧。

       
    1. Tabs({ barPosition: BarPosition.Start }) {
    2. ...
    3. }
    4. .vertical(true)
    5. .barWidth(100)
    6. .barHeight(200)

    效果图如下:

  • BarPosition.End

    vertical属性方法设置为false时,页签位于容器底部。

       
    1. Tabs({ barPosition: BarPosition.End }) {
    2. ...
    3. }
    4. .vertical(false)
    5. .barWidth('100%')
    6. .barHeight(60)

    效果图如下:

    vertical属性方法设置为true时,页签位于容器右侧。

       
    1. Tabs({ barPosition: BarPosition.End}) {
    2. ...
    3. }
    4. .vertical(true)
    5. .barWidth(100)
    6. .barHeight(200)

    效果图如下:

自定义TabBar样式

TabBar的默认显示效果如下所示:

往往开发过程中,UX给我们的设计效果可能并不是这样的,比如下面的这种底部页签效果:

TabContent的tabBar属性除了支持string类型,还支持使用@Builder装饰器修饰的函数。您可以使用@Builder装饰器,构造一个生成自定义TabBar样式的函数,实现上面的底部页签效果,示例代码如下:

   
  1. @Entry
  2. @Component
  3. struct TabsExample {
  4. @State currentIndex: number = 0;
  5. private tabsController: TabsController = new TabsController();
  6. @Builder TabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) {
  7. Column() {
  8. Image(this.currentIndex === targetIndex ? selectedImg : normalImg)
  9. .size({ width: 25, height: 25 })
  10. Text(title)
  11. .fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')
  12. }
  13. .width('100%')
  14. .height(50)
  15. .justifyContent(FlexAlign.Center)
  16. .onClick(() => {
  17. this.currentIndex = targetIndex;
  18. this.tabsController.changeIndex(this.currentIndex);
  19. })
  20. }
  21. build() {
  22. Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
  23. TabContent() {
  24. Column().width('100%').height('100%').backgroundColor('#00CB87')
  25. }
  26. .tabBar(this.TabBuilder('首页', 0, $r('app.media.home_selected'), $r('app.media.home_normal')))
  27. TabContent() {
  28. Column().width('100%').height('100%').backgroundColor('#007DFF')
  29. }
  30. .tabBar(this.TabBuilder('我的', 1, $r('app.media.mine_selected'), $r('app.media.mine_normal')))
  31. }
  32. .barWidth('100%')
  33. .barHeight(50)
  34. .onChange((index: number) => {
  35. this.currentIndex = index;
  36. })
  37. }
  38. }

示例代码中将barPosition的值设置为BarPosition.End,使页签显示在底部。使用@Builder修饰TabBuilder函数,生成由Image和Text组成的页签。同时也给Tabs组件设置了TabsController控制器,当点击某个页签时,调用changeIndex方法进行页签内容切换。

最后还需要给Tabs添加onChange事件,Tab页签切换后触发该事件,这样当我们左右滑动内容视图的时候,页签样式也会跟着改变。

参考

  • Tabs组件的更多属性和参数的使用,可以参考API:Tabs
  • @Builder装饰器的使用,可以参考:@Builder

 

 

标签:Tabs,100%,List,1fr,列表,Grid,组件
From: https://www.cnblogs.com/flyingsir/p/17978284

相关文章

  • CF1375B Neighbor Grid 题解
    题意简述给你一个$n$行$m$列的矩阵,要求你让这个矩阵是“完美”的。“完美”的定义如下:若当前的格子里是一个正整数$k$,那么与这个网格相邻(有公共边)的$k$个格子也必须有一个正整数。若当前的格子里是$0$,那么不受上述的限制。你可以对任意的一个格子加上$1$,次数......
  • Stream toList不能滥用以及与collect(Collectors.toList())的区别
    StreamtoList()返回的是只读List原则上不可修改,collect(Collectors.toList())默认返回的是ArrayList,可以增删改查1.背景在公司看到开发环境突然发现了UnsupportedOperationException报错,想到了不是自己throw的应该就是操作collection不当。发现的确是同事使用了类似stringL......
  • Java将字符串转为list数组
    将字符串转为list数组的实现方法概述在Java开发中,有时候我们需要将一个字符串转换为一个列表数组,以便对其中的元素进行操作和处理。本文将介绍一种常见的实现方法,并提供详细的步骤和示例代码来帮助你完成这个任务。实现步骤下面是实现将字符串转为list数组的一般步骤,你可以按照......
  • StringGrid1单元格内绘图
     varRect:Trect;beginRect:=bg.CellRect(4,3);bg.Canvas.Brush.Color:=clwhite;bg.Canvas.FillRect(rect);bg.Canvas.Draw(rect.Left+trunc((rect.Right-rect.Left-tx2.Width)/2)//单元格水平居中,rect.Top+tr......
  • 解决latex在使用lstlisting环境时的Undefined control sequence.错误
    错误描述,如题,Undefinedcontrolsequence.\begin{lstlisting},查了不少的资料,起始就是一句话,缺了宏包的导入。先看代码:\documentclass[11pt,a4paper]{ctexart}\usepackage{listings}%插入代码要引入的宏包\author{gsc}\title{sample}\lstset{columns=fixed,......
  • Sa-Token组件介绍
    个人博客:无奈何杨(wnhyang)个人语雀:wnhyang共享语雀:在线知识共享Github:wnhyang-Overview前文讲了Sa-Token介绍与SpringBoot环境下使用,但是satoken最重要的登录鉴权直接略过了,那这篇文章就开讲,......
  • Sa-Token组件介绍
    个人博客:无奈何杨(wnhyang)个人语雀:wnhyang共享语雀:在线知识共享Github:wnhyang-Overview前文讲了Sa-Token介绍与SpringBoot环境下使用,但是satoken最重要的登录鉴权直接略过了,那这篇文章就开讲,......
  • `/etc/apt/sources.list` 文件和 `/etc/apt/sources.list.d` 目录介绍
    Debian是一款广泛使用的Linux发行版,它使用apt软件包管理工具来处理软件包的安装、升级和删除。apt管理软件包的工作依赖于一个或多个软件仓库(repository),这些仓库定义在/etc/apt/sources.list文件以及/etc/apt/sources.list.d/目录下的文件中。/etc/apt/sources.list文......
  • 题解 [ABC186F] Rook on Grid
    【洛谷博客】有一点难度,但不多。题意一个\(H\timesW\)的地图上有\(M\)个障碍物。有一辆车在\((1,1)\),一次行动可以向下或向右移动任意格(不得穿过障碍物)。求这辆车在最多两次行动中可能到达多少个格子。分析车有四种选择:向右、向下、先向右再向下、先向下再向右。然......
  • 解决 Ant TreeSelect(树选择)组件可以使用键盘选中 disabled(已禁用)项的问题
    最近在使用AntDesignVue(V3.2.20)的TreeSelect组件时发现一个问题:tree-data中部分数据的disabled属性设置为了true,选项是“禁用”状态,无法通过鼠标点击选中,但是可以通过键盘↑↓键切换选项,按下Enter键选中。一开始还以为是bug,后来通过查阅文档和测试发现,该组件还......