回复
03-万少带你精读鸿蒙codelabs——基于List组件实现二级联动效果 原创 精华
万少skr
发布于 2025-7-18 15:13
浏览
0收藏
03-万少带你精读鸿蒙codelabs——基于List组件实现二级联动效果
1. 功能介绍
本案例实现了一个课程分类展示系统,主要包含以下核心功能:
- 双栏联动布局(左侧分类导航栏+右侧课程列表)
- 分类切换时自动滚动到对应课程区域
- 滚动课程列表时自动同步分类选中状态
- 加载状态管理(显示Loading提示)
- 自适应屏幕布局

2. 关键组件
| 组件/装饰器 | 作用说明 |
|---|---|
| List | 构建可滚动列表容器(左侧分类列表和右侧课程列表) |
| ForEach | 循环渲染分类和课程条目 |
| @State | 管理组件状态(当前选中分类、数据加载状态) |
| @Builder | 构建可复用的UI片段(列表分组头部) |
| Scroller | 控制列表滚动行为 |
| ListItemGroup | 创建带分组的列表项 |
| StickyStyle.Header | 实现分组头部粘滞效果 |
3. 逻辑思路
主要交互流程说明:
- 初始化阶段:通过setTimeout模拟异步数据加载,设置500ms延迟(实际开发中应替换为真实API调用)
- 布局渲染:使用Row容器嵌套两个List实现双栏布局,左侧固定宽度,右侧自适应剩余空间
- 分类联动:
- 点击左侧分类时,通过
scrollToIndex控制右侧列表滚动 - 滚动右侧列表时,通过
onScrollIndex监听首项索引,反向控制左侧分类选中状态
- 点击左侧分类时,通过
- 性能优化:
- 使用
sticky属性实现分组头部粘滞 - 设置
scrollBar(BarState.Off)隐藏滚动条 - 通过
edgeEffect(EdgeEffect.None)禁用边缘发光效果
- 使用
示例图

初始化阶段
初始化阶段:通过setTimeout模拟异步数据加载,设置500ms延迟(实际开发中应替换为真实API调用)
currentClassify:当前选中的分类索引。requestSuccess:数据加载是否成功的状态标志。classifyList:分类数据列表。classifyScroller和scroller:用于控制分类列表和课程列表的滚动。
@State currentClassify: number = 0; // selected classify index.
@State requestSuccess: boolean = false; // is loading data.
private classifyList: Array<ClassifyModel> = [];
private classifyScroller: Scroller = new Scroller();
private scroller: Scroller = new Scroller();
aboutToAppear() {
// loading data.
setTimeout(() => {
this.classifyList = ClassifyViewModel.getLinkData();
this.requestSuccess = true;
}, Constants.LOADING_DURATION);
}
布局渲染
build方法用于构建页面的UI布局。- 当数据加载成功时,使用
List组件渲染分类列表和课程列表。 classifyList用于渲染分类列表,每个分类项使用ClassifyItem组件展示。classifyList中的每个分类项包含多个课程项,使用ListItemGroup组件按分类分组展示。- 当数据加载失败时,显示一个加载中的提示文本。
build() {
Row() {
if (this.requestSuccess) {
List({ scroller: this.classifyScroller }) {
ForEach(this.classifyList, (item: ClassifyModel, index?: number) => {
ListItem() {
ClassifyItem({
classifyName: item.classifyName,
isSelected: this.currentClassify === index,
onClickAction: () => {
if (index !== undefined) {
this.classifyChangeAction(index, true);
}
}
})
}
}, (item: ClassifyModel) => item.classifyName.toString() + this.currentClassify)
}
.height(Constants.FULL_PERCENT)
.width($r('app.float.classify_item_width'))
.backgroundColor($r('app.color.classify_background'))
.scrollBar(BarState.Off)
List({ scroller: this.scroller }) {
ForEach(this.classifyList, (classifyItem: ClassifyModel) => {
ListItemGroup({
header: this.ClassifyHeader(classifyItem.classifyName),
space: Constants.COURSE_ITEM_PADDING
}) {
ForEach(classifyItem.courseList, (courseItem: CourseModel) => {
ListItem() {
CourseItem({ itemStr: JSON.stringify(courseItem) })
}
}, (courseItem: CourseModel) => `${courseItem.courseId}`)
}
}, (item: ClassifyModel) => `${item.classifyId}`)
}
.height(Constants.FULL_PERCENT)
.width(Constants.FULL_PERCENT)
.padding({ left: $r('app.float.item_padding_left'), right: $r('app.float.course_item_padding') })
.sticky(StickyStyle.Header)
.layoutWeight(1)
.edgeEffect(EdgeEffect.None)
.onScrollIndex((start: number) => this.classifyChangeAction(start, false))
} else {
Text($r('app.string.loading'))
.fontFamily($r('app.string.hei_ti_medium'))
.textAlign(TextAlign.Center)
.height(Constants.FULL_PERCENT)
.width(Constants.FULL_PERCENT)
}
}
.backgroundColor($r('app.color.base_background'))
}
分类联动
- 点击左侧分类时,通过
scrollToIndex控制右侧列表滚动

- 滚动右侧列表时,通过
onScrollIndex监听首项索引,反向控制左侧分类选中状态

性能优化
- 使用
sticky属性实现分组头部粘滞 - 设置
scrollBar(BarState.Off)隐藏滚动条 - 通过
edgeEffect(EdgeEffect.None)禁用边缘发光效果
总结
如果你兴趣想要了解更多的开发细节和最新资讯,欢迎在评论区留言或者私信或者看我个人信息,可以加入技术交流群。
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
标签
赞
1
收藏
回复
相关推荐




















