鸿蒙开发-UI-布局-列表

news2024/12/24 2:15:37

鸿蒙开发-UI-布局

鸿蒙开发-UI-布局-线性布局

鸿蒙开发-UI-布局-层叠布局

鸿蒙开发-UI-布局-弹性布局

鸿蒙开发-UI-布局-相对布局

鸿蒙开发-UI-布局-格栅布局

文章目录

前言

一、基本概念

二、开发布局

1.布局约束

2.开发布局

三、应用特性

1.列表数据显示

2.列表数据迭代

3.列表样式自定义

4.分组列表

5.添加粘性标题

6.控制滚动位置

7.列表响应

8.列表项添加标记

9.下垃刷新上拉加载

10.列表编辑

11.长列表处理

总结


前言

上文详细学习常见布局方式-栅格布局,学习栅格布局中列数控制,子组件的排列方向已经间距控制,也学习了栅格容器子组件占用列数以及偏移和顺序的定义方式。本文将学习List布局

一、基本概念

列表是一种复杂的容器,当列表项达到一定数量,内容超过屏幕大小时,可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集,例如图片和文本。

二、开发布局

1.布局约束

列表作为一种容器,会自动按其滚动方向排列子组件,向列表中添加组件或从列表中移除组件会重新排列子组件。

在垂直列表中,List按垂直方向自动排列ListItemGroup或ListItem。ListItemGroup用于列表数据的分组展示,其子组件也是ListItem。ListItem表示单个列表项,可以包含单个子组件

List、ListItemGroup和ListItem组件关系

List的子组件必须是ListItemGroup或ListItem,ListItem和ListItemGroup必须配合List来使用。

列表的主轴方向:子组件列的排列方向,也是列表的滚动方向

列表的交叉轴方向:垂直于主轴的轴,其方向与主轴方向相互垂直

约束1:List组件主轴方向没有设置尺寸

1. 当List子组件主轴方向总尺寸小于List的父组件尺寸时,List主轴方向尺寸自动适应子组件的总尺寸

A: List的父组件(高200); B: List组件(list所有子组件主轴方向高150小于list父组件高200,自适应150); C: List的所有子组件(高150)

2. 子组件主轴方向总尺寸超过List父组件尺寸时,List主轴方向尺寸适应List的父组件尺寸

A: List的父组件(高200); B: List组件(list所有子组件主轴方向高300大于list父组件高200,自适应200); C: List的所有子组件(高300)

约束2:List组件主轴或交叉轴方向设置了尺寸,则其对应方向上的尺寸为设置值

约束3:List组件交叉轴方向在没有设置尺寸时,其尺寸默认自适应父组件尺寸

2.开发布局

1. 设置主轴方向

List组件主轴默认是垂直方向。若是水平滚动列表场景,将List的listDirection属性设置为Axis.Horizontal。

List() {
  ...
}
.listDirection(Axis.Horizontal)

2. 设置交叉轴布局

List组件的交叉轴布局可以通过lanes和alignListItem属性进行设置,lanes属性用于确定交叉轴排列的列表项数量,alignListItem用于设置子组件在交叉轴方向的对齐方式。

List组件的lanes属性通常用于在不同尺寸的设备自适应构建不同行数或列数的列表。lanes属性的取值类型有两种

lanes:number。 如下代码表示垂直列表分成2列显示,默认为1列显示

List() {
  ...
}
.lanes(2)

lanes:LengthConstrain。List组件的尺寸自适应决定行或列数。如下代码表示,当List组件宽度为300vp时,由于minLength为200vp,此时列表为一列。当List组件宽度变化至400vp时,符合两倍的minLength,则此时列表自适应为两列。

List() {
  ...
}
.lanes({ minLength: 200, maxLength: 300 })

List组件的alignListItem属性用于设置子组件在交叉轴方向的对齐方式

alignListItem:ListItemAlign.?默认值ListItemAlign.Start,列表项在列表交叉轴方向上默认按首部对齐。如下代码表示,垂直列表在交叉方向上子组件居中对齐

