核心内容摘要
Ray 集群多用户资源隔离实践
专辑详情页是展示专辑完整信息的页面用户可以查看专辑封面、歌手信息、发行时间以及专辑内的所有歌曲。
本篇文章将详细介绍如何使用CustomScrollView和Sliver组件实现一个美观实用的专辑详情页面。
页面基础结构专辑详情页使用StatelessWidget因为页面状态相对简单。
importpackage:flutter/material.dart;importpackage:get/get.dart;classAlbumDetailPageextendsStatelessWidget{finalint id;constAlbumDetailPage({super.key,requiredthis.id});页面通过构造函数接收专辑ID用于加载对应的专辑数据。
如果需要管理收藏状态等可以改为StatefulWidget。
CustomScrollView结构使用CustomScrollView组合多个Sliver组件。
overrideWidgetbuild(BuildContextcontext){returnScaffold(body:CustomScrollView(slivers:[_buildSliverAppBar(),_buildActionBar(),_buildSongList(),],),);}CustomScrollView允许将多个Sliver组件组合在一起滚动。
页面包含三个部分可折叠的头部、操作按钮栏和歌曲列表。
SliverAppBar头部设计SliverAppBar实现可折叠的专辑信息头部。
Widget_buildSliverAppBar(){returnSliverAppBar(expandedHeight:300,pinned:true,flexibleSpace:FlexibleSpaceBar(background:Container(decoration:BoxDecoration(gradient:LinearGradient(begin:Alignment.topCenter,end:Alignment.bottomCenter,colors:[Colors.primaries[id%Colors.primaries.length],Colors.black,],),),expandedHeight设置展开高度为300pinned为true让AppBar收起后固定在顶部。
背景使用渐变色从专辑主题色过渡到黑色。
专辑封面与信息头部展示专辑封面和基本信息。
child:SafeArea(child:Padding(padding:constEdgeInsets.all(
,child:Row(crossAxisAlignment:CrossAxisAlignment.end,children:[Container(width:150,height:150,decoration:BoxDecoration(borderRadius:BorderRadius.circular(
,color:Colors.white24,boxShadow:[BoxShadow(color:Colors.black.withOpacity(
0.
,blurRadius:20,offset:constOffset(0,
,),],),child:constIcon(Icons.album,size:70,color:Colors.white
,),封面使用圆角矩形添加阴影增加立体感。
实际项目中会使用网络图片替换Icon。
专辑文字信息封面右侧显示专辑名称、歌手和发行时间。
constSizedBox(width:
,Expanded(child:Column(mainAxisAlignment:MainAxisAlignment.end,crossAxisAlignment:CrossAxisAlignment.start,children:[Text(专辑${id1},style:constTextStyle(color:Colors.white,fontSize:22,fontWeight:FontWeight.bold,),),constSizedBox(height:
,GestureDetector(onTap:()Get.toNamed(/artist/$id),child:constText(歌手名称,style:TextStyle(color:Colors.white
,),),constSizedBox(height:
,Text(发行时间:${2020id%5}年,style:constTextStyle(color:Colors.white54,fontSize:
,),],),),],),),),),),);}歌手名称可点击跳转到歌手详情页。
使用不同透明度的白色区分信息层级。
操作按钮栏操作栏包含播放全部、收藏和分享按钮。
Widget_buildActionBar(){returnSliverToBoxAdapter(child:Padding(padding:constEdgeInsets.all(
,child:Row(children:[Expanded(child:ElevatedButton.icon(onPressed:()_playAll(),icon:constIcon(Icons.play_arrow),label:constText(播放全部),style:ElevatedButton.styleFrom(backgroundColor:constColor(0xFFE91E
,foregroundColor:Colors.white,padding:constEdgeInsets.symmetric(vertical:
,shape:RoundedRectangleBorder(borderRadius:BorderRadius.circular(
,),),),),constSizedBox(width:
,IconButton(icon:constIcon(Icons.favorite_border),onPressed:()_toggleFavorite(),),IconButton(icon:constIcon(Icons.share),onPressed:()_shareAlbum(),),],),),);}播放全部按钮使用主题色占据大部分宽度。
收藏和分享使用图标按钮节省空间。
歌曲列表使用SliverList构建歌曲列表。
Widget_buildSongList(){returnSliverList(delegate:SliverChildBuilderDelegate((context,index)_buildSongItem(index),childCount:10,),);}SliverChildBuilderDelegate实现懒加载只构建可见的列表项。
childCount设置歌曲总数。
歌曲列表项每首歌曲显示序号、名称、歌手和时长。
Widget_buildSongItem(int index){returnListTile(leading:Container(width:32,alignment:Alignment.center,child:Text(${index1},style:TextStyle(color:index3?constColor(0xFFE91E
:Colors.grey,fontWeight:index3?FontWeight.bold:FontWeight.normal,),),),title:Text(歌曲${index1},maxLines:1,overflow:TextOverflow.ellipsis,),subtitle:constText(歌手名称,style:TextStyle(color:Colors.grey,fontSize:
,),trailing:Row(mainAxisSize:MainAxisSize.min,children:[constText(04:32,style:TextStyle(color:Colors.grey,fontSize:
,),IconButton(icon:constIcon(Icons.more_vert,color:Colors.grey),onPressed:()_showSongOptions(index),),],),onTap:()_playSong(index),);}前三首歌曲的序号使用主题色突出显示。
trailing包含时长和更多操作按钮。
歌曲操作菜单点击更多按钮显示操作菜单。
void_showSongOptions(int index){Get.bottomSheet(Container(decoration:constBoxDecoration(color:Color(0xFF1E1E1E),borderRadius:BorderRadius.vertical(top:Radius.circular(
),),child:Column(mainAxisSize:MainAxisSize.min,children:[ListTile(leading:Container(width:50,height:50,decoration:BoxDecoration(borderRadius:BorderRadius.circular(
,color:Colors.grey.withOpacity(
0.
,),child:constIcon(Icons.music_note,color:Colors.white
,),title:Text(歌曲${index1}),subtitle:constText(歌手名称,style:TextStyle(color:Colors.grey)),),constDivider(),ListTile(leading:constIcon(Icons.play_circle_outline),title:constText(下一首播放),onTap:()Get.back(),),ListTile(leading:constIcon(Icons.playlist_add),title:constText(添加到歌单),onTap:()Get.back(),),ListTile(leading:constIcon(Icons.download_outlined),title:constText(下载),onTap:()Get.back(),),ListTile(leading:constIcon(Icons.share_outlined),title:constText(分享),onTap:()Get.back(),),constSizedBox(height:
,],),),);}菜单顶部显示歌曲信息下方是各种操作选项。
这种设计让用户在操作前可以确认选中的歌曲。
播放全部方法点击播放全部按钮后播放专辑内所有歌曲。
void_playAll(){Get.toNamed(/player,arguments:{albumId:id,startIndex:0,});Get.snackbar(播放,开始播放专辑,snackPosition:SnackPosition.BOTTOM,);}跳转到播放器页面传递专辑ID和起始索引。
播放单曲方法点击单曲后从该歌曲开始播放。
void_playSong(int index){Get.toNamed(/player,arguments:{albumId:id,startIndex:index,});}传递起始索引播放器会从该歌曲开始播放专辑。
收藏专辑方法收藏按钮的点击处理。
void_toggleFavorite(){// 实际项目中需要调用API并更新状态Get.snackbar(收藏,已添加到收藏,snackPosition:SnackPosition.BOTTOM,);}实际项目中需要调用API更新收藏状态并使用状态管理更新UI。
分享专辑方法分享按钮的点击处理。
void_shareAlbum(){Get.bottomSheet(Container(decoration:constBoxDecoration(color:Color(0xFF1E1E1E),borderRadius:BorderRadius.vertical(top:Radius.circular(
),),child:Column(mainAxisSize:MainAxisSize.min,children:[constPadding(padding:EdgeInsets.all(
,child:Text(分享到,style:TextStyle(fontSize:18,fontWeight:FontWeight.bold)),),Row(mainAxisAlignment:MainAxisAlignment.spaceEvenly,children:[_buildShareItem(Icons.chat,微信),_buildShareItem(Icons.people,朋友圈),_buildShareItem(Icons.message,微博),_buildShareItem(Icons.link,复制链接),],),constSizedBox(height:
,],),),);}Widget_buildShareItem(IconDataicon,Stringlabel){returnGestureDetector(onTap:(){Get.back();Get.snackbar(分享,分享到$label);},child:Column(children:[Container(width:50,height:50,decoration:BoxDecoration(color:Colors.grey.withOpacity(
0.
,shape:BoxShape.circle,),child:Icon(icon,color:Colors.white
,),constSizedBox(height:
,Text(label,style:constTextStyle(fontSize:
),],),);}分享菜单显示常用的分享渠道点击后执行对应的分享操作。
专辑简介区域可以在歌曲列表前添加专辑简介。
Widget_buildAlbumDescription(){returnSliverToBoxAdapter(child:Padding(padding:constEdgeInsets.all(
,child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[constText(专辑简介,style:TextStyle(fontSize:16,fontWeight:FontWeight.bold),),constSizedBox(height:
,constText(这是一张非常棒的专辑收录了歌手的多首经典作品。
专辑风格多样既有抒情慢歌也有动感快歌值得细细品味。
,style:TextStyle(color:Colors.grey,height:
1.
,maxLines:3,overflow:TextOverflow.ellipsis,),GestureDetector(onTap:()_showFullDescription(),child:constText(展开,style:TextStyle(color:Color(0xFFE91E
),),),],),),);}简介默认显示3行点击展开可以查看完整内容。
歌曲列表头部在歌曲列表前添加头部信息。
Widget_buildSongListHeader(){returnSliverToBoxAdapter(child:Padding(padding:constEdgeInsets.symmetric(horizontal:16,vertical:
,child:Row(children:[constText(歌曲列表,style:TextStyle(fontSize:16,fontWeight:FontWeight.bold),),constSizedBox(width:
,Text(共10首,style:TextStyle(color:Colors.grey.withOpacity(
0.
,fontSize:
,),],),),);}显示歌曲列表标题和歌曲总数让用户了解专辑包含多少首歌。
评论入口可以添加评论入口让用户查看和发表评论。
Widget_buildCommentEntry(){returnSliverToBoxAdapter(child:ListTile(leading:constIcon(Icons.comment_outlined,color:Colors.grey),title:constText(评论),subtitle:constText(1234条评论,style:TextStyle(color:Colors.grey,fontSize:
),trailing:constIcon(Icons.chevron_right,color:Colors.grey),onTap:()Get.toNamed(/comment,arguments:{albumId:id}),),);}显示评论数量点击跳转到评论页面。
总结专辑详情页的实现使用了CustomScrollView和多个Sliver组件的组合SliverAppBar实现可折叠的头部SliverToBoxAdapter包装普通WidgetSliverList构建歌曲列表。
通过合理的布局和交互设计为用户提供了清晰的专辑信息展示和便捷的操作入口。
在实际项目中还需要对接后端接口获取真实的专辑数据。
欢迎加入开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net