HarmonyOS 鸿蒙Next中List组件如何实现“吸顶”效果?
HarmonyOS 鸿蒙Next中List组件如何实现“吸顶”效果? 商品分类列表中,每个分类标题滚动到顶部时应固定。ArkUI 有 sticky 属性吗?
ListItemGroup支持通过sticky设置吸顶效果。点击查看设置吸顶/吸底示例。
参考下这个案例呢:如何实现List组件所有分组上滑吸顶效果及触底提示-行业常见问题-公共关键技术方案-场景化知识 - 华为HarmonyOS开发者或者 HarmonyOS_Samples/NestedList - 码云 - 开源中国
更多关于HarmonyOS 鸿蒙Next中List组件如何实现“吸顶”效果?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
List组件的sticky属性配合ListItemGroup组件使用,用于设置ListItemGroup中的头部组件是否呈现吸顶效果或者尾部组件是否呈现吸底效果。
sticky属性可以设置为 StickyStyle.Header | StickyStyle.Footer 以同时支持header吸顶和footer吸底。从API version 20开始,sticky属性也可以设置为StickyStyle.BOTH,以同时支持header吸顶和footer吸底。
官方示例:
import { util } from '@kit.ArkTS';
class Contact {
public key: string = util.generateRandomUUID(true);
public name: string | Resource;
public icon: Resource;
constructor(name: string | Resource, icon: Resource) {
this.name = name;
this.icon = icon;
}
}
class ContactsGroup {
public title: string = '';
public contacts: Array<object> | null = null;
public key: string = '';
}
export class ContactsGroupDataSource implements IDataSource {
private list: object[] = [];
constructor(list: object[]) {
this.list = list;
}
totalCount(): number {
return this.list.length;
}
getData(index: number): object {
return this.list[index];
}
registerDataChangeListener(listener: DataChangeListener): void {
}
unregisterDataChangeListener(listener: DataChangeListener): void {
}
}
export let contactsGroups: object[] = [
{
title: 'A',
contacts: [
// app.string.contacts_A_one 资源文件中的value值为'艾佳',app.media.iconA为自定义资源
new Contact($r('app.string.contacts_A_one'), $r('app.media.iconA')),
// app.string.contacts_A_two 资源文件中的value值为'安安',app.media.iconB为自定义资源
new Contact($r('app.string.contacts_A_two'), $r('app.media.iconB')),
// app.media.iconC为自定义资源
new Contact('Angela', $r('app.media.iconC')),
],
key: util.generateRandomUUID(true)
} as ContactsGroup,
{
title: 'B',
contacts: [
// app.string.contacts_B_one 资源文件中的value值为'白叶',app.media.iconD为自定义资源
new Contact($r('app.string.contacts_B_one'), $r('app.media.iconD')),
// app.string.contacts_B_three 资源文件中的value值为'伯明',app.media.iconE为自定义资源
new Contact($r('app.string.contacts_B_three'), $r('app.media.iconE'))
],
key: util.generateRandomUUID(true)
} as ContactsGroup
];
export let contactsGroupsDataSource: ContactsGroupDataSource = new ContactsGroupDataSource(contactsGroups);
@Entry
@Component
export struct StickyHeaderList {
// 定义分组联系人数据集合contactsGroups数组
@Builder
itemHead(text: string) {
// 列表分组的头部组件,对应联系人分组A、B等位置的组件
Text(text)
.fontSize(20)
.backgroundColor('#fff1f3f5')
.width('100%')
.padding(5)
}
build() {
// ...
List() {
// 懒加载ListItemGroup,contactsGroups为多个分组联系人contacts和标题title的数据集合
LazyForEach(contactsGroupsDataSource, (itemGroup: ContactsGroup) => {
ListItemGroup({ header: this.itemHead(itemGroup.title) }) {
// 循环渲染ListItem
if (itemGroup.contacts) {
LazyForEach(new ContactsGroupDataSource(itemGroup.contacts), (item: Contact) => {
ListItem() {
Row() {
Image(item.icon).width(40).height(40).margin(10)
Text(item.name).fontSize(20)
}.width('100%').justifyContent(FlexAlign.Start)
}
}, (item: Contact) => JSON.stringify(item))
}
}
}, (itemGroup: ContactsGroup) => JSON.stringify(itemGroup))
}
.sticky(StickyStyle.Header) // 设置吸顶,实现粘性标题效果
// ...
}
}
在 ArkUI 中,List 组件本身没有直接的 sticky 属性,但可以试一下通过 ListItemGroup 的 header 属性配合 sticky: StickyStyle.Header 来实现吸顶效果。
去翻翻ListItemGroup的api文档,
在HarmonyOS Next中,使用List组件实现吸顶效果,可通过设置sticky属性实现。将List的子组件ListItemGroup的sticky属性设置为StickyStyle.Header,即可让该组在滚动时固定在顶部。此属性支持Header和Footer两种模式,分别对应顶部和底部固定。
在HarmonyOS Next的ArkUI中,可以通过List组件的sticky属性实现分类标题的“吸顶”效果。该属性属于ListItemGroup组件,而非ListItem。
核心实现方式如下:
- 数据结构:建议将列表数据组织为二维数组,外层数组代表分组,内层数组代表每个分组下的子项。
- 使用
ListItemGroup:在List组件内,使用ListItemGroup包裹每个分类(组)。关键点是为ListItemGroup设置sticky属性。 - 设置
sticky属性:sticky属性的取值类型为StickyStyle,常用值为:StickyStyle.Header:仅组头吸顶(默认值)。StickyStyle.None:不吸顶。
示例代码结构:
@Entry
@Component
struct Index {
// 示例:二维数组数据,[分组][子项]
private data: string[][] = [...];
build() {
Column() {
List({ space: 10 }) {
ForEach(this.data, (itemGroup: string[], groupIndex: number) => {
ListItemGroup({ header: this.GroupHeader(groupIndex) }) {
ForEach(itemGroup, (item: string, itemIndex: number) => {
ListItem() {
// 渲染每个子项的内容
Text(item)
.fontSize(16)
.padding(10)
}
}, (item: string) => item)
}
.sticky(StickyStyle.Header) // 关键:设置该分组头部吸顶
}, (itemGroup: string[]) => JSON.stringify(itemGroup))
}
}
}
// 分组头部组件
@Builder
GroupHeader(index: number) {
Text(`分类 ${index + 1}`)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.backgroundColor(Color.White)
.width('100%')
.padding(10)
}
}
关键说明:
sticky属性直接作用于ListItemGroup,设置后该分组的头部(即header属性构建的组件)在滚动时会自动吸顶。- 吸顶效果是系统原生行为,性能较好,无需手动计算滚动位置。
- 当前
StickyStyle主要支持Header吸顶。如需更复杂的滚动联动效果(如部分内容吸顶后推挤上一个吸顶标题),需要结合Scroll与position属性进行自定义实现。
因此,针对商品分类列表的需求,使用List + ListItemGroup并设置sticky(StickyStyle.Header)是最简洁直接的实现方案。


