Flutter for OpenHarmony音乐播放器App实战22:下载管理实现
下载管理页面的实现涵盖了多个Flutter开发中的常用技术点:TabBar与TabBarView的配合使用、多选模式的状态管理、列表项的自定义布局、底部菜单和对话框的使用等。通过合理的UI设计和交互逻辑,为用户提供了便捷的下载管理体验。在实际项目中,还需要结合后端接口实现真正的下载功能和文件管理。欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn
在音乐播放器应用中,下载管理是一个非常实用的功能。用户可以将喜欢的歌曲下载到本地,方便在没有网络的情况下收听。本篇文章将详细介绍如何实现一个完整的下载管理页面,包括已下载列表、下载中列表以及多选删除等功能。
页面整体结构
下载管理页面采用TabBar切换的方式,将已下载和下载中两个列表分开展示。这种设计让用户可以清晰地区分不同状态的下载任务。
import 'package:flutter/material.dart';
import 'package:get/get.dart';
/// 下载管理页面
/// 管理已下载和正在下载的音乐文件
class DownloadPage extends StatefulWidget {
const DownloadPage({super.key});
State<DownloadPage> createState() => _DownloadPageState();
}
这里我们创建了一个StatefulWidget,因为下载页面需要管理多个状态,比如Tab切换、多选模式等。使用GetX进行状态管理可以让代码更加简洁。
状态管理与TabController
页面需要管理多个状态变量,包括TabController、多选模式标志以及选中项的集合。
class _DownloadPageState extends State<DownloadPage> with SingleTickerProviderStateMixin {
// TabController用于控制Tab切换
late TabController _tabController;
// 是否处于多选模式
bool _isMultiSelect = false;
// 选中的已下载歌曲索引集合
final Set<int> _selectedDownloaded = {};
// 选中的下载中歌曲索引集合
final Set<int> _selectedDownloading = {};
这里使用了SingleTickerProviderStateMixin,这是使用TabController的必要条件。_isMultiSelect用于控制是否显示多选框,两个Set集合分别存储已下载和下载中列表的选中项。
初始化与资源释放
在initState中初始化TabController,在dispose中释放资源,这是Flutter开发中的标准做法。
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
}
void dispose() {
_tabController.dispose();
super.dispose();
}
TabController的length设置为2,对应"已下载"和"下载中"两个Tab。vsync参数传入this,因为我们的State类混入了SingleTickerProviderStateMixin。
AppBar与TabBar设计
页面顶部包含返回按钮、标题、TabBar以及操作按钮。
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Get.back(),
),
title: const Text('下载管理'),
bottom: TabBar(
controller: _tabController,
labelColor: const Color(0xFFE91E63),
unselectedLabelColor: Colors.grey,
indicatorColor: const Color(0xFFE91E63),
tabs: const [
Tab(text: '已下载'),
Tab(text: '下载中'),
],
),
TabBar的样式设计采用了粉色主题色(0xFFE91E63),选中的Tab文字和指示器都使用这个颜色,未选中的Tab使用灰色,形成明显的视觉对比。
操作按钮区域
AppBar的actions区域放置了多选和删除按钮。
actions: [
IconButton(
icon: Icon(_isMultiSelect ? Icons.close : Icons.checklist),
onPressed: () {
setState(() {
_isMultiSelect = !_isMultiSelect;
_selectedDownloaded.clear();
_selectedDownloading.clear();
});
},
),
if (_isMultiSelect)
IconButton(
icon: const Icon(Icons.delete_outline),
onPressed: _deleteSelected,
),
],
),
点击多选按钮时,切换_isMultiSelect状态,同时清空之前的选中项。当处于多选模式时,会显示删除按钮。这种条件渲染的方式让界面更加简洁。
删除选中项的逻辑
删除功能需要根据当前所在的Tab来决定删除哪个列表的内容。
void _deleteSelected() {
final currentTab = _tabController.index;
final selectedSet = currentTab == 0 ? _selectedDownloaded : _selectedDownloading;
if (selectedSet.isEmpty) {
Get.snackbar('提示', '请先选择要删除的歌曲');
return;
}
Get.dialog(
AlertDialog(
title: const Text('确认删除'),
content: Text('确定要删除选中的 ${selectedSet.length} 首歌曲吗?'),
actions: [
TextButton(
onPressed: () => Get.back(),
child: const Text('取消'),
),
TextButton(
onPressed: () {
// 执行删除逻辑
setState(() {
selectedSet.clear();
_isMultiSelect = false;
});
Get.back();
Get.snackbar('成功', '删除成功');
},
child: const Text('确定', style: TextStyle(color: Color(0xFFE91E63))),
),
],
),
);
}
删除前会弹出确认对话框,避免用户误操作。使用GetX的dialog方法可以方便地显示对话框,snackbar方法用于显示提示信息。
TabBarView内容区域
页面主体使用TabBarView来展示两个列表。
body: TabBarView(
controller: _tabController,
children: [
_buildDownloadedList(),
_buildDownloadingList(),
],
),
);
}
TabBarView与TabBar共用同一个controller,这样切换Tab时内容区域会自动同步切换。两个子Widget分别构建已下载列表和下载中列表。
已下载列表构建
已下载列表展示所有已经下载完成的歌曲。
Widget _buildDownloadedList() {
return ListView.builder(
itemCount: 15,
itemBuilder: (context, index) {
final isSelected = _selectedDownloaded.contains(index);
return ListTile(
leading: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (_isMultiSelect)
Checkbox(
value: isSelected,
activeColor: const Color(0xFFE91E63),
onChanged: (value) {
setState(() {
if (value == true) {
_selectedDownloaded.add(index);
} else {
_selectedDownloaded.remove(index);
}
});
},
),
当处于多选模式时,每个列表项前面会显示一个Checkbox。使用Set来存储选中项的索引,可以方便地进行添加和删除操作。
歌曲封面与信息展示
每首歌曲都有封面图、歌曲名和歌手名。
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.primaries[index % Colors.primaries.length].withOpacity(0.3),
),
child: const Icon(Icons.music_note, color: Colors.white70),
),
],
),
title: Text('已下载歌曲 ${index + 1}'),
subtitle: Text('歌手 ${index + 1}'),
封面使用Container配合圆角装饰,颜色根据索引从Colors.primaries中循环取值,这样每首歌曲的封面颜色都不同,增加视觉层次感。
文件大小与更多操作
列表项的尾部显示文件大小和更多操作按钮。
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'${(index + 1) * 3.5} MB',
style: const TextStyle(color: Colors.grey, fontSize: 12),
),
IconButton(
icon: const Icon(Icons.more_vert, color: Colors.grey),
onPressed: () => _showMoreOptions(index),
),
],
),
onTap: () {
// 播放歌曲
},
);
},
);
}
文件大小使用灰色小字体显示,更多操作按钮点击后会弹出底部菜单。整个ListTile点击后可以播放歌曲。
更多操作菜单
点击更多按钮后显示的底部菜单。
void _showMoreOptions(int index) {
Get.bottomSheet(
Container(
padding: const EdgeInsets.symmetric(vertical: 20),
decoration: const BoxDecoration(
color: Color(0xFF1E1E1E),
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.play_arrow, color: Colors.white),
title: const Text('播放'),
onTap: () => Get.back(),
),
ListTile(
leading: const Icon(Icons.playlist_add, color: Colors.white),
title: const Text('添加到歌单'),
onTap: () => Get.back(),
),
底部菜单使用GetX的bottomSheet方法,容器顶部设置圆角,背景使用深色主题。菜单项包括播放、添加到歌单、分享和删除等常用操作。
删除单曲功能
底部菜单中的删除选项。
ListTile(
leading: const Icon(Icons.share, color: Colors.white),
title: const Text('分享'),
onTap: () => Get.back(),
),
ListTile(
leading: const Icon(Icons.delete_outline, color: Colors.red),
title: const Text('删除', style: TextStyle(color: Colors.red)),
onTap: () {
Get.back();
_confirmDelete(index);
},
),
],
),
),
);
}
删除选项使用红色图标和文字,提醒用户这是一个危险操作。点击后会先关闭底部菜单,然后弹出确认对话框。
单曲删除确认
删除单首歌曲的确认逻辑。
void _confirmDelete(int index) {
Get.dialog(
AlertDialog(
title: const Text('确认删除'),
content: const Text('确定要删除这首歌曲吗?删除后将无法恢复。'),
actions: [
TextButton(
onPressed: () => Get.back(),
child: const Text('取消'),
),
TextButton(
onPressed: () {
Get.back();
Get.snackbar('成功', '删除成功');
},
child: const Text('删除', style: TextStyle(color: Colors.red)),
),
],
),
);
}
确认对话框明确告知用户删除后无法恢复,删除按钮使用红色文字。这种二次确认的设计可以有效防止误操作。
下载中列表构建
下载中列表展示正在下载的歌曲及其进度。
Widget _buildDownloadingList() {
return ListView.builder(
itemCount: 5,
itemBuilder: (context, index) {
final progress = (index + 1) * 0.2;
return ListTile(
leading: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Colors.primaries[index % Colors.primaries.length].withOpacity(0.3),
),
child: const Icon(Icons.music_note, color: Colors.white70),
),
title: Text('下载中歌曲 ${index + 1}'),
下载中列表的封面样式与已下载列表保持一致,progress变量模拟不同的下载进度。
下载进度条
使用LinearProgressIndicator显示下载进度。
subtitle: LinearProgressIndicator(
value: progress,
backgroundColor: Colors.grey.withOpacity(0.3),
valueColor: const AlwaysStoppedAnimation<Color>(Color(0xFFE91E63)),
),
trailing: Text(
'${(progress * 100).toInt()}%',
style: const TextStyle(color: Colors.grey, fontSize: 12),
),
);
},
);
}
进度条使用主题色填充,背景使用半透明灰色。尾部显示百分比数字,让用户清楚地知道下载进度。
空状态处理
当列表为空时,需要显示友好的提示。
Widget _buildEmptyState(String message) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.download_outlined,
size: 80,
color: Colors.grey.withOpacity(0.5),
),
const SizedBox(height: 16),
Text(
message,
style: TextStyle(
color: Colors.grey.withOpacity(0.8),
fontSize: 16,
),
),
],
),
);
}
空状态页面使用大图标配合文字说明,居中显示。这种设计比单纯显示空白页面更加友好。
存储空间显示
在页面底部可以添加存储空间使用情况的显示。
Widget _buildStorageInfo() {
return Container(
padding: const EdgeInsets.all(16),
color: const Color(0xFF1E1E1E),
child: Row(
children: [
const Icon(Icons.storage, color: Colors.grey),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('存储空间', style: TextStyle(fontSize: 14)),
const SizedBox(height: 4),
LinearProgressIndicator(
value: 0.35,
backgroundColor: Colors.grey.withOpacity(0.3),
valueColor: const AlwaysStoppedAnimation<Color>(Color(0xFFE91E63)),
),
],
),
),
const SizedBox(width: 12),
const Text('3.5GB / 10GB', style: TextStyle(color: Colors.grey, fontSize: 12)),
],
),
);
}
存储信息栏显示已用空间和总空间,配合进度条直观展示使用比例。这个功能可以帮助用户了解设备存储状况。
总结
下载管理页面的实现涵盖了多个Flutter开发中的常用技术点:TabBar与TabBarView的配合使用、多选模式的状态管理、列表项的自定义布局、底部菜单和对话框的使用等。通过合理的UI设计和交互逻辑,为用户提供了便捷的下载管理体验。在实际项目中,还需要结合后端接口实现真正的下载功能和文件管理。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐




所有评论(0)