一、說明
要實現一個類似上圖中滑動列表項倒計時功能,其中剩餘時間是需要每分鐘更新一次。
二、功能實現
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;
});
}
}
搞定 !