如果在 Flutter 上导航到另一个屏幕,则停止计时器

Stop the timer if navigate to another screen on Flutter

我有一个视频播放到所需的持续时间(计时器)。计时器完成后,它将导航到另一个屏幕。 另外,如果用户想跳过视频转到下一个屏幕,我有一个跳过按钮。 这是问题所在,如果用户单击跳过按钮,计时器仍然是 运行,即使用户跳过视频,屏幕也会更新。 我希望当用户选择跳过时计时器停止。

代码:

//imports

class _VideoAppState extends State<additionVideo> {
  late VideoPlayerController _controller; //the controller of the video player

  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.asset('assets.mp4')
      ..initialize().then((_) {
        _controller.setVolume(1.0); //video sound (volume)
        _controller.setLooping(false); //do not repeat the video when finish
        _controller.play(); //play the video

        //navigate to the question page when the video is finished
        Timer(
            Duration(seconds: 38), //the wanted duration for the timer
            () => Navigator.pushReplacement(
                context,
                MaterialPageRoute(
                  builder: (context) => const HomeScreen(),
                )));

        setState(() {});
      });
  }

  @override
  Widget build(BuildContext context) {
    //fit to the screen
    double width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;
    return MaterialApp(
      home: Stack(
        children: <Widget>[
          SizedBox.expand(
            child: FittedBox(
              fit: BoxFit.cover,
              child: SizedBox(
                width: width,
                height: height,
                child: VideoPlayer(_controller),
              ),
            ),
          ),
          Container(
            alignment: Alignment.topRight,
            padding: EdgeInsets.all(30.0),
            child: NiceButtons(
                //A skip button to go to the questions page
                stretch: false,
                startColor: Colors.lightBlueAccent,
                endColor: Colors.lightBlueAccent,
                borderColor: Color(0xFF3489e9),
                width: 100.0,
                height: 60,
                borderRadius: 60,
                gradientOrientation: GradientOrientation.Horizontal,
                onTap: (finish) {
                  //Navigate to the questions page
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => const HomeScreen()),
                  );
                  _controller
                      .pause(); //stop the video when naviagte to the questions page
                },
                child: Text('skip',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                        decoration: TextDecoration.none,
                        fontSize: 20.0,
                        color: Colors.white,
                        fontFamily: 'ReadexPro-Regular',
                        fontWeight: FontWeight.bold))),
          ),
        ],
      ),
      debugShowCheckedModeBanner: false,
    );
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }
}

试试看:

onTap: (finish) {
              //Navigate to the questions page
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const HomeScreen()),
              );
             setState(() {
               _controller
                  .pause();
    });
               //stop the video when naviagte to the questions page
            },

要实现此目的,您需要在单击“跳过”按钮时取消计时器。 所以在这里我在 initstate 方法中初始化计时器,当用户点击跳过按钮时计时器被取消并导航到其他页面。

class _VideoAppState extends State<additionVideo> {
  late VideoPlayerController _controller; //the controller of the video player
  late Timer timer;
  @override
  void initState() {
    super.initState();
    _controller = VideoPlayerController.asset('assets.mp4')
      ..initialize().then((_) {
        _controller.setVolume(1.0); //video sound (volume)
        _controller.setLooping(false); //do not repeat the video when finish
        _controller.play(); //play the video

        //navigate to the question page when the video is finished
        timer = Timer(
            Duration(seconds: 38), //the wanted duration for the timer
                () => Navigator.pushReplacement(
                context,
                MaterialPageRoute(
                  builder: (context) => const HomeScreen(),
                )));

        setState(() {});
      });
  }

  @override
  Widget build(BuildContext context) {
    //fit to the screen
    double width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;
    return MaterialApp(
      home: Stack(
        children: <Widget>[
          SizedBox.expand(
            child: FittedBox(
              fit: BoxFit.cover,
              child: SizedBox(
                width: width,
                height: height,
                child: VideoPlayer(_controller),
              ),
            ),
          ),
          Container(
            alignment: Alignment.topRight,
            padding: EdgeInsets.all(30.0),
            child: NiceButtons(
              //A skip button to go to the questions page
                stretch: false,
                startColor: Colors.lightBlueAccent,
                endColor: Colors.lightBlueAccent,
                borderColor: Color(0xFF3489e9),
                width: 100.0,
                height: 60,
                borderRadius: 60,
                gradientOrientation: GradientOrientation.Horizontal,
                onTap: (finish) {
                  timer.cancel();
                  //Navigate to the questions page
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (context) => const HomeScreen()),
                  );
                  _controller.pause(); //stop the video when naviagte to the questions page
                },
                child: Text('skip',
                    textAlign: TextAlign.center,
                    style: TextStyle(
                        decoration: TextDecoration.none,
                        fontSize: 20.0,
                        color: Colors.white,
                        fontFamily: 'ReadexPro-Regular',
                        fontWeight: FontWeight.bold))),
          ),
        ],
      ),
      debugShowCheckedModeBanner: false,
    );
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
    timer.cancel();
  }
}

解决方案是定义对计时器的引用并在处理时取消它。

现场:

Timer(
            Duration(seconds: 38), //the wanted duration for the timer
            () => Navigator.pushReplacement(
                context,
                MaterialPageRoute(
                  builder: (context) => const HomeScreen(),
                )));

这样写:

var timer = Timer(
                Duration(seconds: 38), //the wanted duration for the timer
                () => Navigator.pushReplacement(
                    context,
                    MaterialPageRoute(
                      builder: (context) => const HomeScreen(),
                    )));

onDispose 将是这样的:

@override
  void dispose() {
    super.dispose();
    _controller.dispose();
    timer.cancel();
  }

声明timer

late Timer timer;

初始化timer

@override
  void initState() {
    super.initState();
    timer = Timer(
            Duration(seconds: 38),
                () => Navigator.pushReplacement(
                context,
                MaterialPageRoute(
                  builder: (context) => const HomeScreen(),
                )));

        setState(() {});
  }

@override
  void dispose() {
    super.dispose();
    timer.cancel();
  }

取消 timer onTaponPressed 功能或 dispose timer

timer.cancel();