Flutter for OpenHarmony音乐播放器App实战17:每日推荐实现
本文介绍了如何实现音乐播放器中的每日推荐页面功能。主要内容包括:使用CustomScrollView和Sliver组件构建可折叠头部;通过LinearGradient创建渐变背景;利用DateTime处理日期显示;设计包含播放全部、收藏和下载按钮的操作栏;以及使用SliverList展示推荐歌曲列表。页面采用粉色到紫色的渐变设计,突出显示当前日期,并提供播放全部功能,帮助用户发现个性化推荐歌曲。
每日推荐是音乐播放器中一个非常受欢迎的功能,系统根据用户的听歌习惯每天推荐一批歌曲。本篇将详细介绍如何实现每日推荐页面,包括日期展示、渐变头部设计和推荐歌曲列表。
功能分析
每日推荐页面需要实现以下功能:渐变头部显示当前日期、播放全部按钮、收藏和下载按钮、推荐歌曲列表。这个页面是用户发现新歌的重要入口,设计上需要突出日期信息和推荐歌曲。
核心技术点
本篇涉及的核心技术包括:CustomScrollView和Sliver组件、SliverAppBar可折叠头部、LinearGradient渐变背景、SliverList歌曲列表、DateTime日期处理。
对应代码文件
lib/pages/daily/daily_recommend_page.dart
完整代码实现
import 'package:flutter/material.dart';
class DailyRecommendPage extends StatelessWidget {
const DailyRecommendPage({super.key});
Widget build(BuildContext context) {
// 获取当前日期
final now = DateTime.now();
return Scaffold(
body: CustomScrollView(
slivers: [
// 可折叠头部
_buildSliverAppBar(now),
// 操作栏
_buildActionBar(),
// 推荐歌曲列表
_buildSongList(),
],
),
);
}
这段代码导入了Flutter核心库。DailyRecommendPage继承StatelessWidget,因为页面不需要管理内部状态。build方法中使用DateTime.now()获取当前日期。CustomScrollView是实现复杂滚动效果的核心组件。
/// 构建可折叠头部
Widget _buildSliverAppBar(DateTime now) {
return SliverAppBar(
expandedHeight: 220,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
background: _buildHeaderBackground(now),
),
);
}
SliverAppBar设置展开高度220像素,pinned为true表示折叠后固定在顶部。FlexibleSpaceBar定义可折叠区域的内容,当用户向上滚动时,头部会逐渐折叠。
/// 构建头部背景
Widget _buildHeaderBackground(DateTime now) {
return Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFFE91E63),
Color(0xFF9C27B0),
],
),
),
child: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 40),
// 日期数字
_buildDateNumber(now),
// 月份
_buildMonthText(now),
const SizedBox(height: 8),
// 说明文字
_buildDescriptionText(),
],
),
),
);
}
Container使用LinearGradient渐变背景,从粉色(E91E63)过渡到紫色(9C27B0),斜向渐变让视觉效果更加动感。SafeArea确保内容不被系统状态栏遮挡。Column垂直排列日期信息。
/// 构建日期数字
Widget _buildDateNumber(DateTime now) {
return Text(
'${now.day}',
style: const TextStyle(
color: Colors.white,
fontSize: 60,
fontWeight: FontWeight.bold,
shadows: [
Shadow(
color: Colors.black26,
offset: Offset(2, 2),
blurRadius: 4,
),
],
),
);
}
日期数字使用60像素超大白色粗体字突出显示,这是每日推荐页面的标志性视觉元素。添加阴影效果让文字更有立体感,在渐变背景上更加清晰。
/// 构建月份文字
Widget _buildMonthText(DateTime now) {
return Text(
'${now.month}月',
style: const TextStyle(
color: Colors.white70,
fontSize: 18,
),
);
}
/// 构建说明文字
Widget _buildDescriptionText() {
return const Text(
'根据你的音乐口味生成',
style: TextStyle(
color: Colors.white54,
fontSize: 14,
),
);
}
月份使用18像素白色70%透明度作为辅助信息,说明文字使用白色54%透明度,作为最次要的信息。这种透明度层次让信息主次分明,用户一眼就能看出这是每日推荐功能。
/// 构建操作栏
Widget _buildActionBar() {
return SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(
children: [
// 播放全部按钮
Expanded(
child: _buildPlayAllButton(),
),
const SizedBox(width: 12),
// 收藏按钮
_buildIconButton(Icons.favorite_border),
// 下载按钮
_buildIconButton(Icons.download),
],
),
),
);
}
SliverToBoxAdapter将普通Widget转换为Sliver,这是在CustomScrollView中使用普通组件的方式。操作栏使用Row水平排列按钮,Expanded让播放全部按钮占据主要位置。
/// 构建播放全部按钮
Widget _buildPlayAllButton() {
return ElevatedButton.icon(
onPressed: () {
// 播放全部歌曲
},
icon: const Icon(Icons.play_arrow),
label: const Text('播放全部'),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFE91E63),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25),
),
),
);
}
播放全部使用ElevatedButton.icon,背景色使用粉色主题色。padding设置垂直内边距让按钮更高,shape设置圆角让按钮呈胶囊形状。这是最常用的操作,所以占据最大空间。
/// 构建图标按钮
Widget _buildIconButton(IconData icon) {
return Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: Colors.grey.withOpacity(0.3),
),
),
child: IconButton(
icon: Icon(icon),
onPressed: () {},
color: Colors.grey,
),
);
}
收藏和下载使用带边框的圆形IconButton,视觉上与播放全部按钮形成对比。Container添加圆形边框装饰,让按钮更加精致。
/// 构建推荐歌曲列表
Widget _buildSongList() {
return SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => _buildSongItem(index),
childCount: 30,
),
);
}
SliverList构建推荐歌曲列表,SliverChildBuilderDelegate实现懒加载,只构建可见区域的子项。childCount设为30,表示每日推荐包含30首歌曲。
/// 构建单个歌曲项
Widget _buildSongItem(int index) {
return ListTile(
leading: _buildSongCover(index),
title: Text(
'每日推荐 ${index + 1}',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
),
),
subtitle: const Text(
'歌手名称',
style: TextStyle(
color: Colors.grey,
fontSize: 13,
),
),
trailing: _buildPlayButton(),
onTap: () {
// 播放歌曲
},
);
}
ListTile是Flutter提供的列表项组件,leading放置歌曲封面,title显示歌曲名称,subtitle显示歌手名。trailing放置播放按钮,onTap处理点击事件。
/// 构建歌曲封面
Widget _buildSongCover(int index) {
return Container(
width: 50,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.primaries[index % Colors.primaries.length]
.withOpacity(0.3),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
child: const Icon(
Icons.music_note,
color: Colors.white70,
),
);
}
封面使用50x50像素的圆角容器,背景色从primaries颜色列表循环取值。添加阴影效果增加层次感,中央显示音乐图标作为占位。
/// 构建播放按钮
Widget _buildPlayButton() {
return const Icon(
Icons.play_circle_outline,
color: Color(0xFFE91E63),
size: 32,
);
}
}
播放按钮使用粉色主题色突出显示,size设为32像素让按钮更容易点击。play_circle_outline图标是播放按钮的标准样式。
CustomScrollView和Sliver组件详解
CustomScrollView是Flutter中实现复杂滚动效果的核心组件,它的children必须是Sliver类型的组件:
// CustomScrollView基本结构
CustomScrollView(
slivers: [
SliverAppBar(...), // 可折叠头部
SliverToBoxAdapter(...), // 普通Widget转Sliver
SliverList(...), // 列表
SliverGrid(...), // 网格
],
)
常用的Sliver组件包括SliverAppBar、SliverList、SliverGrid、SliverToBoxAdapter等。这种组合可以实现头部可折叠、列表滚动等复杂效果。
SliverAppBar可折叠头部
SliverAppBar是一个可以随滚动折叠的AppBar,提供了丰富的配置选项:
// SliverAppBar配置详解
SliverAppBar(
expandedHeight: 220, // 展开时的高度
pinned: true, // 折叠后是否固定在顶部
floating: false, // 向下滚动时是否立即显示
snap: false, // 是否有吸附效果
flexibleSpace: FlexibleSpaceBar(
background: // 背景内容
),
)
expandedHeight设置展开时的高度,pinned为true表示折叠后固定在顶部。FlexibleSpaceBar定义可折叠区域的内容。
LinearGradient渐变背景
LinearGradient用于创建线性渐变效果,是实现炫酷背景的常用方式:
// 渐变背景配置
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft, // 渐变起点
end: Alignment.bottomRight, // 渐变终点
colors: [
Color(0xFFE91E63), // 起始颜色(粉色)
Color(0xFF9C27B0), // 结束颜色(紫色)
],
),
)
begin和end定义渐变方向,从左上到右下的斜向渐变让视觉效果更加动感。colors数组定义渐变颜色。
SliverList列表实现
SliverList用于在CustomScrollView中创建列表,配合SliverChildBuilderDelegate实现懒加载:
// SliverList基本用法
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return ListTile(...);
},
childCount: 30,
),
)
SliverChildBuilderDelegate只构建可见区域的子项,对于长列表性能更好。childCount指定列表项总数。
DateTime日期处理
Flutter使用DateTime类处理日期和时间:
// 获取当前日期
final now = DateTime.now();
// 获取日期各部分
int year = now.year; // 年
int month = now.month; // 月
int day = now.day; // 日
DateTime.now()获取当前日期时间,通过属性可以获取年、月、日等各部分。在每日推荐页面中,我们使用day和month来显示当前日期。
SliverToBoxAdapter说明
SliverToBoxAdapter用于将普通Widget转换为Sliver,这样就可以在CustomScrollView中使用:
// 将普通Widget转换为Sliver
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.all(16),
child: Row(...),
),
)
这是在CustomScrollView中使用非Sliver组件的标准方式,比如操作栏、分割线等。
小结
本篇实现了音乐播放器的每日推荐页面。使用CustomScrollView和Sliver组件实现头部可折叠效果,渐变背景和大字号日期突出每日推荐的特点。SliverList实现歌曲列表的高效渲染,ListTile简化列表项构建。这种设计在各大音乐App中都很常见,掌握这些技术可以实现各种复杂的滚动界面效果。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐
所有评论(0)