颤动倒数计时器

Flo*_*epa 17 timer countdown dart flutter

如何将传递的值放入构造中,使计时器四舍五入到小数点后一位并显示在RaisedButton的子文本中?我已经尝试过但没有运气。我设法使用一个简单的Timer来使回调函数起作用,但没有周期性,并且文本中没有实时更新值...

import 'package:flutter/material.dart';
import 'dart:ui';
import 'dart:async';

class TimerButton extends StatefulWidget {
  final Duration timerTastoPremuto;


  TimerButton(this.timerTastoPremuto);

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

class _TimerButtonState extends State<TimerButton> {
  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.all(5.0),
      height: 135.0,
      width: 135.0,
      child: new RaisedButton(
        elevation: 100.0,
        color: Colors.white.withOpacity(.8),
        highlightElevation: 0.0,
        onPressed: () {
          int _start = widget.timerTastoPremuto.inMilliseconds;

          const oneDecimal = const Duration(milliseconds: 100);
          Timer _timer = new Timer.periodic(
              oneDecimal,
                  (Timer timer) =>
                  setState(() {
                    if (_start < 100) {
                      _timer.cancel();
                    } else {
                      _start = _start - 100;
                    }
                  }));

        },
        splashColor: Colors.red,
        highlightColor: Colors.red,
        //shape: RoundedRectangleBorder e tutto il resto uguale
        shape: BeveledRectangleBorder(
            side: BorderSide(color: Colors.black, width: 2.5),
            borderRadius: new BorderRadius.circular(15.0)),
        child: new Text(
          "$_start",
          style: new TextStyle(fontFamily: "Minim", fontSize: 50.0),
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

Yan*_*n39 35

这是使用Timer.periodic的示例:

倒数开始从100按钮点击:

import 'dart:async';

[...]

Timer _timer;
int _start = 10;

void startTimer() {
  const oneSec = const Duration(seconds: 1);
  _timer = new Timer.periodic(
    oneSec,
    (Timer timer) => setState(
      () {
        if (_start < 1) {
          timer.cancel();
        } else {
          _start = _start - 1;
        }
      },
    ),
  );
}

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

Widget build(BuildContext context) {
  return new Scaffold(
    appBar: AppBar(title: Text("Timer test")),
    body: Column(
      children: <Widget>[
        RaisedButton(
          onPressed: () {
            startTimer();
          },
          child: Text("start"),
        ),
        Text("$_start")
      ],
    ),
  );
}
Run Code Online (Sandbox Code Playgroud)

结果:

颤动倒数计时器示例

您还可以使用quiver.async库中的CountdownTimer类,用法更加简单:

import 'package:quiver/async.dart';

[...]

int _start = 10;
int _current = 10;

void startTimer() {
  CountdownTimer countDownTimer = new CountdownTimer(
    new Duration(seconds: _start),
    new Duration(seconds: 1),
  );

  var sub = countDownTimer.listen(null);
  sub.onData((duration) {
    setState(() { _current = _start - duration.elapsed.inSeconds; });
  });

  sub.onDone(() {
    print("Done");
    sub.cancel();
  });
}

Widget build(BuildContext context) {
  return new Scaffold(
    appBar: AppBar(title: Text("Timer test")),
    body: Column(
      children: <Widget>[
        RaisedButton(
          onPressed: () {
            startTimer();
          },
          child: Text("start"),
        ),
        Text("$_current")
      ],
    ),
  );
}
Run Code Online (Sandbox Code Playgroud)

  • “ Timer”创建一个新的计时器,其回调函数在指定的持续时间后仅被调用一次(例如,延迟操作)。“ Timer.periodic”会创建一个新的“重复”定时器,以便根据指定的持续时间间隔重复调用回调函数。如果要显示十进制数字,请使用“ double”而不是“ int”。如果您的问题是更改间隔以使其减少0.1,则只需在上面的代码中将“ 1”更改为“ 0.1”即可。最后,如果您需要格式化输出,请参阅[NumberFormat](https://docs.flutter.io/flutter/intl/NumberFormat-class.html)。 (3认同)

Fav*_* Kv 15

这是我的计时器小部件,与问题无关,但可以帮助某人。

import 'dart:async';

import 'package:flutter/material.dart';

class OtpTimer extends StatefulWidget {
  @override
  _OtpTimerState createState() => _OtpTimerState();
}

class _OtpTimerState extends State<OtpTimer> {
  final interval = const Duration(seconds: 1);

  final int timerMaxSeconds = 60;

  int currentSeconds = 0;

  String get timerText =>
      '${((timerMaxSeconds - currentSeconds) ~/ 60).toString().padLeft(2, '0')}: ${((timerMaxSeconds - currentSeconds) % 60).toString().padLeft(2, '0')}';

  startTimeout([int milliseconds]) {
    var duration = interval;
    Timer.periodic(duration, (timer) {
      setState(() {
        print(timer.tick);
        currentSeconds = timer.tick;
        if (timer.tick >= timerMaxSeconds) timer.cancel();
      });
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Icon(Icons.timer),
        SizedBox(
          width: 5,
        ),
        Text(timerText)
      ],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

你会得到这样的东西

在此处输入图片说明

  • 您必须使用小部件的已安装检查来包装您的 startTimeout 函数,如下所示 if(mounted){startTimeout();} ,否则您将因 setState 和异步代码的影响而导致内存泄漏 (2认同)

Ana*_*nan 12

我创建了一个很棒的计时器,没有任何插件,在这里您还可以获得倒计时器。并且不要忘记停止按下背面的计时器。

这是我的计时器完整项目的链接。 *希望这会对某人有所帮助。谢谢。 *

在此输入图像描述

   import 'dart:async';

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: AttendanceScreen(),
    );
  }
}

class AttendanceScreen extends StatefulWidget {
  AttendanceScreen();

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

class _AttendanceScreenState extends State<AttendanceScreen> {
  static var countdownDuration = Duration(minutes: 10);
  static var countdownDuration1 = Duration(minutes: 10);
  Duration duration = Duration();
  Duration duration1 = Duration();
  Timer? timer;
  Timer? timer1;
  bool countDown = true;
  bool countDown1 = true;

  @override
  void initState() {
    var hours;
    var mints;
    var secs;
    hours = int.parse("00");
    mints = int.parse("00");
    secs = int.parse("00");
    countdownDuration = Duration(hours: hours, minutes: mints, seconds: secs);
    startTimer();
    reset();
    var hours1;
    var mints1;
    var secs1;
    hours1 = int.parse("10");
    mints1 = int.parse("00");
    secs1 = int.parse("00");
    countdownDuration1 =
        Duration(hours: hours1, minutes: mints1, seconds: secs1);
    startTimer1();
    reset1();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: _onWillPop,
      child: Scaffold(
        appBar: AppBar(
          title: Text("Timer Example"),
          leading: IconButton(
            icon: Icon(Icons.arrow_back_ios),
            color: Colors.white,
            onPressed: () {
              _onWillPop();
            },
          ),
        ),
        body: Container(
          color: Colors.black12,
          width: double.infinity,
          child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                SizedBox(
                  height: 20,
                ),
                Text(
                  "Timer",
                  style: TextStyle(fontSize: 25),
                ),
                Container(
                    margin: EdgeInsets.only(top: 30, bottom: 30),
                    child: buildTime()),
                SizedBox(
                  height: 20,
                ),
                Text(
                  "Count down timer",
                  style: TextStyle(fontSize: 25),
                ),
                Container(
                    margin: EdgeInsets.only(top: 30, bottom: 30),
                    child: buildTime1()),
              ]),
        ),
      ),
    );
  }

  Future<bool> _onWillPop() async {
    final isRunning = timer == null ? false : timer!.isActive;
    if (isRunning) {
      timer!.cancel();
    }
    Navigator.of(context, rootNavigator: true).pop(context);
    return true;
  }

  void reset() {
    if (countDown) {
      setState(() => duration = countdownDuration);
    } else {
      setState(() => duration = Duration());
    }
  }

  void reset1() {
    if (countDown) {
      setState(() => duration1 = countdownDuration1);
    } else {
      setState(() => duration1 = Duration());
    }
  }

  void startTimer() {
    timer = Timer.periodic(Duration(seconds: 1), (_) => addTime());
  }

  void startTimer1() {
    timer = Timer.periodic(Duration(seconds: 1), (_) => addTime1());
  }

  void addTime() {
    final addSeconds = 1;
    setState(() {
      final seconds = duration.inSeconds + addSeconds;
      if (seconds < 0) {
        timer?.cancel();
      } else {
        duration = Duration(seconds: seconds);
      }
    });
  }

  void addTime1() {
    final addSeconds = 1;
    setState(() {
      final seconds = duration1.inSeconds - addSeconds;
      if (seconds < 0) {
        timer1?.cancel();
      } else {
        duration1 = Duration(seconds: seconds);
      }
    });
  }

  Widget buildTime() {
    String twoDigits(int n) => n.toString().padLeft(2, '0');
    final hours = twoDigits(duration.inHours);
    final minutes = twoDigits(duration.inMinutes.remainder(60));
    final seconds = twoDigits(duration.inSeconds.remainder(60));
    return Row(mainAxisAlignment: MainAxisAlignment.center, children: [
      buildTimeCard(time: hours, header: 'HOURS'),
      SizedBox(
        width: 8,
      ),
      buildTimeCard(time: minutes, header: 'MINUTES'),
      SizedBox(
        width: 8,
      ),
      buildTimeCard(time: seconds, header: 'SECONDS'),
    ]);
  }

  Widget buildTime1() {
    String twoDigits(int n) => n.toString().padLeft(2, '0');
    final hours = twoDigits(duration1.inHours);
    final minutes = twoDigits(duration1.inMinutes.remainder(60));
    final seconds = twoDigits(duration1.inSeconds.remainder(60));
    return Row(mainAxisAlignment: MainAxisAlignment.center, children: [
      buildTimeCard(time: hours, header: 'HOURS'),
      SizedBox(
        width: 8,
      ),
      buildTimeCard(time: minutes, header: 'MINUTES'),
      SizedBox(
        width: 8,
      ),
      buildTimeCard(time: seconds, header: 'SECONDS'),
    ]);
  }

  Widget buildTimeCard({required String time, required String header}) =>
      Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Container(
            padding: EdgeInsets.all(8),
            decoration: BoxDecoration(
                color: Colors.white, borderRadius: BorderRadius.circular(20)),
            child: Text(
              time,
              style: TextStyle(
                  fontWeight: FontWeight.bold,
                  color: Colors.black,
                  fontSize: 50),
            ),
          ),
          SizedBox(
            height: 24,
          ),
          Text(header, style: TextStyle(color: Colors.black45)),
        ],
      );
}
Run Code Online (Sandbox Code Playgroud)


Sor*_*omo 9

不直接回答你的问题。但对于那些想在一段时间后开始某事的人很有帮助。

Future.delayed(Duration(seconds: 1), () {
            print('yo hey');
          });
Run Code Online (Sandbox Code Playgroud)

