5G时代,运营商如何应对网络运维挑战?——网络投诉系统建设

核心内容摘要

S195柴油机机体钻组合机床总体及夹具设计
1C31227G02分析输入(电压)模块

2026 竞品分析工具怎么选?4 款工具横向对比 + 避坑指南

首页是用户进入App后看到的第一个内容页面它需要展示最重要的信息和功能入口。

音乐播放器的首页通常包含Banner轮播、快捷入口、推荐歌单、热门歌手、新碟上架等模块。

本篇我们来实现一个功能丰富的首页。

功能分析首页需要实现以下功能顶部搜索入口、Banner区域展示每日推荐、快捷入口、推荐歌单网格展示、热门歌手横向滚动列表、新碟上架横向滚动列表。

核心技术点本篇涉及的核心技术包括SingleChildScrollView实现页面滚动、GridView.builder实现网格布局、ListView.builder实现横向滚动列表、数据驱动的UI构建方式。

对应代码文件lib/pages/home/home_page.dart完整代码实现importpackage:flutter/material.dart;importpackage:get/get.dart;import../search/search_page.dart;import../playlist/playlist_detail_page.dart;import../artist/artist_detail_page.dart;import../album/album_detail_page.dart;import../ranking/ranking_page.dart;import../daily/daily_recommend_page.dart;classHomePageextendsStatelessWidget{constHomePage({super.key});overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:constText(音乐播放器),actions:[IconButton(icon:constIcon(Icons.search),onPressed:()Get.to(()constSearchPage()),),],),上面这段代码导入了必要的依赖和子页面。

HomePage使用StatelessWidget因为不需要管理内部状态。

AppBar右侧放置搜索按钮点击后使用GetX导航到搜索页面。

