一、支持分组列表
在列表中支持数据的分组展示,可以使列表显示结构清晰,查找方便,从而提高使用效率。分组列表在实际应用中十分常见,如下图所示联系人列表。
联系人分组列表
在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)
}
}
}