1# 音乐专辑页 2 3 4本小节将以音乐专辑页为例,介绍如何使用自适应布局能力和响应式布局能力适配不同尺寸窗口。 5 6 7## 页面设计 8 9音乐专辑页的页面设计如下。 10 11 | sm | md | lg | 12| -------- | -------- | -------- | 13|  |  |  | 14 15同样观察音乐专辑的页面设计,不同断点下的页面设计有较多相似的地方。 16 17据此,我们可以将页面分拆为多个组成部分。 18 191. 标题栏 20 212. 歌单封面 22 233. 歌单列表 24 254. 播放控制栏 26 27 | sm | md | lg | 28| -------- | -------- | -------- | 29|  |  |  | 30 31 32## 标题栏 33 34不同断点下,标题栏始终只显示“返回按钮”、“歌单”以及“更多按钮”,但“歌单”与“更多按钮”之间的间距不同。由于不同断点下标题栏的背景色也有较大差异,因此无法使用拉伸能力实现,此场景更适合使用栅格实现。我们可以将标题栏划分为“返回按钮及歌单”和“更多按钮”两部分,这两部分在不同断点下占据的列数如下图所示。另外,还可以借助OnBreakpointChange事件,调整不同断点下这两部分的背景色。 35 36 | | sm | md | lg | 37| -------- | -------- | -------- | -------- | 38| 效果图 |  |  |  | 39| 栅格布局图 |  |  |  | 40 41 42```ts 43@Component 44export struct PlayListHeader { 45 @State moreBackgroundColor: Resource = $r('app.color.play_list_cover_background_color'); 46 build() { 47 GridRow() { 48 GridCol({span: {sm:6, md: 6, lg:4}}) { 49 Row() { 50 Image($r('app.media.ic_back')).height('24vp').width('24vp') 51 } 52 .width('100%') 53 .height('50vp') 54 .justifyContent(FlexAlign.Start) 55 .alignItems(VerticalAlign.Center) 56 .padding({left:$r('app.float.default_margin')}) 57 .backgroundColor($r('app.color.play_list_cover_background_color')) 58 } 59 GridCol({span: {sm:6, md: 6, lg:8}}) { 60 Row() { 61 Image($r('app.media.ic_add')).height('24vp').width('24vp') 62 } 63 .width('100%') 64 .height('50vp') 65 .justifyContent(FlexAlign.End) 66 .alignItems(VerticalAlign.Center) 67 .padding({right:$r('app.float.default_margin')}) 68 .backgroundColor(this.moreBackgroundColor) 69 } 70 }.onBreakpointChange((currentBreakpoint) => { 71 // 调整不同断点下返回按钮及歌单的背景色 72 if (currentBreakpoint === 'sm') { 73 this.moreBackgroundColor = $r('app.color.play_list_cover_background_color'); 74 } else { 75 this.moreBackgroundColor = $r('app.color.play_list_songs_background_color'); 76 } 77 }).height('100%').width('100%') 78 } 79} 80``` 81 82 83## 歌单封面 84 85歌单封面由封面图片、歌单介绍及常用操作三部分组成,这三部分的布局在md和lg断点下完全相同,但在sm断点下有较大差异。此场景同样可以用栅格实现。 86 87 | | sm | md/lg | 88| -------- | -------- | -------- | 89| 效果图 |  |  | 90| 栅格布局图 |  |  | 91 92 93```ts 94@Component 95export default struct PlayListCover { 96 ... 97 build() { 98 Column() { 99 // 借助栅格组件实现总体布局 100 GridRow() { 101 // 歌单图片 102 GridCol({ span: { sm: 4, md: 10 }, offset: { sm: 0, md: 1, lg: 1 } }) { 103 this.CoverImage() 104 } 105 // 歌单介绍 106 GridCol({ span: { sm: 8, md: 10 }, offset: { sm: 0, md: 2, lg: 2 } }) { 107 this.CoverIntroduction() 108 } 109 // 歌单操作 110 GridCol({ span: { sm: 12, md: 10 }, offset: { sm: 0, md: 2, lg: 2 } }) { 111 this.CoverOptions() 112 }.margin({ 113 top: this.currentBreakpoint === 'sm' ? 15 : 0, 114 bottom: this.currentBreakpoint === 'sm' ? 15 : 0 115 }) 116 } 117 .margin({ left: this.coverMargin, right: this.coverMargin }) 118 } 119 .height(this.currentBreakpoint === 'sm' ? this.coverHeight : '100%') 120 .padding({ top: this.currentBreakpoint === 'sm' ? 50 : 70 }) 121 } 122} 123``` 124 125 126## 歌单列表 127 128不同断点下,歌单列表的样式基本一致,但sm和md断点下是歌单列表是单列显示,lg断点下是双列显示。可以通过[List组件](../../reference/arkui-ts/ts-container-list.md)的lanes属性实现这一效果。 129 130 131```ts 132@Component 133export default struct PlayList { 134 ... 135 build() { 136 Column() { 137 this.PlayAll() 138 Scroll() { 139 List() { 140 LazyForEach(new MyDataSource(songList), item => { 141 ListItem() { 142 this.SongItem(item.title, item.label, item.singer) 143 } 144 }, item => item.id) 145 } 146 .width('100%') 147 .height('100%') 148 // 配置不同断点下歌单列表的列数 149 .lanes(this.currentBreakpoint === 'lg' ? 2 : 1) 150 } 151 .backgroundColor('#fff') 152 .margin({ top: 50, bottom: this.currentBreakpoint === 'sm' ? this.coverHeight : 0 }) 153 } 154 .padding({top: 50,bottom: 48}) 155 } 156} 157``` 158 159 160## 播放控制栏 161 162在不同断点下,播放控制栏显示的内容完全一致,唯一的区别是歌曲信息与播放控制按钮之间的间距有差异,这是典型的拉伸能力的使用场景。 163 164 165```ts 166@Component 167export struct MusicBar { 168 build() { 169 Row() { 170 Image($r('app.media.pic_album')).height(32).width(32).margin({right: 12}) 171 SongTitle() 172 // 通过Blank组件实现拉伸能力 173 Blank() 174 Image($r('app.media.icon_play')).height(26).width(26).margin({right: 16}) 175 Image($r('app.media.ic_next')).height(24).width(24).margin({right: 16}) 176 Image($r('app.media.ic_Music_list')).height(24).width(24) 177 } 178 .width('100%') 179 .height(48) 180 .backgroundColor('#D8D8D8') 181 .alignItems(VerticalAlign.Center) 182 .padding({left: 16, right: 16}) 183 } 184} 185``` 186 187 188## 运行效果 189 190将页面中的四部分组合在一起,即可显示完整的页面。 191 192其中歌单封面和歌单列表这两部分的相对位置,在sm断点下是上下排布,在md和lg断点下是左右排布,也可以用栅格来实现目标效果。 193 194 | | sm | md | lg | 195| -------- | -------- | -------- | -------- | 196| 效果图 |  |  |  | 197| 栅格布局图 |  |  |  | 198 199 200```ts 201@Component 202export default struct MusicContent { 203 ... 204 build() { 205 GridRow() { 206 // 歌单封面 207 GridCol({ span: { xs: 12, sm: 12, md: 6, lg: 4 } }) { 208 PlayListCover() 209 } 210 // 歌单列表 211 GridCol({ span: { xs: 12, sm: 12, md: 6, lg: 8 } }) { 212 PlayList() 213 } 214 } 215 .height('100%') 216 } 217} 218``` 219 220最后将页面各部分组合在一起即可。 221 222 223```ts 224@Entry 225@Component 226struct Index { 227 build() { 228 Column() { 229 // 标题栏 230 PlayListHeader() 231 // 歌单 232 MusicContent() 233 // 播放控制栏 234 MusicBar() 235 }.width('100%').height('100%') 236 } 237} 238``` 239 240音乐专辑页面的运行效果如下所示。 241 242 | sm | md | lg | 243| -------- | -------- | -------- | 244|  |  |  | 245 246## 相关实例 247 248针对音乐专辑应用,有以下相关实例可供参考: 249 250- [典型页面场景:音乐专辑页(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/SuperFeature/MultiDeviceAppDev/MusicAlbum) 251 252