Flutter 倒計時功能

一、說明

要實現一個類似上圖中滑動列表項倒計時功能,其中剩餘時間是需要每分鐘更新一次。

二、功能實現

class ItemOrderWidget extends StatefulWidget {

  final OrderEntity order;

  ItemOrderWidget({
    Key key,
    this.order,
  }) : super(key: key);

  @override
  _ItemOrderWidgetState createState() {
    return _ItemOrderWidgetState();
  }
}

class _ItemOrderWidgetState extends State<ItemOrderWidget> {

  // 用來在佈局中顯示相應的剩餘時間
  String remainTime = '';
  Timer _timer;

  @override
  void initState() {
    super.initState();
    // 初始化的時候開啓倒計時
    startCountDown(widget.order.validEndTime);
  }

  @override
  void dispose() {
    super.dispose();
    // 在頁面回收或滑動複用回收的時候一定要把 timer 清除
    if (_timer != null) {
      if (_timer.isActive) {
        _timer.cancel();
        _timer = null;
      }
    }
  }

  @override
  void didUpdateWidget(ItemOrderWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    // 外部重新請求接口後重新進行倒計時,這個方法是用來監控外部 setState 的
    startCountDown(widget.order.validEndTime);
  }

  
  void startCountDown(time){
    var nowTime = DateTime.now();
    var endTime = DateTime.parse(time.toString());

    // 如果剩餘時間已經不足一分鐘,則不必計時,直接標記超時
    if (endTime.millisecondsSinceEpoch - nowTime.millisecondsSinceEpoch < 1000 * 60) {
      setState(() {
        remainTime = '超時';
      });

      return;
    }

    // 重新計時的時候要把之前的清除掉
    if (_timer != null) {
      if (_timer.isActive) {
        _timer.cancel();
        _timer = null;
      }
    }

    const repeatPeriod = const Duration(minutes: 1);

    caculateTime(nowTime, endTime);

    _timer = Timer.periodic(repeatPeriod, (timer) {
      //到時回調
      nowTime = nowTime.add(repeatPeriod);

      if (endTime.millisecondsSinceEpoch - nowTime.millisecondsSinceEpoch < 1000 * 60) {
        //取消定時器,避免無限回調
        timer.cancel();
        timer = null;

        setState(() {
          remainTime = '超時';
        });

        return;
      }

      caculateTime(nowTime, endTime);
    });
  }

  /// 計算天數、小時、分鐘、秒
  void caculateTime(nowTime, endTime) {
    var _surplus = endTime.difference(nowTime);
    int day = (_surplus.inSeconds ~/ 3600) ~/ 24;
    int hour = (_surplus.inSeconds ~/ 3600) % 24;
    int minute = _surplus.inSeconds % 3600 ~/ 60;
    // 如果用到秒的話計算
    // int second = _surplus.inSeconds % 60;

    var str = '';
    if (day > 0) {
      str = day.toString() + '天';
    }
    if (hour > 0 || (day > 0 && hour == 0)) {
      str = str + hour.toString() + '小時';
    }
    str = str + minute.toString() + '分鐘';

    setState(() {
      remainTime = str;
    });
  }
}

搞定 !

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章