|
|
|
@ -111,12 +111,12 @@ class MiniPlayer extends StatelessWidget {
|
|
|
|
|
maxWidth: 42,
|
|
|
|
|
maxHeight: 42,
|
|
|
|
|
),
|
|
|
|
|
onPressed: null, // 禁用按钮
|
|
|
|
|
onPressed: null, // 禁用按钮
|
|
|
|
|
icon: Image.asset(
|
|
|
|
|
"assets/img/music_pause.png",
|
|
|
|
|
width: 25,
|
|
|
|
|
height: 25,
|
|
|
|
|
color: Colors.grey, // 使用灰色表示禁用状态
|
|
|
|
|
color: Colors.grey, // 使用灰色表示禁用状态
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
@ -142,12 +142,12 @@ class MiniPlayer extends StatelessWidget {
|
|
|
|
|
),
|
|
|
|
|
onPressed: audioController.playOrPause,
|
|
|
|
|
icon: Obx(() => Image.asset(
|
|
|
|
|
audioController.isPlaying.value
|
|
|
|
|
? "assets/img/music_play.png"
|
|
|
|
|
: "assets/img/music_pause.png",
|
|
|
|
|
width: 25,
|
|
|
|
|
height: 25,
|
|
|
|
|
)),
|
|
|
|
|
audioController.isPlaying.value
|
|
|
|
|
? "assets/img/music_play.png"
|
|
|
|
|
: "assets/img/music_pause.png",
|
|
|
|
|
width: 25,
|
|
|
|
|
height: 25,
|
|
|
|
|
)),
|
|
|
|
|
);
|
|
|
|
|
}),
|
|
|
|
|
),
|
|
|
|
@ -158,21 +158,22 @@ class MiniPlayer extends StatelessWidget {
|
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
|
return Obx(() {
|
|
|
|
|
final bool hasPlaylist = audioController.songList.isNotEmpty;
|
|
|
|
|
|
|
|
|
|
return GestureDetector(
|
|
|
|
|
onHorizontalDragEnd: hasPlaylist ? (DragEndDetails details) {
|
|
|
|
|
if (audioController.songList.isEmpty) return;
|
|
|
|
|
final velocity = details.velocity.pixelsPerSecond.dx;
|
|
|
|
|
const threshold = 300.0;
|
|
|
|
|
onHorizontalDragEnd: hasPlaylist
|
|
|
|
|
? (DragEndDetails details) {
|
|
|
|
|
if (audioController.songList.isEmpty) return;
|
|
|
|
|
final velocity = details.velocity.pixelsPerSecond.dx;
|
|
|
|
|
const threshold = 300.0;
|
|
|
|
|
|
|
|
|
|
if (velocity > threshold) {
|
|
|
|
|
audioController.playPrevious();
|
|
|
|
|
HapticFeedback.mediumImpact();
|
|
|
|
|
} else if (velocity < -threshold) {
|
|
|
|
|
audioController.playNext();
|
|
|
|
|
HapticFeedback.mediumImpact();
|
|
|
|
|
}
|
|
|
|
|
} : null,
|
|
|
|
|
if (velocity > threshold) {
|
|
|
|
|
audioController.playPrevious();
|
|
|
|
|
HapticFeedback.mediumImpact();
|
|
|
|
|
} else if (velocity < -threshold) {
|
|
|
|
|
audioController.playNext();
|
|
|
|
|
HapticFeedback.mediumImpact();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
: null,
|
|
|
|
|
child: Container(
|
|
|
|
|
height: 64, // 增加高度使布局更加宽敞
|
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
@ -207,12 +208,15 @@ class MiniPlayer extends StatelessWidget {
|
|
|
|
|
child: Hero(
|
|
|
|
|
tag: 'album_cover',
|
|
|
|
|
flightShuttleBuilder: (
|
|
|
|
|
BuildContext flightContext,
|
|
|
|
|
Animation<double> animation,
|
|
|
|
|
HeroFlightDirection flightDirection,
|
|
|
|
|
BuildContext fromHeroContext,
|
|
|
|
|
BuildContext toHeroContext,
|
|
|
|
|
) {
|
|
|
|
|
BuildContext flightContext,
|
|
|
|
|
Animation<double> animation,
|
|
|
|
|
HeroFlightDirection flightDirection,
|
|
|
|
|
BuildContext fromHeroContext,
|
|
|
|
|
BuildContext toHeroContext,
|
|
|
|
|
) {
|
|
|
|
|
if (!hasPlaylist) {
|
|
|
|
|
return const Icon(Icons.music_note, size: 30);
|
|
|
|
|
}
|
|
|
|
|
return ClipRRect(
|
|
|
|
|
borderRadius: BorderRadius.circular(8),
|
|
|
|
|
clipBehavior: Clip.hardEdge,
|
|
|
|
@ -220,10 +224,13 @@ class MiniPlayer extends StatelessWidget {
|
|
|
|
|
width: 48,
|
|
|
|
|
height: 48,
|
|
|
|
|
child: Image.network(
|
|
|
|
|
audioController.songList[audioController.currentSongIndex.value].pic,
|
|
|
|
|
audioController
|
|
|
|
|
.songList[
|
|
|
|
|
audioController.currentSongIndex.value]
|
|
|
|
|
.pic,
|
|
|
|
|
fit: BoxFit.cover,
|
|
|
|
|
errorBuilder: (context, error, stackTrace) =>
|
|
|
|
|
const Icon(Icons.music_note, size: 30),
|
|
|
|
|
const Icon(Icons.music_note, size: 30),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
@ -234,38 +241,20 @@ class MiniPlayer extends StatelessWidget {
|
|
|
|
|
child: Obx(() {
|
|
|
|
|
final currentSong = audioController.songList.isEmpty
|
|
|
|
|
? null
|
|
|
|
|
: audioController.songList[audioController.currentSongIndex.value];
|
|
|
|
|
: audioController.songList[
|
|
|
|
|
audioController.currentSongIndex.value];
|
|
|
|
|
return AnimatedSwitcher(
|
|
|
|
|
duration: const Duration(milliseconds: 300),
|
|
|
|
|
child: currentSong != null
|
|
|
|
|
? Image.network(
|
|
|
|
|
currentSong.pic,
|
|
|
|
|
key: ValueKey(currentSong.pic),
|
|
|
|
|
width: 48,
|
|
|
|
|
height: 48,
|
|
|
|
|
fit: BoxFit.cover,
|
|
|
|
|
errorBuilder: (context, error, stackTrace) =>
|
|
|
|
|
const Icon(Icons.music_note, size: 30),
|
|
|
|
|
// loadingBuilder: (context, child, loadingProgress) {
|
|
|
|
|
// if (loadingProgress == null) return child;
|
|
|
|
|
// return Container(
|
|
|
|
|
// color: Colors.grey[100],
|
|
|
|
|
// width: 48,
|
|
|
|
|
// height: 48,
|
|
|
|
|
// child: Center(
|
|
|
|
|
// child: CircularProgressIndicator(
|
|
|
|
|
// strokeWidth: 2,
|
|
|
|
|
// valueColor: const AlwaysStoppedAnimation<Color>(
|
|
|
|
|
// Color(0xff429482)),
|
|
|
|
|
// value: loadingProgress.expectedTotalBytes != null
|
|
|
|
|
// ? loadingProgress.cumulativeBytesLoaded /
|
|
|
|
|
// loadingProgress.expectedTotalBytes!
|
|
|
|
|
// : null,
|
|
|
|
|
// ),
|
|
|
|
|
// ),
|
|
|
|
|
// );
|
|
|
|
|
// },
|
|
|
|
|
)
|
|
|
|
|
currentSong.pic,
|
|
|
|
|
key: ValueKey(currentSong.pic),
|
|
|
|
|
width: 48,
|
|
|
|
|
height: 48,
|
|
|
|
|
fit: BoxFit.cover,
|
|
|
|
|
errorBuilder: (context, error, stackTrace) =>
|
|
|
|
|
const Icon(Icons.music_note, size: 30),
|
|
|
|
|
)
|
|
|
|
|
: const Icon(Icons.music_note, size: 30),
|
|
|
|
|
);
|
|
|
|
|
}),
|
|
|
|
|