Flutter佈局錦囊---驗證碼倒計時
阿新 • • 發佈:2019-01-05
設計給的效果如下:
拿到設計後,先把整體拆分成幾個部分:
- “獲取驗證碼按鈕”,可以通過點選按鈕來獲取驗證碼。
然後就可以開始進行編碼了。
第1步:繪製元件樹
第2步:實現“獲取驗證碼按鈕”
獲取驗證碼的按鈕需要顯示在文字欄位的上面,所以你可以直接使用Flutter的墨水瓶(InkWell
)元件,一個可以響應觸控的矩形區域。然後通過dart:async
庫的計時器(Timer
)類,使其控制墨水瓶(InkWell
)元件的狀態。
import 'dart:async';
import 'package:flutter/material.dart' ;
/// 墨水瓶(`InkWell`)可用時使用的字型樣式。
final TextStyle _availableStyle = TextStyle(
fontSize: 16.0,
color: const Color(0xFF00CACE),
);
/// 墨水瓶(`InkWell`)不可用時使用的樣式。
final TextStyle _unavailableStyle = TextStyle(
fontSize: 16.0,
color: const Color(0xFFCCCCCC),
);
class LoginFormCode extends StatefulWidget {
/// 倒計時的秒數,預設60秒。
final int countdown;
/// 使用者點選時的回撥函式。
final Function onTapCallback;
/// 是否可以獲取驗證碼,預設為`false`。
final bool available;
LoginFormCode({
this.countdown: 60,
this.onTapCallback,
this.available: false,
});
@override
_LoginFormCodeState createState() => _LoginFormCodeState();
}
class _LoginFormCodeState extends State<LoginFormCode> {
/// 倒計時的計時器。
Timer _timer;
/// 當前倒計時的秒數。
int _seconds;
/// 當前墨水瓶(`InkWell`)的字型樣式。
TextStyle inkWellStyle = _availableStyle;
/// 當前墨水瓶(`InkWell`)的文字。
String _verifyStr = '獲取驗證碼';
@override
void initState() {
super.initState();
_seconds = widget.countdown;
}
/// 啟動倒計時的計時器。
void _startTimer() {
// 計時器(`Timer`)元件的定期(`periodic`)建構函式,建立一個新的重複計時器。
_timer = Timer.periodic(
Duration(seconds: 1),
(timer) {
if (_seconds == 0) {
_cancelTimer();
_seconds = widget.countdown;
inkWellStyle = _availableStyle;
setState(() {});
return;
}
_seconds--;
_verifyStr = '已傳送$_seconds'+'s';
setState(() {});
if (_seconds == 0) {
_verifyStr = '重新發送';
}
});
}
/// 取消倒計時的計時器。
void _cancelTimer() {
// 計時器(`Timer`)元件的取消(`cancel`)方法,取消計時器。
_timer?.cancel();
}
@override
Widget build(BuildContext context) {
// 墨水瓶(`InkWell`)元件,響應觸控的矩形區域。
return widget.available ? InkWell(
child: Text(
' $_verifyStr ',
style: inkWellStyle,
),
onTap: (_seconds == widget.countdown) ? () {
_startTimer();
inkWellStyle = _unavailableStyle;
_verifyStr = '已傳送$_seconds'+'s';
setState(() {});
widget.onTapCallback();
} : null,
): InkWell(
child: Text(
' 獲取驗證碼 ',
style: _unavailableStyle,
),
);
}
}