我正在尝试制作一个小部件,可以通过滑动来更改播放列表中当前播放的歌曲。我试图模仿其他应用程序的做法,让用户滑动当前曲目和即将到来的下一首曲目。 Dismissible接近我实际想要的效果。它有一个漂亮的动画效果,我可以轻松使用onDismissed函数来处理逻辑。我的问题是Dismissible实际上想从树中删除小部件,这不是我想要的。
当歌曲更改时,我正在使用StreamBuilder更新我正在滑动的小部件,因此能够将小部件滑到新的小部件上将是完美的。我可以这样做吗?还是有更适合我需要的小部件?
这是我正在工作的小部件:
这是我想要的效果(虽然我想要整个ListTile被滑动,而不仅仅是歌曲名称):https://i.imgur.com/ZapzpJS.mp4
当歌曲更改时,我正在使用StreamBuilder更新我正在滑动的小部件,因此能够将小部件滑到新的小部件上将是完美的。我可以这样做吗?还是有更适合我需要的小部件?
这是我正在工作的小部件:
class NowPlayingBar extends StatelessWidget {
const NowPlayingBar({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return StreamBuilder<ScreenState>(
stream: _screenStateStream,
builder: (context, snapshot) {
if (snapshot.hasData) {
final screenState = snapshot.data;
final queue = screenState.queue;
final mediaItem = screenState.mediaItem;
final state = screenState.playbackState;
final processingState =
state?.processingState ?? AudioProcessingState.none;
final playing = state?.playing ?? false;
if (mediaItem != null) {
return Container(
width: MediaQuery.of(context).size.width,
child: Dismissible(
key: Key("NowPlayingBar"),
onDismissed: (direction) {
switch (direction) {
case DismissDirection.startToEnd:
AudioService.skipToNext();
break;
case DismissDirection.endToStart:
AudioService.skipToPrevious();
break;
default:
throw ("Unsupported swipe direction ${direction.toString()} on NowPlayingBar!");
}
},
child: ListTile(
leading: AlbumImage(itemId: mediaItem.id),
title: mediaItem == null ? null : Text(mediaItem.title),
subtitle: mediaItem == null ? null : Text(mediaItem.album),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (playing)
IconButton(
onPressed: () => AudioService.pause(),
icon: Icon(Icons.pause))
else
IconButton(
onPressed: () => AudioService.play(),
icon: Icon(Icons.play_arrow)),
],
),
),
),
);
} else {
return Container(
width: MediaQuery.of(context).size.width,
child: ListTile(
title: Text("Nothing playing..."),
));
}
} else {
return Container(
width: MediaQuery.of(context).size.width,
// The child below looks pretty stupid but it's actually genius.
// I wanted the NowPlayingBar to stay the same length when it doesn't have data
// but I didn't want to actually use a ListTile to tell the user that.
// I use a ListTile to create a box with the right height, and put whatever I want on top.
// I could just make a container with the length of a ListTile, but that value could change in the future.
child: Stack(
alignment: Alignment.center,
children: [
ListTile(),
Text(
"Nothing Playing...",
style: TextStyle(color: Colors.grey, fontSize: 18),
)
],
));
}
},
);
}
}
这是我想要的效果(虽然我想要整个ListTile被滑动,而不仅仅是歌曲名称):https://i.imgur.com/ZapzpJS.mp4