简体   繁体   中英

Flutter: Countdown timer that displays minutes and seconds

I have created a countdown timer that will countdown from a user inputted duration, in minutes.

The countdown timer technically works, but only the minutes are being shown counting down. The seconds remain at :00 the entire time.

How can I get the seconds to also display as part of the countdown timer?

Here is the relevant code, excerpted from a longer file. I can include more if needed.

The individual pieces of code are broken down as follows:

First, I have a class that actually displays the timer text and allows it to be styled:

class Countdown extends AnimatedWidget {
  Countdown({ Key key, this.animation }) : super(key: key, listenable: animation);
  Animation<int> animation;

  @override

  build(BuildContext context){

    Duration clockTimer = Duration(seconds: animation.value*60);

    String timerText = '${clockTimer.inMinutes.remainder(60).toString()}:${(clockTimer.inSeconds.remainder(60) % 60).toString().padLeft(2, '0')}';

    return Text(
      "$timerText",
      style: TextStyle(         
        fontSize: 110,
        color: Theme.of(context).primaryColor,
      ),
    );

  }
}

I have an animation controller as follows:

AnimationController _controller;

  @override

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

  void initState() {
    super.initState();
    @override

      _controller = AnimationController(
          vsync: this,
        duration: Duration(minutes: gameData.levelClock)  // gameData.levelClock is a user entered number elsewhere in the applciation
      );


  }

And finally here is the part of the code that calls the Countdown widget:

Countdown(
     animation: StepTween(
     begin: gameData.levelClock,   // THIS IS A USER ENTERED NUMBER 
     end: 0,
   ).animate(_controller),
)

Thank you for any help that can be offered.

You can copy paste run full code below
Your duration of AnimationController need to use seconds
code snippet

_controller = AnimationController(
        vsync: this,
        duration: Duration(
            seconds:
                levelClock) // gameData.levelClock is a user entered number elsewhere in the applciation
        );

working demo

在此处输入图片说明

full code

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

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

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  int _counter = 0;
  AnimationController _controller;
  int levelClock = 180;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

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

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
        vsync: this,
        duration: Duration(
            seconds:
                levelClock) // gameData.levelClock is a user entered number elsewhere in the applciation
        );

    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Countdown(
              animation: StepTween(
                begin: levelClock, // THIS IS A USER ENTERED NUMBER
                end: 0,
              ).animate(_controller),
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class Countdown extends AnimatedWidget {
  Countdown({Key key, this.animation}) : super(key: key, listenable: animation);
  Animation<int> animation;

  @override
  build(BuildContext context) {
    Duration clockTimer = Duration(seconds: animation.value);

    String timerText =
        '${clockTimer.inMinutes.remainder(60).toString()}:${clockTimer.inSeconds.remainder(60).toString().padLeft(2, '0')}';

    print('animation.value  ${animation.value} ');
    print('inMinutes ${clockTimer.inMinutes.toString()}');
    print('inSeconds ${clockTimer.inSeconds.toString()}');
    print('inSeconds.remainder ${clockTimer.inSeconds.remainder(60).toString()}');

    return Text(
      "$timerText",
      style: TextStyle(
        fontSize: 110,
        color: Theme.of(context).primaryColor,
      ),
    );
  }
}

So the problem is that when you create the CountDown widget you set begin to a double value which is the value in minutes for your timer(for this example say the value is 5). As the animation continues it will count down from begin to end (0 in this case). Over 5 minutes it will animate from 5 to 0.

You then use the value and convert it to seconds but since the value of the animation is between 0 and 5 it will always give you 5:00, 4:00, 3:00, 2:00, 1:00 or 0:00.

The solution would be to change your code to

Countdown(
     animation: StepTween(
     begin: gameData.levelClock * 60, // convert to seconds here
     end: 0,
   ).animate(_controller),
)

and then in your countdown widget change the Duration to

Duration clockTimer = Duration(seconds: animation.value);

You can find a working example on DartPad here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM