發(fā)表日期:2019-01 文章編輯:小燈 瀏覽次數(shù):2308
設(shè)計給的效果如下:
拿到設(shè)計后,先把整體拆分成幾個部分:
然后就可以開始進(jìn)行編碼了。
首先引入需要的自定義組件,login_form_field.dart
文件是《Flutter布局錦囊---帶彩條的文本字段》中的代碼,login_form_code.dart
文件是《Flutter布局錦囊---驗證碼倒計時》中的代碼,doodle_button.dart
文件是《Flutter布局錦囊---涂鴉風(fēng)格按鈕》中的代碼。
import 'package:flutter/material.dart'; import 'login_form_field.dart'; import 'login_form_code.dart'; import '../common/doodle_button.dart';/// 自定義的登錄表單組件。 class LoginForm extends StatefulWidget { @override _LoginFormState createState() => _LoginFormState(); }
然后定義一些用來控制文本字段狀態(tài)、驗證碼按鈕狀態(tài)的成員變量,同時把UI布局的基本輪廓描繪出來。
/// 與自定義的登錄表單組件關(guān)聯(lián)的狀態(tài)子類。 class _LoginFormState extends State<LoginForm> { /// 手機號文本字段的控制器。 final _phoneController = TextEditingController(); /// 驗證碼文本字段的控制器。 final _codeController = TextEditingController(); /// 發(fā)送驗證碼按鈕是否可用。 bool _codeAvailable = false; /// 手機號文本字段是否符合格式。 bool _phoneActivation = false; /// 驗證碼文本字段是否符合格式。 bool _codeActivation = false;@override Widget build(BuildContext context) { return Row( children: <Widget>[ Expanded( flex: 1, child: SizedBox(), ), Expanded( flex: 8, child: Column( children: <Widget>[ // TODO: 實現(xiàn)“手機號輸入框”。 // TODO: 第3步:實現(xiàn)“驗證碼輸入框”。 // TODO: 第4步:實現(xiàn)“登錄按鈕”。 ], ), ), Expanded( flex: 1, child: SizedBox(), ), ] ); } }
通過《Flutter布局錦囊---帶彩條的文本字段》中實現(xiàn)的LoginFormField
組件,你可以迅速實現(xiàn)“手機號輸入框”。
// TODO: 實現(xiàn)“手機號輸入框”。 SizedBox(height: 20.0), LoginFormField( hintText: '請輸入手機號', textEditingController: _phoneController, maxLength: 11, minLength: 7, legitimateCallback: () { setState(() { _phoneActivation = true; _codeAvailable = true;}); }, illegalCallback: () { setState(() { _phoneActivation = false; _codeAvailable = false;}); }, ),
通過《Flutter布局錦囊---帶彩條的文本字段》中實現(xiàn)的LoginFormField
組件、《Flutter布局錦囊---驗證碼倒計時》中實現(xiàn)的LoginFormCode
組件,你可以迅速實現(xiàn)“驗證碼輸入框”。
// TODO: 第3步:實現(xiàn)“驗證碼輸入框”。 SizedBox(height: 30.0), Stack( children: <Widget>[ LoginFormField( hintText: '請輸入驗證碼', textEditingController: _codeController, maxLength: 6, minLength: 6, legitimateCallback: () { setState(() { _codeActivation = true; }); }, illegalCallback: () { setState(() { _codeActivation = false; }); }, ), // 對齊(`Align`)組件,用于將其子項與其自身對齊,并根據(jù)子級的大小自行調(diào)整大小。 Align( // 高度因子(`heightFactor`)屬性,如果為非空值,則將其高度設(shè)置為子組件高度乘以此系數(shù)。 // 可以更大也可以小于`1.0`,但必須是正數(shù)。 heightFactor: 1.7, // 對準(zhǔn)(`alignment`)屬性,如何調(diào)整子組件。 // 對準(zhǔn)(`Alignment`)類的中心右邊(`centerRight`)常量,沿右邊的中心點對準(zhǔn)。 alignment: Alignment.centerRight, child: LoginFormCode( countdown: 60, available: _codeAvailable, onTapCallback: () { print(_codeController.text); }, ), ), ], ),
最后,通過《Flutter布局錦囊---涂鴉風(fēng)格按鈕》中的DoodleButton
組件,迅速實現(xiàn)“登錄按鈕”。
// TODO: 第4步:實現(xiàn)“登錄按鈕”。 SizedBox(height: 48.0), DoodleButton( promptText: '登錄', activation: _codeActivation && _phoneActivation, onTapCallback: (){ print('點擊了“登錄”按鈕'); }, ),