List() {
  ...
}
.alignListItem(ListItemAlign.Center)

三、应用特性

1.列表数据显示

列表视图垂直或水平显示项目集合,在行或列超出屏幕时提供滚动功能,使其适合显示大型数据集合

List组件+列表项ListItem组件组合 显示列表数据

@Component
struct CityList {
  build() {
    List() {
      ListItem() {
        Text('北京').fontSize(24)
      }

      ListItem() {
        Text('杭州').fontSize(24)
      }

      ListItem() {
        Text('上海').fontSize(24)
      }
    }
    .backgroundColor('#FFF1F3F5')
    .alignListItem(ListItemAlign.Center)
  }
}

ListItem中只能有一个根节点组件。因此,若列表项是由多个组件元素组成的,则需要将这多个元素组合到一个容器组件内或组成一个自定义组件

2.列表数据迭代

常用使用场景,通过数据集合动态地创建列表,使用ForEach循环渲染迭代获取数据源中数据,并在迭代过程中创建相应组件,如下代码示例,List组件通过ForEach循环渲染address数据源数组,每次迭代创建一个Row容器组件,Row容器组件中创建一个Text组件


@Entry
@Component
struct SimpleTest {
  private address = [
    'address1',
    'address2',
    ...
  ]

  build() {
    List() {
      ForEach(this.address , (item: string) => {
        ListItem() {
          Row() {
            Text(item).fontSize(20)
          }
          .width('100%')
          .justifyContent(FlexAlign.Start)
        }
      }, item => item)
    }
    .width('100%')
  }
}

3.列表样式自定义

1.设置内容间距

在初始化列表时,如需在列表项之间添加间距,可以使用space参数。如下代码所示,在每个列表项之间沿主轴方向添加10vp的间距

List({ space: 10 }) {
  ...
}

2.添加分割线

List提供了divider属性用于给列表项之间添加分隔线。在设置divider属性时,可以通过strokeWidth和color属性设置分隔线的粗细和颜色。startMargin和endMargin属性分别用于设置分隔线距离列表侧边起始端的距离和距离列表侧边结束端的距离。

List() {
  ...
}
.divider({
  strokeWidth: 1,
  startMargin: 60,
  endMargin: 10,
  color: '#ffe9f0f0'
})

如上代码表示从距离列表侧边起始端60vp开始到距离结束端10vp的位置,画一条粗细为1vp的分割线

3.添加滚动条

当列表项高度(宽度)超出屏幕高度(宽度)时,列表可以沿垂直(水平)方向滚动。在页面内容很多时,若用户需快速定位,可拖拽滚动条。

List组件可通过scrollBar属性控制列表滚动条的显示。

scrollBar的取值类型为BarState,当取值为BarState.Auto表示按需显示滚动条。当触摸到滚动条区域时显示控件,可上下拖拽滚动条快速浏览内容,拖拽时会变粗。若不进行任何操作,2秒后滚动条自动消失。

List() {
  ...
}
.scrollBar(BarState.Auto)

4.分组列表

在列表中支持数据的分组展示,在List组件中使用ListItemGroup对项目进行分组,可以构建二维列表。在List组件中可以直接使用一个或者多个ListItemGroup组件,ListItemGroup的宽度默认充满List组件。在初始化ListItemGroup时,可通过header参数设置列表分组的头部组件

@Component
struct ContactsList {
  ...
  
  @Builder itemHead(text: string) {
    // 列表分组的头部组件,对应联系人分组A、B等位置的组件
    Text(text)
      .fontSize(20)
      .backgroundColor('#fff1f3f5')
      .width('100%')
      .padding(5)
  }

  build() {
    List() {
      ListItemGroup({ header: this.itemHead('A') }) {
        // 循环渲染分组A的ListItem
        ...
      }
      ...

      ListItemGroup({ header: this.itemHead('B') }) {
        // 循环渲染分组B的ListItem
        ...
      }
      ...
    }
  }
}

