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

发布于:2025-02-15 ⋅ 阅读:(33) ⋅ 点赞:(0)

一、支持分组列表

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

联系人分组列表

在这里插入图片描述

在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)
    }
  }
}

网站公告

今日签到

点亮在社区的每一天
去签到