Flutter video_player restart video from start on tap

7,045

Solution 1

I finally found a solution to my issue by calling initialize() again on the controller on the tap event if the video is no longer playing (i.e. the video finished already).

return AspectRatio(
  aspectRatio: _controller.value.aspectRatio,
  child: GestureDetector(
    onTap: () {
      if (!_controller.value.isPlaying) {
         setState(() {});
         _controller.initialize();
      }
    },
    child: VideoPlayer(_controller),
  ),
);

Solution 2

You need to rebuild the VideoPlayer if you changes anything in video playback. The most simple solution to your case is just fire build method again with a setState call.

/// ... after some code
child: GestureDetector(
          onTap: () async {
            await _controller.seekTo(Duration.zero);
            setState( () {
              _controller.play();
            } );
          },
          child: VideoPlayer(_controller),
        ),

Solution 3

I solve this problem in this way.

GestureDetector(
    onTap() {  
    if(_controller.value.position==_controller.value.duration){
            _controller.initialize();  
       }
     }
)

_controller.value.duration store the video duration, _controller.value.position store the actual position of the video and if the video reaches to the end the _controller.value.position will be equal by _controller.value.duration.

Share:
7,045
skuallpa
Author by

skuallpa

Updated on December 16, 2022

Comments

  • skuallpa
    skuallpa over 1 year

    I am using the flutter video_player package to play a short video file using in my application. I inspired from the flutter cookbook: Play and pause a video.

    I would like to allow the user to tap on the video to restart it from beginning. So I wrapped the VideoPlayer with a GestureDetector.

    I currently have the following code:

    class MyVideoPlayer extends StatefulWidget {
      final File videoFile;
    
      MyVideoPlayer({Key key, this.videoFile}) : super(key: key);
    
      @override
      _MyVideoPlayerState createState() => _MyVideoPlayerState();
    }
    
    class _MyVideoPlayerState extends State<MyVideoPlayer> {
      VideoPlayerController _controller;
      Future<void> _initializeVideoPlayerFuture;
    
      @override
      void initState() {
        _controller = VideoPlayerController.file(widget.videoFile);
        _initializeVideoPlayerFuture = _controller.initialize();
        super.initState();
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return FutureBuilder(
          future: _initializeVideoPlayerFuture,
          builder: (context, snapshot) {
            print(snapshot.connectionState);
            if (snapshot.connectionState == ConnectionState.done) {
              // Play video once it's loaded
              _controller.play();
    
              return AspectRatio(
                aspectRatio: _controller.value.aspectRatio,
                child: GestureDetector(
                  onTap: () async {
                    await _controller.seekTo(Duration.zero);
                    _controller.play();
                  },
                  child: VideoPlayer(_controller),
                ),
              );
            } else {
              return CircularProgressIndicator();
            }
          },
        );
      }
    }
    
    

    The video plays well once the video file is loaded (once the connection state passed to done), however, when I try to tap on the video to replay it a second time, it doesn't replay the video from start. The audio starts playing again, but video doesn't restart playing. Any idea?

    EDIT 1

    Following @marcosboaventura suggestion, I tried to wrap the calls in a setState to trigger the build method again:

    return AspectRatio(
      aspectRatio: _controller.value.aspectRatio,
      child: GestureDetector(
        onTap: () async {
          await _controller.seekTo(Duration.zero);
          setState(() {
            _controller.play();
          });
        },
        child: VideoPlayer(_controller),
      ),
    );
    

    But still the video doesn't replay, only the sound. Any other idea?