因为倒计时的场景多种多样,所以只提供一个倒计时容器控件,具体内容布局具体实现。
源码:
class CountDownWidgetWrapper extends StatefulWidget {
  final CountDownWidgetBuilder builder;
  final CountdownController controller;
  const CountDownWidgetWrapper(
      {Key key, @required this.builder, @required this.controller})
      : super(key: key);
  @override
  _CountDownWidgetWrapperState createState() => _CountDownWidgetWrapperState();
}
class _CountDownWidgetWrapperState extends State<CountDownWidgetWrapper> {
  @override
  void initState() {
    super.initState();
    widget.controller._countDownChanged = () {
      setState(() {});
    };
  }
  @override
  Widget build(BuildContext context) =>
      widget.builder.call(widget.controller.count);
  @override
  void dispose() {
    super.dispose();
    widget.controller.cancel();
  }
}
typedef CountDownWidgetBuilder = Widget Function(int count);
class CountdownController {
  final int startCount;
  final int endCount;
  int _countDown = 0;
  int get count => _countDown;
  VoidCallback _countDownChanged;
  Timer _timer;
  CountdownController({this.startCount = 60, this.endCount = 0});
  void start() {
    _countDown = startCount;
    _countDownChanged.call();
    cancel();
    _timer = new Timer.periodic(
      Duration(seconds: 1),
      (Timer timer) {
        if (_countDown == endCount) {
          timer.cancel();
        } else {
          _countDown--;
        }
        _countDownChanged.call();
      },
    );
  }
  void cancel() {
    if (_timer != null && _timer.isActive) {
      _timer.cancel();
    }
  }
}
使用:
class TestWidget extends StatefulWidget {
  @override
  _TestWidgetState createState() => _TestWidgetState();
}
class _TestWidgetState extends State<TestWidget> {
  CountdownController controller = CountdownController(startCount: 30);
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        CountDownWidgetWrapper(
            builder: (count) {
              return Text('倒计时$count');
            },
            controller: controller),
        TextButton(
            onPressed: () {
              controller.start();
            },
            child: Text('开始'))
      ],
    );
  }
}