专辑详情页是展示专辑完整信息的页面,用户可以查看专辑封面、歌手信息、发行时间以及专辑内的所有歌曲。本篇文章将详细介绍如何使用CustomScrollView和Sliver组件实现一个美观实用的专辑详情页面。
页面基础结构
专辑详情页使用StatelessWidget,因为页面状态相对简单。
import'package:flutter/material.dart';import'package: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设置展开高度为300,pinned为true让AppBar收起后固定在顶部。背景使用渐变色,从专辑主题色过渡到黑色。
专辑封面与信息
头部展示专辑封面和基本信息。
child:SafeArea(child:Padding(padding:constEdgeInsets.all(20),child:Row(crossAxisAlignment:CrossAxisAlignment.end,children:[Container(width:150,height:150,decoration:BoxDecoration(borderRadius:BorderRadius.circular(12),color:Colors.white24,boxShadow:[BoxShadow(color:Colors.black.withOpacity(0.3),blurRadius:20,offset:constOffset(0,10),),],),child:constIcon(Icons.album,size:70,color:Colors.white70),),封面使用圆角矩形,添加阴影增加立体感。实际项目中会使用网络图片替换Icon。
专辑文字信息
封面右侧显示专辑名称、歌手和发行时间。
constSizedBox(width:16),Expanded(child:Column(mainAxisAlignment:MainAxisAlignment.end,crossAxisAlignment:CrossAxisAlignment.start,children:[Text('专辑${id+1}',style:constTextStyle(color:Colors.white,fontSize:22,fontWeight:FontWeight.bold,),),constSizedBox(height:8),GestureDetector(onTap:()=>Get.toNamed('/artist/$id'),child:constText('歌手名称',style:TextStyle(color:Colors.white70),),),constSizedBox(height:4),Text('发行时间:${2020+id%5}年',style:constTextStyle(color:Colors.white54,fontSize:12),),],),),],),),),),),);}歌手名称可点击跳转到歌手详情页。使用不同透明度的白色区分信息层级。
操作按钮栏
操作栏包含播放全部、收藏和分享按钮。
Widget_buildActionBar(){returnSliverToBoxAdapter(child:Padding(padding:constEdgeInsets.all(16),child:Row(children:[Expanded(child:ElevatedButton.icon(onPressed:()=>_playAll(),icon:constIcon(Icons.play_arrow),label:constText('播放全部'),style:ElevatedButton.styleFrom(backgroundColor:constColor(0xFFE91E63),foregroundColor:Colors.white,padding:constEdgeInsets.symmetric(vertical:12),shape:RoundedRectangleBorder(borderRadius:BorderRadius.circular(25),),),),),constSizedBox(width:12),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('${index+1}',style:TextStyle(color:index<3?constColor(0xFFE91E63):Colors.grey,fontWeight:index<3?FontWeight.bold:FontWeight.normal,),),),title:Text('歌曲${index+1}',maxLines:1,overflow:TextOverflow.ellipsis,),subtitle:constText('歌手名称',style:TextStyle(color:Colors.grey,fontSize:12),),trailing:Row(mainAxisSize:MainAxisSize.min,children:[constText('04:32',style:TextStyle(color:Colors.grey,fontSize:12),),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(16)),),child:Column(mainAxisSize:MainAxisSize.min,children:[ListTile(leading:Container(width:50,height:50,decoration:BoxDecoration(borderRadius:BorderRadius.circular(8),color:Colors.grey.withOpacity(0.3),),child:constIcon(Icons.music_note,color:Colors.white70),),title:Text('歌曲${index+1}'),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:16),],),),);}菜单顶部显示歌曲信息,下方是各种操作选项。这种设计让用户在操作前可以确认选中的歌曲。
播放全部方法
点击播放全部按钮后播放专辑内所有歌曲。
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(16)),),child:Column(mainAxisSize:MainAxisSize.min,children:[constPadding(padding:EdgeInsets.all(16),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:24),],),),);}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.3),shape:BoxShape.circle,),child:Icon(icon,color:Colors.white70),),constSizedBox(height:8),Text(label,style:constTextStyle(fontSize:12)),],),);}分享菜单显示常用的分享渠道,点击后执行对应的分享操作。
专辑简介区域
可以在歌曲列表前添加专辑简介。
Widget_buildAlbumDescription(){returnSliverToBoxAdapter(child:Padding(padding:constEdgeInsets.all(16),child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[constText('专辑简介',style:TextStyle(fontSize:16,fontWeight:FontWeight.bold),),constSizedBox(height:8),constText('这是一张非常棒的专辑,收录了歌手的多首经典作品。''专辑风格多样,既有抒情慢歌,也有动感快歌,值得细细品味。',style:TextStyle(color:Colors.grey,height:1.6),maxLines:3,overflow:TextOverflow.ellipsis,),GestureDetector(onTap:()=>_showFullDescription(),child:constText('展开',style:TextStyle(color:Color(0xFFE91E63)),),),],),),);}简介默认显示3行,点击"展开"可以查看完整内容。
歌曲列表头部
在歌曲列表前添加头部信息。
Widget_buildSongListHeader(){returnSliverToBoxAdapter(child:Padding(padding:constEdgeInsets.symmetric(horizontal:16,vertical:8),child:Row(children:[constText('歌曲列表',style:TextStyle(fontSize:16,fontWeight:FontWeight.bold),),constSizedBox(width:8),Text('共10首',style:TextStyle(color:Colors.grey.withOpacity(0.8),fontSize:14),),],),),);}显示"歌曲列表"标题和歌曲总数,让用户了解专辑包含多少首歌。
评论入口
可以添加评论入口让用户查看和发表评论。
Widget_buildCommentEntry(){returnSliverToBoxAdapter(child:ListTile(leading:constIcon(Icons.comment_outlined,color:Colors.grey),title:constText('评论'),subtitle:constText('1234条评论',style:TextStyle(color:Colors.grey,fontSize:12)),trailing:constIcon(Icons.chevron_right,color:Colors.grey),onTap:()=>Get.toNamed('/comment',arguments:{'albumId':id}),),);}显示评论数量,点击跳转到评论页面。
总结
专辑详情页的实现使用了CustomScrollView和多个Sliver组件的组合:SliverAppBar实现可折叠的头部,SliverToBoxAdapter包装普通Widget,SliverList构建歌曲列表。通过合理的布局和交互设计,为用户提供了清晰的专辑信息展示和便捷的操作入口。在实际项目中,还需要对接后端接口获取真实的专辑数据。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net