暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

147.[HarmonyOS NEXT 实战案例八 :List系列] 粘性头部列表基础篇

原创 若城 2025-06-29
99

[HarmonyOS NEXT 实战案例八 :List系列] 粘性头部列表基础篇

项目已开源,开源地址: https://gitcode.com/nutpi/HarmonyosNextCaseStudyTutorial , 欢迎fork & star

效果演示

粘性头部列表是移动应用中常见的UI模式,它允许列表的分组标题在滚动时保持可见,提供更好的导航体验。本教程将详细讲解如何在HarmonyOS NEXT中实现一个功能完善的粘性头部列表,以音乐播放器应用为例,展示如何创建按专辑分组的音乐列表。

一、粘性头部列表概述

粘性头部列表是List组件与ListItemGroup组件结合使用的一种应用场景,它具有以下特点:

  1. 分组显示:内容按照一定规则分组显示
  2. 粘性头部:当滚动时,当前分组的头部会固定在屏幕顶部
  3. 层级结构:通过视觉设计清晰地表达内容的层级关系
  4. 导航便捷:用户可以快速了解当前浏览的内容类别

在HarmonyOS NEXT中,粘性头部列表主要通过以下组件实现:

  • List:基础列表容器
  • ListItemGroup:列表项分组容器
  • ListItem:列表项
  • sticky属性:控制粘性效果

二、数据模型设计

首先,我们需要定义音乐数据的接口:

// 歌曲接口 interface SongsType { title: string, duration: string, isLiked: boolean } // 专辑接口 interface MusicType { album: string, artist: string, cover: Resource, year: string, songs: SongsType[] } // 当前播放歌曲接口 interface CurrentSongType { album: string, title: string }

这些接口定义了我们的数据结构:

  • SongsType:定义歌曲的基本属性(标题、时长、是否喜欢)
  • MusicType:定义专辑的基本属性(专辑名、艺术家、封面、年份、歌曲列表)
  • CurrentSongType:定义当前播放歌曲的信息(所属专辑、歌曲标题)

然后,我们创建示例音乐数据:

