从页面导航到另一个页面时如何暂停颤动视频(video_player 插件)

div*_*ava 6 android ios dart flutter

我正在使用 flutter video_player( https://pub.dartlang.org/packages/video_player ) 插件来播放视频。但是当我在颤动中从一页导航到另一页时,视频仍在播放。从任何其他应用程序播放音乐时,我遇到了同样的问题(例如:播放颤动视频时从通知中播放音乐)。我怎样才能暂停它?

Sam*_*ehi 24

编辑: 第二个选项: 所以我想出了另一个解决方案。VisibilityDetector 是一个“小部件”,可以包装任何其他小部件并在小部件的可见区域发生变化时发出通知。

VisibilityDetector(
   key: Key("unique key"),
   onVisibilityChanged: (VisibilityInfo info) {
       debugPrint("${info.visibleFraction} of my widget is visible");
       if(info.visibleFraction == 0){
           videoPlayerController.pause();
       }
       else{
           videoPlayerController.play();
       }
   },
   child: VideoPlayer());
)
Run Code Online (Sandbox Code Playgroud)

第一个选项: 通过使用 ,当另一个屏幕被推到它上面时RouteObserverRouteAware你的小部件将被通知,或者它被弹回顶部。

首先,您需要添加一个RouteObservertoMaterialApp或您的Navigator.

RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      navigatorObservers: [routeObserver], //HERE
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

Run Code Online (Sandbox Code Playgroud)

然后您必须将RouteAwaremixin添加到您的小部件中,并将其订阅到RouteObserver.

class VideoPlayerItem extends StatefulWidget {
  final File file;

  VideoPlayerItem(this.file);

  @override
  _VideoPlayerItemState createState() => _VideoPlayerItemState();
}

class _VideoPlayerItemState extends State<VideoPlayerItem> with RouteAware {

  VideoPlayerController _videoPlayerController;

  @override
  void initState() {
    super.initState();
    _videoPlayerController = VideoPlayerController.file(widget.file);
    _videoPlayerController.initialize().then((_) {
      if (mounted) {
        setState(() {});
        _videoPlayerController.play();
      }
    });
  }

  @override
  void didChangeDependencies() {
    routeObserver.subscribe(this, ModalRoute.of(context));//Subscribe it here
    super.didChangeDependencies();
  }

  /// Called when the current route has been popped off.
  @override
  void didPop() {
    print("didPop");
    super.didPop();
  }

  /// Called when the top route has been popped off, and the current route
  /// shows up.
  @override
  void didPopNext() {
    print("didPopNext");
    _videoPlayerController.play();
    super.didPopNext();
  }

  /// Called when the current route has been pushed.
  @override
  void didPush() { 
    print("didPush");
    super.didPush();
  }

  /// Called when a new route has been pushed, and the current route is no
  /// longer visible.
  @override
  void didPushNext() {
    print("didPushNext");
    _videoPlayerController.pause();
    super.didPushNext();
  }


  @override
  Widget build(BuildContext context) {
    return _videoPlayerController?.value?.initialized ?? false
        ? AspectRatio(
            aspectRatio: _videoPlayerController.value.aspectRatio,
            child: VideoPlayer(_videoPlayerController),
          )
        : Container();
  }

  @override
  void dispose() {
    routeObserver.unsubscribe(this); //Don't forget to unsubscribe it!!!!!!
    super.dispose();
    _videoPlayerController.dispose();
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这个答案对我非常有帮助 - 因为我有视频列表并且多次面临竞争条件...如果您有视频列表,请将 autoinitialize 设置为 false ,将 autoplay 设置为 false 然后 _videoPlayerController.initialize().then ((_) { if (mounted) { setState(() {}); _videoPlayerController.play(); } }); (2认同)

anm*_*ail 1

你有 -VideoPlayerController _controller;

在导航到其他屏幕之前 -

 _controller.pause();  // add this
Navigator.push(
      context, MaterialPageRoute(builder: (BuildContext context) => NextPage()));
Run Code Online (Sandbox Code Playgroud)

或者

如果它是一个有状态的小部件,那么你可以重写 -dispose()方法。

@override
  void dispose() {
   super.dispose();
   _controller.pause();
  }
Run Code Online (Sandbox Code Playgroud)