如上代码所示,List组件定义两个ListItemGroup组件,每个ListItemGroup组件通过header参数定义组件的头部UI,为了实现UI渲染逻辑的复用,通过@Builder装饰器定义公用的UI渲染逻辑,通过传参方式,实现UI渲染逻辑复用。

5.添加粘性标题

粘性标题是一种常见的标题模式,常用于定位字母列表的头部元素。

List组件的sticky属性配合ListItemGroup组件使用,用于设置ListItemGroup中的头部组件是否呈现吸顶效果或者尾部组件是否呈现吸底效果。

sticky:StickyStyle。

StickyStyle.Header即可实现列表的粘性标题效果。

吸底效果:可以通过footer参数初始化ListItemGroup的底部组件,并将sticky属性设置为StickyStyle.Footer。

@Component
struct ContactsList {
  // 定义分组联系人数据集合contactsGroups数组
  ...
 
  @Builder itemHead(text: string) {
    // 列表分组的头部组件,对应联系人分组A、B等位置的组件
    Text(text)
      .fontSize(20)
      .backgroundColor('#fff1f3f5')
      .width('100%')
      .padding(5)
  }

  build() {
    List() {
      // 循环渲染ListItemGroup,contactsGroups为多个分组联系人contacts和标题title的数据集合
      ForEach(this.contactsGroups, item => {
        ListItemGroup({ header: this.itemHead(item.title) }) {
          // 循环渲染ListItem
          ForEach(item.contacts, contact => {
            ListItem() {
              ...
            }
          }, item => item.key)
        }
        ...
      })
    }
    .sticky(StickyStyle.Header)  // 设置吸顶,实现粘性标题效果
  }
}

6.控制滚动位置

控制滚动位置在实际应用中十分常见,例如当新闻页列表项数量庞大,用户滚动列表到一定位置时,希望快速滚动到列表底部或返回列表顶部。此时,可以通过控制滚动位置来实现列表的快速定位

// step1:创建一个Scroller的对象listScroller
private listScroller: Scroller = new Scroller();

Stack({ alignContent: Alignment.BottomEnd }) {
  //step2: 将listScroller用于初始化List组件的scroller参数,完成listScroller与列表的绑定。
  List({ space: 20, scroller: this.listScroller }) {
    ...
  }
  ...

  Button() {
    ...
  }
  .onClick(() => {
    // 点击按钮时,指定跳转位置,返回列表顶部
    this.listScroller.scrollToIndex(0)
  })
  ...
}

如上代码所示,定义层叠容器组件Stack,其子元素List组件和Button组件,Button组件浮在List组件上方,通过Button点击事件触发Scroll对象的scrollToIndex方法调用,实现List组件滚动

7.列表响应

1.响应滚动位置

使用场景:需要监听列表的滚动位置变化并作出响应,例如在联系人列表滚动时,如果跨越了不同字母开头的分组,则侧边字母索引栏也需要更新到对应的字母位置

