当前位置: 首页 > news >正文

鸿蒙开发中的List组件详解

目录

引言

1.List组件基础

2.List接口参数

 1.space

2.initialIndex

3.scroller

3.ListView的属性        

1.listDirection

2.lanes

3.divider

4.scrollBar

4.布局与约束

5.ListItem生命周期

1.使用ForEach创建ListItem

2.使用LazyForEach创建ListItem        

3.使用Repeat创建ListItem

1.使用virtualScroll

2.不使用virtualScroll

6.List的使用场景

1. 最简单的List

2. 自定义组件

3. 滚动控制

高级特性

1. 分组列表

2. 懒加载

3. 下拉刷新与上拉加载

性能优化技巧

常见问题解决

结语


引言

        在鸿蒙(HarmonyOS)应用开发中,List组件是最常用的UI组件之一,用于展示垂直滚动的列表数据。本文将详细介绍List组件的特性、使用方法以及一些实用技巧。

1.List组件基础

        列表是一种复杂的容器,当列表项达到一定数量,内容超过屏幕大小时,可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集,例如图片和文本。在列表中显示数据集合是许多应用程序中的常见要求(如通讯录、音乐列表、购物清单等)。

        List是鸿蒙OS中用于展示垂直滚动列表的容器组件,具有以下特点:

  • 高性能的列表渲染

  • 支持大数据量的流畅滚动

  • 内置多种布局和交互效果

  • 支持分组和多种列表项样式

2.List接口参数

    当我们创建 List 的时候,有三个默认可选参数,分别是 space、initialIndex、scroller。

    我们分别看看他们的属性。

 1.space

        space 用来设置子组件主轴方向的间隔。

 图1.space属性

2.initialIndex

        设置当前 List初次加载的时候,初始 item 的索引值。

图2.修改初次加载显示的数据元素下标

3.scroller

        可以滚动组件的控制器。

        我们可以调用scroll的相关方法处理List。

        例如我们可以通过下面的代码把List滚动到底部

          Button("滚动到底部").onClick(()=>{this.scroller.scrollEdge(Edge.Bottom)})

3.ListView的属性        

1.listDirection

        设置List组件的排列方向。

        listDirection是Axis类型的枚举,定义如下:

declare enum Axis {
    Vertical,
    Horizontal
}        

        默认值为Axis.Vertical,方向为纵向。

        Axis.Horizontal方向为横向。

2.lanes

        设置List组件的布局列数或者行数。

        lanes是鸿蒙(HarmonyOS)中List组件的一个重要属性,用于控制列表在水平方向上的布局方式,特别适用于需要多列布局的场景。通过设置lanes属性,可以让List组件中的列表项以网格形式排列,而不是传统的单列垂直排列。

3.divider

        设置ListItem分割线样式,默认无分割线。

4.scrollBar

        设置滚动条状态。

        BarState.AutoAuto:按需显示

        BarState.AutoOff:不显示

        BarState.AutoOn:常驻显示

4.布局与约束

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

        如下图所示,在垂直列表中,List按垂直方向自动排列ListItemGroup或ListItem。

ListItemGroup用于列表数据的分组展示,其子组件也是ListItem。ListItem表示单个列表项,可以包含单个子组件。

图3.List、ListItemGroup和ListItem组件关系

5.ListItem生命周期

1.使用ForEach创建ListItem

        List组件创建时,所有ListItem将会被创建。显示区域内的ListItem在首帧进行布局,预加载范围内的ListItem在空闲时完成布局。预加载范围之外的ListItem仅创建ListItem自身,ListItem其内部的子组件不会被创建。

        当List组件滑动时,进入预加载及显示区域的ListItem将会创建其内部的子组件并完成布局,而滑出预加载及显示区域的ListItem将不会被销毁。

图4.ForEach创建ListItem

2.使用LazyForEach创建ListItem        

        List组件创建时,显示区域中的ListItem会被创建与布局。预加载范围内的ListItem在空闲时创建与布局,但是不会被挂载到组件树上。预加载范围外的ListItem则不会被创建。

        当List组件滑动时,进入预加载及显示区域的ListItem将被创建与布局,创建ListItem过程中,若ListItem内部如果包含@Reusable标记的自定义组件,则会优先从缓存池中复用。滑出预加载及显示区域的ListItem将被销毁,其内部若含@Reusable标记的自定义组件,则会被回收并加入缓存池。

图5.LazyForEach创建ListItem的生命周期

3.使用Repeat创建ListItem

1.使用virtualScroll

        List组件创建时,显示区域内的ListItem将被创建和布局。预加载范围内的ListItem在空闲时创建和布局,并且挂载至组件树上。预加载范围外的ListItem则不会被创建。

        当List组件滑动时,进入预加载及显示区域的ListItem,将从缓存池中获取ListItem并复用及布局,若缓存池中无ListItem,则会新创建并布局。滑出预加载及显示区域的ListItem会将被回收至缓存池。

        图6.Repeat使用virtualScroll创建ListItem的生命周期

2.不使用virtualScroll

        List组件创建时,所有ListItem均被创建。显示区域内的ListItem在首帧完成布局,预加载范围内的ListItem在空闲时完成布局。预加载范围外的ListItem不会进行布局。

        当List组件滑动时,进入预加载及显示区域的ListItem将进行布局。滑出预加载及显示区域的ListItem不会销毁。

图7.Repeat不使用virtualScroll创建ListItem的生命周期

1.listDirection

1.listDirection

// 示例代码:基本List使用
import { List, ListItem } from '@ohos/arkui';@Entry
@Component
struct MyList {private data: string[] = ['苹果', '香蕉', '橙子', '葡萄', '西瓜']build() {Column() {List({ space: 20 }) {ForEach(this.data, (item: string) => {ListItem() {Text(item).fontSize(20).margin({ left: 15 })}})}.width('100%').height('100%')}}
}

6.List的使用场景

1. 最简单的List

        在最简单的列表形式中,List静态地创建其列表项ListItem的内容。

        当我们ListView的ListItem只有一个组件的时候,我们使用下面的代码即可实现一个简单的列表。

@Entry
@Component
struct CityList {build() {NavDestination(){List() {ListItem(){Text('北京').fontSize(24)}ListItem(){Text('上海').fontSize(24)}ListItem(){Text('杭州').fontSize(24)}}    .backgroundColor('#FFF1F3F5').alignListItem(ListItemAlign.Center)}.title("List实现城市列表")}
}

        效果图如下:

图8.最简单的List

@State private messages: Message[] = [{ id: 1, content: '你好鸿蒙' },{ id: 2, content: 'List组件学习' },// 更多数据...
];List() {ForEach(this.messages, (item: Message) => {ListItem() {Text(item.content)}})
}

2. 自定义组件

        因此,如果ListItem是由多个组件元素组成的,则需要将这多个元素组合到一个容器组件内或组成一个自定义组件。

        例如我们要实现一个通讯录联系人页面:

图9.联系人列表

        如上图所示,联系人列表的列表项中,每个联系人都有头像和名称。此时,需要将Image和Text封装到一个Row容器内。

List() {ListItem() {Row() {// app.media.iconE为自定义资源Image($r('app.media.iconE')).width(40).height(40).margin(10)Text('小明').fontSize(20)}}ListItem() {Row() {// app.media.iconF为自定义资源Image($r('app.media.iconF')).width(40).height(40).margin(10)Text('小红').fontSize(20)}}
}

3. 滚动控制

private scroller: Scroller = new Scroller()List({ scroller: this.scroller }) {// 列表内容
}// 滚动到指定位置
this.scroller.scrollTo({ x: 0, y: 100 })

高级特性

1. 分组列表

List() {ForEach(this.groupData, (group: Group) => {ListItemGroup({ header: this.GroupHeader(group.name) }) {ForEach(group.items, (item: Item) => {ListItem() {Text(item.name)}})}})
}

2. 懒加载

List() {LazyForEach(this.dataSource, (item: Item) => {ListItem() {Text(item.name)}})
}

3. 下拉刷新与上拉加载

List({ controller: this.listController }) {// 列表内容
}
.onRefresh(() => {// 下拉刷新逻辑
})
.onReachEnd(() => {// 上拉加载更多
})

性能优化技巧

  1. 复用列表项​:确保ListItem的结构尽可能简单,提高复用率

  2. 避免复杂计算​:在列表渲染中避免复杂的计算和频繁的UI更新

  3. 使用LazyForEach​:对于大数据集,使用LazyForEach代替ForEach

  4. 图片懒加载​:列表中的图片使用懒加载技术

常见问题解决

  1. 列表滚动卡顿​:

    • 检查是否有过多的UI更新

    • 确保使用了正确的数据绑定方式

    • 考虑分页加载数据

  2. 列表项点击无响应​:

    • 检查是否添加了.onClick事件

    • 确保没有其他组件遮挡了点击区域

  3. 列表数据显示异常​:

    • 检查数据源是否正确更新

    • 确认ForEach或LazyForEach的key值唯一且稳定

结语

List组件是鸿蒙应用开发中不可或缺的重要组件,掌握其使用方法和优化技巧对于构建流畅的用户界面至关重要。通过本文的介绍,希望您能更高效地使用List组件,为您的鸿蒙应用带来更好的用户体验。

在实际开发中,建议多参考鸿蒙官方文档和示例代码,不断实践和优化您的列表实现。

http://www.dtcms.com/a/343643.html

相关文章:

  • spring之自定义拦截器:HandlerInterceptor 控制请求生死权
  • Java微服务开发:从入门到精通
  • 证书只是手段:把学习变成可复用能力的路线图
  • FPGA 在情绪识别领域的护理应用(三)
  • gRPC 与 HTTP 性能对比分析
  • C++浅拷贝和深拷贝区别
  • 【华为OD-C卷-019 对称字符串 100分(python、java、c++、js、c)】
  • 【Transient-Free 3DGS】delayed densification + coarse to fine增加GS的鲁棒性
  • 【GaussDB】使用gdb定位GaussDB编译package报错
  • 图像中物体计数:基于YOLOv5的目标检测与分割技术
  • 智能编程中的智能体与 AI 应用:概念、架构与实践场景
  • Effective C++ 条款54:熟悉标准库
  • typescript常用命令选项
  • Function Call与MCP:大模型能力扩展的两条路径对比
  • CF每日4题(1500-1700)
  • 谈谈架构的内容
  • 前端别名与环境变量使用
  • AI 赋能教育变革:机遇、实践与展望
  • 基于随机森林的红酒分类与特征重要性分析
  • MySQL高可用之MHA实战
  • 【高等数学】第九章 多元函数微分法及其应用——第九节 二元函数的泰勒公式
  • 北京JAVA基础面试30天打卡14
  • 【51单片机学习】AT24C02(I2C)、DS18B20(单总线)、LCD1602(液晶显示屏)
  • AI 在医疗领域的应用与挑战
  • 带宽评估(三)lossbase_v2
  • 测试面试题第二篇:专项业务领域(上)
  • 嵌入式学习day33-网络-c/s
  • 有符号和无符号的区别
  • DAG的DP(UVA437 巴比伦塔 The Tower of Babylon)
  • Java—— 网络编程