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

HarmonyOS:使用List实现分组列表(包含粘性标题)

一、支持分组列表

在列表中支持数据的分组展示,可以使列表显示结构清晰,查找方便,从而提高使用效率。分组列表在实际应用中十分常见,如下图所示联系人列表。

联系人分组列表

在这里插入图片描述

在List组件中使用ListItemGroup对项目进行分组,可以构建二维列表。

在List组件中可以直接使用一个或者多个ListItemGroup组件,ListItemGroup的宽度默认充满List组件。在初始化ListItemGroup时,可通过header参数设置列表分组的头部组件。

@Entry
@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
      }
    }
  }
}

如果多个ListItemGroup结构类似,可以将多个分组的数据组成数组,然后使用ForEach对多个分组进行循环渲染。例如在联系人列表中,将每个分组的联系人数据contacts和对应分组的标题title数据进行组合,定义为数组contactsGroups。然后在ForEach中对contactsGroups进行循环渲染,即可实现多个分组的联系人列表。可参考添加粘性标题示例代码。

二、添加粘性标题

粘性标题是一种常见的标题模式,常用于定位字母列表的头部元素。如下图所示,在联系人列表中滚动A部分时,B部分开始的头部元素始终处于A的下方。而在开始滚动B部分时,B的头部会固定在屏幕顶部,直到所有B的项均完成滚动后,才被后面的头部替代。

粘性标题不仅有助于阐明列表中数据的表示形式和用途,还可以帮助用户在大量信息中进行数据定位,从而避免用户在标题所在的表的顶部与感兴趣区域之间反复滚动。

粘性标题–联系人分组列表

在这里插入图片描述

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

通过给List组件设置sticky属性为StickyStyle.Header,即可实现列表的粘性标题效果。如果需要支持吸底效果,可以通过footer参数初始化ListItemGroup的底部组件,并将sticky属性设置为StickyStyle.Footer。

三、完整示例代码

TestContactsList.ets

import { util } from '@kit.ArkTS'

class Contact {
  contactkey: string = util.generateRandomUUID(true);
  name: string;
  avatar: Resource;

  constructor(name: string, avatar: Resource) {
    this.name = name;
    this.avatar = avatar;
  }
}

class ContactsGroup {
  title: string = '';
  key: string = '';
  contacts: Array<object> | null = null;
}

let contactsGroups: object[] = [
  {
    title: 'A',
    key: util.generateRandomUUID(true),
    contacts: [
      new Contact('Andy', $r('app.media.circle')),
      new Contact('安沃', $r('app.media.circle')),
      new Contact('昂科1', $r('app.media.circle')),
      new Contact('昂科2', $r('app.media.circle')),
      new Contact('昂科3', $r('app.media.circle')),
    ]
  } as ContactsGroup,
  {
    title: 'B',
    key: util.generateRandomUUID(true),
    contacts: [
      new Contact('Ben', $r('app.media.circle')),
      new Contact('蹦高', $r('app.media.circle')),
      new Contact('巴掌1', $r('app.media.circle')),
      new Contact('巴掌2', $r('app.media.circle')),
    ]
  } as ContactsGroup,
  {
    title: 'C',
    key: util.generateRandomUUID(true),
    contacts: [
      new Contact('ChenL', $r('app.media.circle')),
      new Contact('成才', $r('app.media.circle')),
      new Contact('程程1', $r('app.media.circle')),
      new Contact('程程2', $r('app.media.circle')),
      new Contact('程程3', $r('app.media.circle')),
      new Contact('程程4', $r('app.media.circle')),
    ]
  } as ContactsGroup,
  {
    title: 'D',
    key: util.generateRandomUUID(true),
    contacts: [
      new Contact('DIba', $r('app.media.circle')),
      new Contact('迪迪1', $r('app.media.circle')),
      new Contact('迪迪2', $r('app.media.circle')),
      new Contact('迪迪3', $r('app.media.circle')),
    ]
  } as ContactsGroup
]

@Component
struct ItemContact {
  @Prop item: Contact

  build() {
    Row({ space: 10 }) {
      Image(this.item.avatar)
        .width('50vp')
        .height('50vp')
      Text(this.item.name)
        .fontSize(20)
        .fontColor(Color.Black)
        .ellipsisMode(EllipsisMode.END)
        .maxLines(1)
    }
    .width('100%')
    .margin({ top: 16, bottom: 10 })
    .padding({ left: 16 })
    .alignItems(VerticalAlign.Center)
    .justifyContent(FlexAlign.Start)
  }
}

@Entry
@Component
struct TestContactsList {
  @State message: string = '分组列表';

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

  build() {
    Column({ space: 10 }) {
      Text(this.message)
        .id('TestContactsListHelloWorld')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)

      List() {
        ForEach(contactsGroups, (itemGroup: ContactsGroup) => {
          ListItemGroup({ header: this.itemHead(itemGroup.title) }) {
            if (itemGroup.contacts) {
              ForEach(itemGroup.contacts, (contact: Contact) => {
                ListItem() {
                  ItemContact({ item: contact })
                }
              }, (item: Contact) => JSON.stringify(item))
            }
          }
        }, (itemGroup: ContactsGroup) => JSON.stringify(itemGroup))
      }
      .sticky(StickyStyle.Header)
      .scrollBar(BarState.Auto)
    }
  }
}

相关文章:

  • 算法18(力扣136)只出现一次的数字
  • Huggingface加载阅读理解任务数据集至本地
  • 深度学习项目--基于RNN的阿尔茨海默病诊断研究(pytorch实现)
  • Node.js技术原理分析系列——Node.js调试能力分析
  • pycharm ai插件
  • 【人工智能】如何选择合适的大语言模型,是能否提高工作效率的关键!!!
  • 【学术投稿-第四届智能电网和绿色能源国际学术会议(ICSGGE 2025)】CSS基本选择器详解:掌握基础,轻松布局网页
  • ML.NET库学习006:成人人口普查数据分析与分类预测
  • AI 编程私有化部署,在使用 cline 时,可能无法避免私隐的泄漏问题
  • Kotlin 优雅的接口实现
  • 如何通过MDM高效管理企业的Android平板?
  • [每日动态]科技新闻每日信息差2025年2月14日
  • 景联文科技:以精准标注赋能AI未来,打造高质量数据基石
  • 数据结构--八大排序算法
  • 2025年单片机毕业设计选题物联网计算机电气电子通信类
  • 开发美颜相机录制视频时,对于音频数据的处理
  • ECharts鼠标悬浮提示框数字设置鼠标在左侧时 tooltip 显示到右侧,鼠标在右侧时 tooltip 显示到左侧。
  • OpenCV机器学习(3)期望最大化(Expectation-Maximization, EM)算法cv::ml::EM
  • 深入解析 vLLM:高性能 LLM 服务框架的架构之美(上)
  • 深入探讨复变函数:核心概念与关键应用
  • 开题报告旅游网站开发/热搜榜排名前十
  • 做网站比较大的公司/西安楼市最新房价
  • 鹤壁哪里做网站/做整站优化
  • 做调查的网站‘/搜狗收录查询
  • 如何建立一个网站论坛/企业查询宝
  • 基金网站建设/最好的bt种子搜索引擎