🎯 案例集合List:多级列表(商品分类)
🌍 案例集合List
🏷️ 效果图

📖 参考
🧩 拆解
- 多级列表滚动,头部组粘性(后续会增加高性能的方式)
javascript
import { HashMap } from "@kit.ArkTS";
/**
* 模拟数据
*/
const mockData: string[] = ['购物', '体育', '服装', '军事']
/**
* 多级列表数据
*/
const hasMap: HashMap<string, string[]> = new HashMap()
for (let i = 0; i < mockData.length; i++) {
hasMap.set(`${mockData[i]}_mock`, ['吃饭', '睡觉', '打豆豆'])
}
@Component
export struct MultiLevelList {
/**
* 当前选中的列表项下标
*/
@State curSelectIdx: number = 0
/**
* 列表构造器
*/
private listScroller: ListScroller = new ListScroller()
/**
* 列表组头部
* @param headerName
*/
@Builder
groupHeaderBuilder(headerName: string) {
Row() {
Text(headerName)
.fontSize(18)
.fontWeight(500)
}
.width('100%')
.height(56)
.padding({ left: 8 })
.backgroundColor('#F1F3F5')
}
/**
* 当前滑动或者点击的列表组项
* @param index
* @param operationType 操作类型
*/
curSelectItemChange(index: number, operationType: string) {
this.curSelectIdx = index
// 只有为左边点击label的时候才需滚动右侧列表
if (operationType === 'click') {
this.listScroller.scrollToIndex(index)
}
}
/**
* 最后一个列表组的下的内边距 (主要处理列表组滑动到底部)
* @param idx
* @returns
*/
private ednListItemGroupBottomPadding(idx: number) {
// 单个列表组的高度 (购物为例)
const itemGroupHeight = hasMap.get('购物_mock').length * 100
// 表头高度 * 2
const groupHeaderHeight = 56 * 2
return mockData.length - 1 === idx ? itemGroupHeight + groupHeaderHeight : 0
}
build() {
Row() {
Column() {
ForEach(mockData, (item: number, idx: number) => {
Text(item.toString())
.width('100%')
.height(56)
.fontSize(this.curSelectIdx === idx ? 20 : 16)
.textAlign(TextAlign.Center)
.fontColor(this.curSelectIdx === idx ? Color.Orange : Color.Black)
.opacity(this.curSelectIdx === idx ? 1 : 0.6)
.fontWeight(this.curSelectIdx === idx ? FontWeight.Bold : FontWeight.Normal)
.onClick(() => {
this.curSelectItemChange(idx, 'click')
})
}, (item: number) => item.toString())
}
.width(130)
.height('100%')
.backgroundColor('#4dfdddcb')
List({ scroller: this.listScroller }) {
ForEach(mockData, (item: string, idx: number) => {
ListItemGroup({ header: this.groupHeaderBuilder(item), space: 5 }) {
ForEach(hasMap.get(`${item}_mock`), (item: string) => {
ListItem() {
Text(item)
.height(100)
.width('100%')
.fontSize(20)
.borderRadius(10)
.textAlign(TextAlign.Center)
}
}, (item: number) => item.toString())
}
.padding({ bottom: this.ednListItemGroupBottomPadding(idx) })
}, (item: number) => item.toString())
}
.height('100%')
.layoutWeight(1)
.scrollBar(BarState.Off) // 关闭滚动条
.sticky(StickyStyle.Header) // 头部粘性
.edgeEffect(EdgeEffect.None) // 关闭滚动动效
.padding({ left: 8, right: 12 })
.onScrollIndex((idx: number) => {
this.curSelectItemChange(idx, 'swipe')
})
}
.width('100%')
.height('100%')
}
}
🌸🌼🌺