  • 延迟操作是否会在 Flutter/Mobile 应用程序中的主机程序被杀死后继续存在? (2认同)

mah*_*mnj 9

派对有点晚了,但你们为什么不尝试动画。不,我不是告诉你管理动画控制器并将它们处理掉和所有这些东西。有一个名为TweenAnimationBuilder的内置小部件。你可以在值之间设置动画任何类型,这是一个带有 Duration 类的示例

TweenAnimationBuilder<Duration>(
  duration: Duration(minutes: 3),
  tween: Tween(begin: Duration(minutes: 3), end: Duration.zero),
  onEnd: () {
    print('Timer ended');
  },
  builder: (BuildContext context, Duration value, Widget child) {
    final minutes = value.inMinutes;
    final seconds = value.inSeconds % 60;
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 5),
      child: Text('$minutes:$seconds',
               textAlign: TextAlign.center,
               style: TextStyle(
               color: Colors.black,
               fontWeight: FontWeight.bold,
               fontSize: 30)));
    }),
Run Code Online (Sandbox Code Playgroud)

并且您还会收到 onEnd 回调,它会在动画完成时通知您;

这是输出


小智 7

如果您只需要一个简单的倒计时器,那么这是一个很好的选择,而不是安装软件包。快乐编码!

countDownTimer() async {
 int timerCount;
 for (int x = 5; x > 0; x--) {
   await Future.delayed(Duration(seconds: 1)).then((_) {
     setState(() {
       timerCount -= 1;
    });
  });
 }
}
Run Code Online (Sandbox Code Playgroud)


