設計給的效果如下:
拿到設計後,先把整體拆分成幾個部分:
- “頂部導航欄”,標題+取消按鈕+跳過按鈕的應用欄。
- “手機號輸入框”,用於獲取手機號碼的圓角邊框輸入字段。
- “驗證碼輸入框”,用於獲取驗證碼的圓角邊框輸入字段,還包括獲取驗證碼的按鈕。
- “提交按鈕”,在滿足條件後讓用戶點擊的提交按鈕。
然後就可以開始進行編碼了。
第1步:繪製組件樹
第2步:實現“頂部導航欄”
下面的代碼導入了一堆東西,大概說一下都是些什麼吧。../common/first_navigation.dart
是《Flutter佈局錦囊—簡單的應用欄》,不過針對這個需求做了一些小改動。../common/doodle_button.dart
是《Flutter佈局錦囊—塗鴉風格按鈕》。../common/round_form_field.dart
是《Flutter佈局錦囊—圓框的表單字段》。widgets/login_form_code.dart
是《Flutter佈局錦囊—驗證碼倒計時》。
import 'package:flutter/material.dart';
import '../common/first_navigation.dart';
import '../common/doodle_button.dart';
import '../common/round_form_field.dart';
import 'widgets/login_form_code.dart';
/// 自定義的綁定頁面組件。
class Binding extends StatefulWidget {
@override
_BindingState createState() => _BindingState();
}
下面代碼的主體是《Flutter佈局錦囊—簡單的應用欄》中自定義的一級導航(firstNavigation
)組件,不過這裏你要把行動(actions
)和主導(leading
)屬性設置成可以配置的,如果沒有則爲空值(null
)。
/// 與自定義的綁定頁面組件關聯的狀態子類。
class _BindingState extends State<Binding> {
/// 手機號表單字段的控制器。
final _phoneController = TextEditingController();
/// 驗證碼錶單字段的控制器。
final _codeController = TextEditingController();
/// 發送驗證碼按鈕是否可用。
bool _codeAvailable = false;
/// 手機號表單字段是否符合格式。
bool _phoneActivation = false;
/// 驗證碼錶單字段是否符合格式。
bool _codeActivation = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: firstNavigation(
'綁定手機',
// 墨水瓶(`InkWell`)組件,響應觸摸的矩形區域。
leading: InkWell(
child: Text(
' 取消 ',
style: TextStyle(
color: Color(0xFF777777),
fontSize: 16.0,
),
),
onTap: (){
Navigator.of(context).pop();
},
),
actions: InkWell(
child: Text(
' 跳過 ',
style: TextStyle(
color: Color(0xFFFF6B47),
fontSize: 16.0,
),
),
onTap: (){
Navigator.of(context).pushNamedAndRemoveUntil('/', (Route<dynamic> route) => false);
},
),
),
body: ListView(
padding: EdgeInsets.symmetric(horizontal: 20.0),
children: <Widget>[
// TODO: 第3步:實現“手機號輸入框”
// TODO: 第4步:實現“驗證碼輸入框”
// TODO: 第5步:實現“提交按鈕”
],
),
);
}
}
第3步:實現“手機號輸入框”
下面代碼的主體是《Flutter佈局錦囊—圓框的表單字段》中自定義的圓框表單字段(RoundFormField
)組件。這個就可以直接使用了,不用像上面那一步修改代碼。
// TODO: 第3步:實現“手機號輸入框”
Container(
padding: EdgeInsets.symmetric(vertical: 20.0),
child: Text(
'綁定手機後可以直接使用手機號碼登錄',
style: TextStyle(
color: Color(0xFF777777),
fontSize: 14.0,
),
),
),
RoundFormField(
hintText: '請輸入手機號',
textEditingController: _phoneController,
checkCallback: (value){
if(value.trim().length == 11) {
_codeAvailable = true;
_phoneActivation = true;
} else {
_codeAvailable = false;
_phoneActivation = false;
}
setState(() {});
},
),
SizedBox(height: 20),
第4步:實現“驗證碼輸入框”
下面代碼的主體是《Flutter佈局錦囊—圓框的表單字段》中自定義的圓框表單字段(RoundFormField
)組件,再佐以《Flutter佈局錦囊—驗證碼倒計時》中自定義的倒計時(LoginFormCode
)組件作爲調料。它們共同完成了驗證碼輸入框。
// TODO: 第4步:實現“驗證碼輸入框”
Stack(
children: <Widget>[
RoundFormField(
hintText: '請輸入驗證碼',
textEditingController: _codeController,
checkCallback: (value){
if(value.trim().length == 6) {
_codeActivation = true;
} else {
_codeActivation = false;
}
setState(() {});
},
),
// 對齊(`Align`)組件,用於將其子項與其自身對齊,並根據子級的大小自行調整大小。
Align(
// 高度因子(`heightFactor`)屬性,如果爲非空值,則將其高度設置爲子組件高度乘以此係數。
heightFactor: 2.0,
// 對準(`alignment`)屬性,如何調整子組件。
alignment: Alignment.centerRight,
child: LoginFormCode(
countdown: 60,
available: _codeAvailable,
onTapCallback: () {
// 根據需求寫提交的過程以及後續操作~
},
),
),
],
),
第5步:實現“提交按鈕”
下面代碼的主體是《Flutter佈局錦囊—塗鴉風格按鈕》中自定義的塗鴉按鈕(DoodleButton
)組件,注意要通過setState(() {});
來改變按鈕的可點擊狀態。
// TODO: 第5步:實現“提交按鈕”
SizedBox(height: 40),
DoodleButton(
promptText: '綁定',
activation: _phoneActivation && _codeActivation,
onTapCallback: (){
setState(() {
_codeActivation = false;
});
// 根據需求寫提交的過程以及後續操作~
setState(() {
_codeActivation = true;
});
},
),