我可以在不实际解除小部件的情况下使用Dismissible吗?

3
我正在尝试制作一个小部件,可以通过滑动来更改播放列表中当前播放的歌曲。我试图模仿其他应用程序的做法,让用户滑动当前曲目和即将到来的下一首曲目。 Dismissible接近我实际想要的效果。它有一个漂亮的动画效果,我可以轻松使用onDismissed函数来处理逻辑。我的问题是Dismissible实际上想从树中删除小部件,这不是我想要的。
当歌曲更改时,我正在使用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
1个回答

5

这可以通过使用confirmDismiss回调而不是onDismiss回调来完成。为了确保小部件实际上从未被解除,您需要在函数末尾返回false。

Dismissible(
    confirmDismiss: (direction) {
        ...
        return false;
    }
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接