private musicData: MusicType[] = [ { album: '星辰大海', artist: '周杰伦', cover: $r('app.media.big25'), year: '2023', songs: [ { title: '星辰大海', duration: '4:25', isLiked: true }, { title: '城市之光', duration: '3:48', isLiked: false }, // 更多歌曲... ] }, // 更多专辑... ]

三、状态管理

为了管理当前播放的歌曲状态,我们定义以下状态变量:

// 当前播放歌曲 @State currentSong: CurrentSongType | null = null

这个状态变量用于跟踪当前正在播放的歌曲,初始值为null表示没有歌曲在播放。

四、核心功能实现

1. 播放歌曲功能

// 播放歌曲 playSong(album: string, title: string) { this.currentSong = { album, title } }

这个方法用于设置当前播放的歌曲,接收专辑名和歌曲标题作为参数。

2. 专辑头部构建器

// 构建专辑头部 @Builder AlbumHeader(album: string, artist: string, cover: Resource, year: string) { Row() { // 专辑封面 Image(cover) .width(60) .height(60) .borderRadius(8) .margin({ right: 16 }) // 专辑信息 Column() { Text(album) .fontSize(18) .fontWeight(FontWeight.Bold) Text(artist) .fontSize(16) .fontColor('#666666') .margin({ top: 4 }) Text(year) .fontSize(14) .fontColor('#999999') .margin({ top: 2 }) } .alignItems(HorizontalAlign.Start) } .width('100%') .backgroundColor('#FFFFFF') .padding({ left: 16, right: 16, top: 12, bottom: 12 }) }

这个Builder用于构建专辑头部的UI,包括专辑封面和专辑信息(专辑名、艺术家、年份)。

五、UI构建

1. 整体布局

build() { Stack({ alignContent: Alignment.Bottom }) { Column() { // 标题栏 Row() { /* ... */ } // 音乐列表 List() { /* ... */ } } .width('100%') .height('100%') .backgroundColor('#FFFFFF') // 底部播放控制栏(当有歌曲播放时显示) if (this.currentSong) { Row() { /* ... */ } } } .width('100%') .height('100%') }

整体布局使用Stack容器,包含两个主要部分:

  1. 主内容区(Column容器):包含标题栏和音乐列表
  2. 底部播放控制栏:仅在有歌曲播放时显示

2. 标题栏实现

// 标题栏 Row() { Text('音乐') .fontSize(24) .fontWeight(FontWeight.Bold) Blank() Image($r('app.media.music_icon')) .width(24) .height(24) .margin({ right: 16 }) } .width('100%') .height(56) .padding({ left: 16, right: 16 }) .backgroundColor('#F1F3F5')

标题栏包含应用标题和一个音乐图标。

3. 音乐列表实现

// 音乐列表 List() { ForEach(this.musicData, (albumData: MusicType) => { ListItemGroup({ header: this.AlbumHeader(albumData.album, albumData.artist, albumData.cover, albumData.year), space: 0 }) { ForEach(albumData.songs, (song: SongsType) => { ListItem() { Row() { // 歌曲信息 Column() { Text(song.title) .fontSize(16) .fontWeight(FontWeight.Medium) Text(song.duration) .fontSize(14) .fontColor('#666666') .margin({ top: 4 }) } .alignItems(HorizontalAlign.Start) .layoutWeight(1) // 喜欢按钮 Image(song.isLiked ? $r('app.media.heart_filled') : $r('app.media.heart_outline')) .width(24) .height(24) .margin({ right: 16 }) // 更多按钮 Image($r('app.media.dcc_health_icon')) .width(24) .height(24) } .width('100%') .padding({ left: 16, right: 16, top: 12, bottom: 12 }) .onClick(() => this.playSong(albumData.album, song.title)) .backgroundColor( this.currentSong?.album === albumData.album && this.currentSong?.title === song.title ? '#F0F7FF' : '#FFFFFF' ) } .height(64) }) } }) } .sticky(StickyStyle.Header) // 设置粘性头部 .width('100%') .layoutWeight(1) .divider({ // 设置分割线 strokeWidth: 1, color: '#E5E5E5', startMargin: 16, endMargin: 16 })

音乐列表的关键点:

  1. 使用ForEach遍历专辑数据,为每个专辑创建一个ListItemGroup
  2. 使用自定义的AlbumHeader构建器作为ListItemGroup的头部
  3. 在每个ListItemGroup中,再次使用ForEach遍历歌曲数据,为每首歌曲创建一个ListItem
  4. List组件设置sticky(StickyStyle.Header)属性,启用粘性头部功能
  5. 为歌曲项添加点击事件,点击时调用playSong方法
  6. 根据当前播放歌曲状态,设置不同的背景色以提供视觉反馈

4. 底部播放控制栏实现

// 底部播放控制栏(当有歌曲播放时显示) if (this.currentSong) { Row() { // 当前播放歌曲信息 Column() { Text(this.currentSong.title) .fontSize(16) .fontWeight(FontWeight.Medium) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) Text(this.currentSong.album) .fontSize(14) .fontColor('#666666') .margin({ top: 2 }) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) } .alignItems(HorizontalAlign.Start) .layoutWeight(1) // 播放控制按钮 Row({ space: 16 }) { Image($r('app.media.active_weather_icon')) .width(24) .height(24) Image($r('app.media.mobile_calculator_ap')) .width(32) .height(32) Image($r('app.media.note_icon')) .width(24) .height(24) } } .width('100%') .height(72) .padding({ left: 16, right: 16 }) .backgroundColor('#FFFFFF') .borderColor('#E5E5E5') .borderWidth({ top: 1 }) }

底部播放控制栏仅在有歌曲播放时显示,包含当前播放歌曲信息和播放控制按钮。

六、关键技术点分析

1. 粘性头部的实现

粘性头部功能主要通过List组件的sticky属性实现:

.sticky(StickyStyle.Header) // 设置粘性头部

这个属性使得ListItemGroup的头部在滚动时保持可见,直到下一个分组的头部出现。

2. ListItemGroup的使用

ListItemGroup组件用于创建分组列表,它接收一个header参数作为分组的头部:

ListItemGroup({ header: this.AlbumHeader(albumData.album, albumData.artist, albumData.cover, albumData.year), space: 0 })

header参数可以是一个自定义的Builder,这里我们使用AlbumHeader构建器来创建专辑头部。

3. 条件渲染

我们使用条件渲染来控制底部播放控制栏的显示:

if (this.currentSong) { Row() { /* ... */ } }

只有当currentSong不为null时,才会显示底部播放控制栏。

4. 状态反馈

为了提供良好的用户体验,我们为当前播放的歌曲提供视觉反馈:

.backgroundColor( this.currentSong?.album === albumData.album && this.currentSong?.title === song.title ? '#F0F7FF' : '#FFFFFF' )

当歌曲正在播放时,其背景色会变为浅蓝色,以便用户快速识别当前播放的歌曲。

七、代码结构与样式设置

组件部分 主要功能 样式设置
Stack 整体容器 宽高100%,底部对齐
Column 主内容区 宽高100%,白色背景
标题栏Row 显示应用标题和图标 高56px,左右内边距16px,浅灰背景
List 显示音乐列表 宽100%,弹性布局权重1,粘性头部,带分割线
ListItemGroup 专辑分组 自定义头部,间距0
ListItem 单首歌曲 高64px,点击事件,条件背景色
底部Row 播放控制栏 高72px,左右内边距16px,白色背景,顶部边框

八、粘性头部列表的应用场景

粘性头部列表适用于多种应用场景,包括但不限于:

  1. 音乐播放器:按专辑、艺术家或流派分组显示歌曲
  2. 联系人列表:按字母或组织分组显示联系人
  3. 设置页面:按功能类别分组显示设置项
  4. 电商应用:按类别分组显示商品
  5. 日历应用:按月份或周分组显示事件
  6. 新闻应用:按日期或主题分组显示新闻

九、总结

本教程详细讲解了如何在HarmonyOS NEXT中实现一个功能完善的粘性头部列表,
通过本教程,你应该能够掌握HarmonyOS NEXT中粘性头部列表的基本实现方法,并能够应用到自己的项目中。在进阶篇中,我们将探讨如何增强粘性头部列表的功能,如自定义粘性效果、动画过渡、交互优化等高级特性。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论