body:SingleChildScrollView(padding:constEdgeInsets.all(

,child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[_buildBanner(),constSizedBox(height:

,_buildQuickActions(),constSizedBox(height:

,_buildSection(推荐歌单,_buildPlaylistGrid()),constSizedBox(height:

,_buildSection(热门歌手,_buildArtistList()),constSizedBox(height:

,_buildSection(新碟上架,_buildAlbumList()),constSizedBox(height:

,],),),);}SingleChildScrollView包裹Column实现整体滚动。

padding设置16像素内边距crossAxisAlignment设为start让内容左对齐。

底部留100像素空间避免被迷你播放器遮挡。

Widget_buildBanner(){returnGestureDetector(onTap:()Get.to(()constDailyRecommendPage()),child:Container(height:160,decoration:BoxDecoration(borderRadius:BorderRadius.circular(

,gradient:constLinearGradient(begin:Alignment.topLeft,end:Alignment.bottomRight,colors:[Color(0xFFE91E

,Color(0xFF9C27B

],),boxShadow:[BoxShadow(color:constColor(0xFFE91E

.withOpacity(

0.

,blurRadius:15,offset:constOffset(0,

,),],),Banner是首页的视觉焦点高度160像素使用16像素圆角。

渐变从粉色到紫色与App主题一致boxShadow添加粉色阴影让Banner有悬浮效果。

点击跳转到每日推荐页面。

child:Stack(children:[Positioned(right:20,bottom:20,child:Icon(Icons.headphones,size:100,color:Colors.white.withOpacity(

0.

,),),Padding(padding:constEdgeInsets.all(

,child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[Container(padding:constEdgeInsets.symmetric(horizontal:8,vertical:

,decoration:BoxDecoration(color:Colors.white.withOpacity(

0.

,borderRadius:BorderRadius.circular(

,),child:constText(每日推荐,style:TextStyle(color:Colors.white,fontSize:

,),),Stack叠加背景装饰图标和文字内容。

Positioned将耳机图标定位在右下角作为装饰使用20%透明度不抢夺视觉焦点。

标签使用半透明白色背景的胶囊形状。

constSizedBox(height:

,constText(发现你的专属音乐,style:TextStyle(color:Colors.white,fontSize:24,fontWeight:FontWeight.bold,),),constSizedBox(height:

,constText(根据你的口味每天为你推荐30首歌曲,style:TextStyle(color:Colors.white70,fontSize:

,),],),),],),),);}主标题使用24像素粗体白色大字副标题使用白色70%透明度形成主次层次。

SizedBox添加固定间距让布局整齐。

Widget_buildQuickActions(){finalactions[{icon:Icons.today,label:每日推荐,color:constColor(0xFFE91E

,onTap:()Get.to(()constDailyRecommendPage()),},{icon:Icons.leaderboard,label:排行榜,color:constColor(0xFF9C27B

,onTap:()Get.to(()constRankingPage()),},{icon:Icons.radio,label:私人FM,color:constColor(0xFF2196F

,onTap:(){},},{icon:Icons.album,label:新碟,color:constColor(0xFF4CAF

,onTap:(){},},];快捷入口使用数据驱动方式构建每个入口包含图标、文字、颜色和点击回调。

这种方式让代码更易维护添加或修改入口只需修改数据即可。

returnRow(mainAxisAlignment:MainAxisAlignment.spaceAround,children:actions.map((action){returnGestureDetector(onTap:action[onTap]asVoidCallback,child:Column(children:[Container(width:56,height:56,decoration:BoxDecoration(color:(action[color]asColor).withOpacity(

0.

,borderRadius:BorderRadius.circular(

,),child:Icon(action[icon]asIconData,color:action[color]asColor,size:28,),),constSizedBox(height:

,Text(action[label]asString,style:constTextStyle(fontSize:

,),],),);}).toList(),);}Row的spaceAround让入口均匀分布。

每个入口使用不同颜色增加视觉区分度图标背景使用10%透明度的对应颜色。

Widget_buildSection(Stringtitle,Widgetchild){returnColumn(crossAxisAlignment:CrossAxisAlignment.start,children:[Row(mainAxisAlignment:MainAxisAlignment.spaceBetween,children:[Text(title,style:constTextStyle(fontSize:18,fontWeight:FontWeight.bold,),),GestureDetector(onTap:(){},child:constRow(children:[Text(更多,style:TextStyle(color:Colors.grey,fontSize:

,),Icon(Icons.chevron_right,color:Colors.grey,size:

,],),),],),constSizedBox(height:

,child,],);}通用Section组件封装标题行和内容区域避免重复代码。

标题行左侧显示标题右侧显示更多按钮让页面结构更清晰。

Widget_buildPlaylistGrid(){returnGridView.builder(shrinkWrap:true,physics:constNeverScrollableScrollPhysics(),gridDelegate:constSliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:3,childAspectRatio:

75,crossAxisSpacing:12,mainAxisSpacing:12,),itemCount:6,itemBuilder:(context,index){returnGestureDetector(onTap:()Get.to(()PlaylistDetailPage(id:index)),child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[Expanded(child:Container(decoration:BoxDecoration(borderRadius:BorderRadius.circular(

,color:Colors.primaries[index%Colors.primaries.length].withOpacity(

0.

,),GridView.builder的shrinkWrap让高度自适应内容NeverScrollableScrollPhysics禁用内部滚动。

gridDelegate配置3列、

75宽高比、12像素间距。

child:Stack(children:[constCenter(child:Icon(Icons.queue_music,size:40,color:Colors.white70,),),Positioned(top:4,right:4,child:Container(padding:constEdgeInsets.symmetric(horizontal:6,vertical:2,),decoration:BoxDecoration(color:Colors.black45,borderRadius:BorderRadius.circular(

,),child:Row(mainAxisSize:MainAxisSize.min,children:[constIcon(Icons.play_arrow,size:12,color:Colors.white,),Text(${(index

*10}万,style:constTextStyle(color:Colors.white,fontSize:10,),),],),),),],),),),constSizedBox(height:

,Text(推荐歌单${index1},style:constTextStyle(fontSize:

,maxLines:2,overflow:TextOverflow.ellipsis,),],),);},);}每个歌单项包含封面和标题封面右上角显示播放量。

Stack叠加音乐图标和播放量角标Positioned精确定位角标位置。

Widget_buildArtistList(){returnSizedBox(height:110,child:ListView.builder(scrollDirection:Axis.horizontal,itemCount:10,itemBuilder:(context,index){returnGestureDetector(onTap:()Get.to(()ArtistDetailPage(id:index)),child:Container(width:80,margin:constEdgeInsets.only(right:

,child:Column(children:[Container(width:64,height:64,decoration:BoxDecoration(shape:BoxShape.circle,color:Colors.primaries[index%Colors.primaries.length].withOpacity(

0.

,border:Border.all(color:constColor(0xFFE91E

.withOpacity(

0.

,width:2,),),child:constIcon(Icons.person,color:Colors.white70,size:32,),),SizedBox固定高度110像素scrollDirection设为Axis.horizontal实现横向滚动。

每个歌手项宽80像素圆形头像使用粉色边框与主题色呼应。

constSizedBox(height:

,Text(歌手${index1},style:constTextStyle(fontSize:

,maxLines:1,overflow:TextOverflow.ellipsis,textAlign:TextAlign.center,),Text(${(index

*50}首,style:constTextStyle(fontSize:10,color:Colors.grey,),),],),),);},),);}歌手名和歌曲数量显示在头像下方maxLines和overflow确保文字过长时显示省略号。

歌曲数量使用灰色小字作为辅助信息。

Widget_buildAlbumList(){returnSizedBox(height:180,child:ListView.builder(scrollDirection:Axis.horizontal,itemCount:10,itemBuilder:(context,index){returnGestureDetector(onTap:()Get.to(()AlbumDetailPage(id:index)),child:Container(width:130,margin:constEdgeInsets.only(right:

,child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[Container(height:130,decoration:BoxDecoration(borderRadius:BorderRadius.circular(

,color:Colors.primaries[index%Colors.primaries.length].withOpacity(

0.

,boxShadow:[BoxShadow(color:Colors.black.withOpacity(

0.

,blurRadius:8,offset:constOffset(0,

,),],),新碟列表高度180像素每个专辑项宽130像素。

封面区域高130像素添加阴影增加立体感。

child:Stack(children:[constCenter(child:Icon(Icons.album,size:50,color:Colors.white70,),),Positioned(bottom:8,right:8,child:Container(width:32,height:32,decoration:constBoxDecoration(shape:BoxShape.circle,color:Color(0xFFE91E

,),child:constIcon(Icons.play_arrow,color:Colors.white,size:20,),),),],),),constSizedBox(height:

,Text(专辑${index1},style:constTextStyle(fontSize:

,maxLines:1,overflow:TextOverflow.ellipsis,),Text(歌手${index1},style:constTextStyle(fontSize:11,color:Colors.grey,),maxLines:1,overflow:TextOverflow.ellipsis,),],),),);},),);}}封面右下角有粉色圆形播放按钮是整个专辑项的视觉焦点。

下方显示专辑名和歌手名歌手名使用灰色小字作为辅助信息。

GridView与ListView对比GridView适合展示网格布局的内容如歌单封面、图片墙等。

ListView适合展示列表形式的内容设置scrollDirection为Axis.horizontal可实现横向滚动。

两者都支持builder模式实现懒加载只构建可见区域的项目提升性能。

数据驱动UI的优势使用List或Map存储数据通过map方法遍历生成Widget这种方式让代码更易维护。

添加、删除或修改内容只需修改数据源不需要改动UI构建逻辑。

这也是Flutter推荐的声明式UI编程方式。

小结本篇实现了音乐播放器的首页通过SingleChildScrollView实现页面滚动使用GridView和ListView分别展示网格和列表内容。

抽取通用的Section组件减少重复代码使用数据驱动的方式构建快捷入口。

首页包含Banner、快捷入口、推荐歌单、热门歌手、新碟上架等模块为用户提供丰富的内容入口。

欢迎加入开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net

为您精选优质动漫美女光㊙️屁股网站-为您精选优质动漫美女光㊙️屁股网站应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123