...
const alphabets = ['#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
  'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];

@Entry
@Component
struct ContactsList {
  @State selectedIndex: number = 0;
  private listScroller: Scroller = new Scroller();
  ...

  build() {
    Stack({ alignContent: Alignment.End }) {
      List({ scroller: this.listScroller }) {
        ...
      }
      .onScrollIndex((firstIndex: number) => {
          this.selectedIndex = firstIndex
        // 根据列表滚动到的索引值,重新计算对应联系人索引栏的位置this.selectedIndex
        ...
      })
      ...

      // 字母表索引组件
      AlphabetIndexer({ arrayValue: alphabets, selected: 0 })
        .selected(this.selectedIndex)
      ...
    }
  }
}

如以上代码所示,计算索引值时,ListItemGroup作为一个整体占一个索引值,不计算ListItemGroup内部ListItem的索引值,字母索引组件的index与ListItemGroup组件index一一对应

2.响应列表项侧滑

侧滑菜单在许多应用中都很常见。例如,通讯类应用通常会给消息列表提供侧滑删除功能,即用户可以通过向左侧滑列表的某一项,再点击删除按钮删除消息

ListItem的swipeAction属性可用于实现列表项的左右滑动功能。swipeAction属性方法初始化时有必填参数SwipeActionOptions,其中,start参数表示设置列表项右滑时起始端滑出的组件,end参数表示设置列表项左滑时尾端滑出的组件。

@Entry
@Component
struct MessageList {
  @State messages: object[] = [
    // 初始化消息列表数据
    ...
  ];

  @Builder itemEnd(index: number) {
    // 侧滑后尾端出现的组件
    Button({ type: ButtonType.Circle }) {
      Image($r('app.media.ic_public_delete_filled'))
        .width(20)
        .height(20)
    }
    .onClick(() => {
      this.messages.splice(index, 1);
    })
    ...
  }

  build() {
    ...
      List() {
        ForEach(this.messages, (item, index) => {
          ListItem() {
            ...
          }
          .swipeAction({ end: this.itemEnd.bind(this, index) }) // 设置侧滑属性
        }, item => item.id.toString())
      }
    ...
  }
}

如以上代码所示,在消息列表中,end参数表示设置ListItem左滑时尾端划出自定义组件,即删除按钮。在初始化end方法时,将滑动列表项的索引传入删除按钮组件,当用户点击删除按钮时,可以根据索引值来删除列表项对应的数据,从而实现侧滑删除功能。

8.列表项添加标记

添加标记是一种无干扰性且直观的方法,用于显示通知或将注意力集中到应用内的某个区域,例如,当消息列表接收到新消息时,通常对应的联系人头像的右上方会出现标记,提示有若干条未读消息

在ListItem中使用Badge组件可实现给列表项添加标记功能。Badge是可以附加在单个组件上用于信息标记的容器组件。

9.下垃刷新上拉加载

页面的下拉刷新与上拉加载功能在移动应用中十分常见,例如,新闻页面的内容刷新和加载。这两种操作的原理都是通过响应用户的触摸事件,在顶部或者底部显示一个刷新或加载视图,完成后再将此视图隐藏

10.列表编辑

列表的编辑模式常见于待办事项管理、文件管理、备忘录的记录管理等应用场景。在列表的编辑模式下,新增和删除列表项是最基础的功能,其核心是对列表项对应的数据集合进行数据添加和删除

11.长列表处理

循环渲染适用于短列表,当构建具有大量列表项的长列表时,如果直接采用循环渲染方式,会一次性加载所有的列表元素,会导致页面启动时间过长,影响用户体验。因此,使用数据懒加载(LazyForEach)方式实现按需迭代加载数据,从而提升列表性能

当使用懒加载方式渲染列表时,为了更好的列表滚动体验,减少列表滑动时出现白块,List组件提供了cachedCount参数用于设置列表项缓存数,只在懒加载LazyForEach中生效

List() {
  LazyForEach(this.dataSource, item => {
    ListItem() {
      ...
    }
  })
}.cachedCount(3)

已垂直列表为例:
若懒加载是用于ListItem,当列表为单列模式时,会在List显示的ListItem前后各缓存cachedCount个ListItem;若是多列模式下,会在List显示的ListItem前后各缓存cachedCount*列数个ListItem。

若懒加载是用于ListItemGroup,无论单列模式还是多列模式,都是在List显示的ListItem前后各缓存cachedCount个ListItemGroup。

注:cachedCount的增加会增大UI的CPU、内存开销。使用时需要根据实际情况,综合性能和用户体验进行调整。列表使用数据懒加载时,除了显示区域的列表项和前后缓存的列表项,其他列表项会被销毁。


总结

本文学习了List布局容器的基本概念,了解List布局容器的相关约束,详细学习了List容器组件数据展示(包括迭代展示)、列表样式定义(分割线)、数据分组展示等相关常见使用场景的应用方法,下文将学习网格布局容器相关知识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1404963.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

啥,ui叫我做一个移动端好看的轮播--异形的Slide

先看效果,得实现两边的缩放和无线滚动 实现方法 我的基础架构是 next.jsswiper 下载swiper包 yarn add swiper下载后在页面中引用 import { useEffect, useState } from "react"; import styles from "./index.module.css"; import Image from "n…

leetcode—图 岛屿数量

岛屿数量 给你一个由 1(陆地)和 0(水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外,你可以假设该网…

C语言 小明喝饮料

题目&#xff1a;喝汽水&#xff0c;1瓶汽水1元&#xff0c;2个空瓶可以换汽水&#xff0c;给n元&#xff0c;可以喝多少汽水//理论问题&#xff0c;请勿模仿-^- #include <stdio.h> int main() {int n,ret,i;scanf("%d", &n);ret n;while (n>1){ret …

JavaEE:多线程(2):线程状态,线程安全

目录 线程状态 线程安全 线程不安全 加锁 互斥性 可重入 死锁 死锁的解决方法 Java标准库中线程安全类 内存可见性引起的线程安全问题 等待和通知机制 线程饿死 wait notify 线程状态 就绪&#xff1a;线程随时可以去CPU上执行&#xff0c;也包含在CPU上执行的…

csdn发布文章审核一直未通过解决办法

搞了很久的confluence&#xff0c;踩了很多坑终于弄好了&#xff0c;却一直显示审核不通过&#xff0c;给笔记一顿狂改还是不通过&#xff0c;一直说是版权问题就很让人起疑&#xff0c;最后问了客服才知道&#xff0c;现在开始查版权问题&#xff0c;所以我给confluence笔记中…

【开发日记】换掉Nginx,使用HAProxy作为反向代理服务器

HAProxy&#xff0c;全称为 "High Availability Proxy"&#xff0c;是一款开源的、高性能的负载均衡器和代理服务器。主要用于改善应用程序的可用性、可靠性和性能。 与大众熟知的Nginx相比各有优缺点&#xff0c;如果你需要的是一个Web服务器&#xff0c;还是首选N…

GitHub README-Template.md - README.md 模板

GitHub README-Template.md - README.md 模板 1. README-Template.md 预览模式2. README-Template.md 编辑模式References A template to make good README.md. https://gist.github.com/PurpleBooth/109311bb0361f32d87a2 1. README-Template.md 预览模式 2. README-Templat…

AI对比:ChatGPT和文心一言的区别和差异

目录 一、ChatGPT和文心一言大模型的对比分析 1.1 二者训练的数据情况分析 1.2 训练大模型数据规模和参数对比 1.3 二者3.5版本大模型对比总结 二、ChatGPT和文心一言功能对比分析 2.1 二者产品提供的功能情况分析 2.2 测试一下各种功能的特性 2.2.1 文本创作能力 2.2…

websocket服务端本地部署

文章目录 1. Java 服务端demo环境2. 在pom文件引入第三包封装的netty框架maven坐标3. 创建服务端,以接口模式调用,方便外部调用4. 启动服务,出现以下信息表示启动成功,暴露端口默认99995. 创建隧道映射内网端口6. 查看状态->在线隧道,复制所创建隧道的公网地址加端口号7. 以…

Samtec微波、毫米波连接器系统实现卓越性能

【摘要/前言】 在IMS 2023展会上&#xff0c;Samtec 的展台展示了各种尖端产品和技术。其中之一是各种微波、毫米波连接器系统&#xff0c;这些系统性能卓越&#xff0c;令人印象深刻。 Samtec射频设计与仿真工程经理Michael Griesi向我们介绍了演示过程和结果。 【Demo演示】…

Qt5.12.0 与 VS2017 在 .pro文件转.vcxproj文件

一、参考资料 stackoverflow qt - How to generate .sln/.vcproj using qmake - Stack Overflowhttps://stackoverflow.com/questions/2339832/how-to-generate-sln-vcproj-using-qmake?answertabtrending#tab-topqt - 如何使用 qmake 生成 .sln/.vcproj - IT工具网 (coder.wo…

综合小型气象观测站

TH-QC12随着科技的发展&#xff0c;气象观测站已经变得越来越普遍。无论是大规模的国家级气象站&#xff0c;还是小型的气象观测站&#xff0c;它们都为我们的生活和生产提供了重要的气象数据。 综合小型气象观测站&#xff0c;顾名思义&#xff0c;它集成了多种气象观测设备&a…

如何搭建一个短视频社区?这篇文章告诉你

短视频社区是随着手机拍摄和社交媒体的普及而兴起的一种社区形式。 短视频社区通过提供用户生成的短视频内容&#xff0c;并与其他用户互动和分享&#xff0c;为用户提供了一个展示自己才华和创造力的平台。当前已经成为全球范围内的热门社交媒体形式&#xff0c;市场情况非常…

Apache Zeppelin结合Apache Airflow使用1

Apache Zeppelin结合Apache Airflow使用1 文章目录 Apache Zeppelin结合Apache Airflow使用1前言一、安装Airflow二、使用步骤1.目标2.编写DAG2.加载、执行DAG 总结 前言 之前学了Zeppelin的使用&#xff0c;今天开始结合Airflow串任务。 Apache Airflow和Apache Zeppelin是两…

DAY07_SpringBoot—用法整合MyBatis

目录 1 SpringBoot 用法1.1 环境切换1.1.1 业务需求1.1.2 多环境编辑 1.2 热部署1.2.1 需求说明1.2.2 引入jar包1.2.3 配置IDEA环境 2 SpringBoot整合Mybatis2.1 导入数据库2.2 创建SpringBoot项目2.2.1 创建项目2.2.2 生成POM.xml文件如下2.2.3 Mavenjar包作用范围2.2.4 数据源…

面试经验分享 | 工控安全研究员

本文由掌控安全学院 - 徐浩洋 投稿 笔试 进程注入有几种简单描述一下? Windows异常分发流程。 Windows下反调试和反反调试的手段。 使用分页机制下虚拟地址怎么翻译为物理地址。 符号延时加载(DeferredSymbolLoading)的原理? 漏洞触发流程是怎么样的,怎么定位触发点如何进行…

服务器数据恢复—服务器进水导致阵列中磁盘同时掉线的数据恢复案例

服务器数据恢复环境&#xff1a; 数台服务器数台存储阵列柜&#xff0c;共上百块硬盘&#xff0c;划分了数十组lun。 服务器故障&检测&#xff1a; 外部因素导致服务器进水&#xff0c;进水服务器中一组阵列内的所有硬盘同时掉线。 北亚数据恢复工程师到达现场后发现机房内…

OpenMP和MPI环境配置

目录 OpenMP和MPI环境配置OpenMP环境配置MPI环境配置&#xff08;Windows&#xff09;MPI环境配置&#xff08;Ubuntu&#xff09; 参考资料 OpenMP和MPI环境配置 OpenMP环境配置 首先创建项目&#xff0c;选择C 控制台应用。 选择项目&#xff0c;属性。 在C/C —— 语言中&…

老师家访的目的是什么

家访&#xff0c;对于老师来说&#xff0c;是工作中必不可少的一部分。有人会问&#xff0c;老师家访的目的是什么呢&#xff1f;是为了了解学生的家庭情况&#xff0c;还是为了和家长建立良好的沟通关系&#xff1f;其实&#xff0c;老师家访的目的远不止于此。 老师家访是为…

【MySQL】计算日期是当前月份的第几周

力扣题 1、题目地址 2993. 发生在周五的交易 I 2、模拟表 表&#xff1a;Purchases Column NameTypeuser_idintpurchase_datedateamount_spendint (user_id, purchase_date, amount_spend) 是该表的主键(具有唯一值的列)。purchase_date 的范围从 2023 年 11 月 1 日到 2…