Wit*_*ult 5

I have created a Generic Timer Widget which can be used to display any kind of timer and its flexible as well.

This Widget takes following properties

  1. secondsRemaining: duration for which timer needs to run in seconds
  2. whenTimeExpires: what action needs to be performed if timer finished
  3. countDownStyle: any kind of style which you want to give to timer
  4. countDownFormatter:用户希望显示倒数计时器的方式,例如 hh mm ss字符串01 hours: 20 minutes: 45 seconds

您可以提供默认的格式化程序(formatHHMMSS),以防您不想在每个地方都提供它。

//为此提供实现- formatHHMMSS(duration.inSeconds);或在我提供的代码以下使用。

import 'package:flutter/material.dart';
class CountDownTimer extends StatefulWidget {
  const CountDownTimer({
    Key key,
    int secondsRemaining,
    this.countDownTimerStyle,
    this.whenTimeExpires,
    this.countDownFormatter,
  })  : secondsRemaining = secondsRemaining,
        super(key: key);

  final int secondsRemaining;
  final Function whenTimeExpires;
  final Function countDownFormatter;
  final TextStyle countDownTimerStyle;

  State createState() => new _CountDownTimerState();
}

class _CountDownTimerState extends State<CountDownTimer>
    with TickerProviderStateMixin {
  AnimationController _controller;
  Duration duration;

  String get timerDisplayString {
    Duration duration = _controller.duration * _controller.value;
    return widget.countDownFormatter != null
        ? widget.countDownFormatter(duration.inSeconds)
        : formatHHMMSS(duration.inSeconds);
      // In case user doesn't provide formatter use the default one
     // for that create a method which will be called formatHHMMSS or whatever you like
  }

  @override
  void initState() {
    super.initState();
    duration = new Duration(seconds: widget.secondsRemaining);
    _controller = new AnimationController(
      vsync: this,
      duration: duration,
    );
    _controller.reverse(from: widget.secondsRemaining.toDouble());
    _controller.addStatusListener((status) {
      if (status == AnimationStatus.completed || status == AnimationStatus.dismissed) {
        widget.whenTimeExpires();
      }
    });
  }

  @override
  void didUpdateWidget(CountDownTimer oldWidget) {
    if (widget.secondsRemaining != oldWidget.secondsRemaining) {
      setState(() {
        duration = new Duration(seconds: widget.secondsRemaining);
        _controller.dispose();
        _controller = new AnimationController(
          vsync: this,
          duration: duration,
        );
        _controller.reverse(from: widget.secondsRemaining.toDouble());
        _controller.addStatusListener((status) {
          if (status == AnimationStatus.completed) {
            widget.whenTimeExpires();
          } else if (status == AnimationStatus.dismissed) {
            print("Animation Complete");
          }
        });
      });
    }
  }

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

  @override
  Widget build(BuildContext context) {
    return new Center(
        child: AnimatedBuilder(
            animation: _controller,
            builder: (_, Widget child) {
              return Text(
                timerDisplayString,
                style: widget.countDownTimerStyle,
              );
            }));
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

 Container(
       width: 60.0,
       padding: EdgeInsets.only(top: 3.0, right: 4.0),
         child: CountDownTimer(
           secondsRemaining: 30,
           whenTimeExpires: () {
              setState(() {
                hasTimerStopped = true;
              });
            },
            countDownStyle: TextStyle(
                color: Color(0XFFf5a623),
                fontSize: 17.0,
                height: 1.2),
          ),
        )
Run Code Online (Sandbox Code Playgroud)

formatHHMMSS的示例:

String formatHHMMSS(int seconds) {
  int hours = (seconds / 3600).truncate();
  seconds = (seconds % 3600).truncate();
  int minutes = (seconds / 60).truncate();

  String hoursStr = (hours).toString().padLeft(2, '0');
  String minutesStr = (minutes).toString().padLeft(2, '0');
  String secondsStr = (seconds % 60).toString().padLeft(2, '0');

  if (hours == 0) {
    return "$minutesStr:$secondsStr";
  }

  return "$hoursStr:$minutesStr:$secondsStr";
}
Run Code Online (Sandbox Code Playgroud)