fir_release_Android包下载地址
GIF
login_page.gif
UI如图 login_page.png
需求分析:
- 通过手机号方式注册或登录 ,限制长度,只能输入数字(API限制只有ui和交互)
- 整体滑动
- 登录按钮联动
- 验证码(倒计时不可点击状态,获取或重新发送状态)
- 协议与政策颜色和点击事件
UI拆解并实现:
TextField: 手机号和验证码实现(数字键盘,限制长度,数字限制)
Widget _buildPhoneEdit() {
var node = new FocusNode();
return new Padding(
padding: const EdgeInsets.only(left: 40.0, right: 40.0),
child: new TextField(
onChanged: (str) {
_phoneNum = str;
setState(() {});
},
decoration: new InputDecoration(
hintText: '请输入手机号',
),
maxLines: 1,
maxLength: 11,
//键盘展示为号码
keyboardType: TextInputType.phone,
//只能输入数字
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly,
],
onSubmitted: (text) {
FocusScope.of(context).reparentIfNeeded(node);
},
),
);
}
Widget _buildVerifyCodeEdit() {
var node = new FocusNode();
Widget verifyCodeEdit = new TextField(
onChanged: (str) {
_verifyCode = str;
setState(() {});
},
decoration: new InputDecoration(
hintText: '请输入短信验证码',
),
maxLines: 1,
maxLength: 6,
//键盘展示为数字
keyboardType: TextInputType.number,
//只能输入数字
inputFormatters: <TextInputFormatter>[
WhitelistingTextInputFormatter.digitsOnly,
],
onSubmitted: (text) {
FocusScope.of(context).reparentIfNeeded(node);
},
);
Widget verifyCodeBtn = new InkWell(
...........
...........
);
return new Padding(
padding: const EdgeInsets.only(left: 40.0, right: 40.0, top: 10.0),
child: new Stack(
children: <Widget>[
verifyCodeEdit,
new Align(
alignment: Alignment.topRight,
child: verifyCodeBtn,
),
],
),
);
}
InkWell,BoxDecoration: 实现线框效果,水波纹效果,验证码倒计时状态,重新发送状态
Widget verifyCodeBtn = new InkWell(
onTap: (_seconds == 0)
? () {
setState(() {
_startTimer();
});
}
: null,
child: new Container(
alignment: Alignment.center,
width: 100.0,
height: 36.0,
decoration: new BoxDecoration(
border: new Border.all(
width: 1.0,
color: Colors.blue,
),
),
child: new Text(
'$_verifyStr',
style: new TextStyle(fontSize: 14.0),
),
),
);
_startTimer() {
_seconds = 10;
_timer = new Timer.periodic(new Duration(seconds: 1), (timer) {
if (_seconds == 0) {
_cancelTimer();
return;
}
_seconds--;
_verifyStr = '$_seconds(s)';
setState(() {});
if (_seconds == 0) {
_verifyStr = '重新发送';
}
});
}
_cancelTimer() {
_timer?.cancel();
}
RaisedButton: 根据手机号和验证码的输入值,进行状态改变
Widget _buildRegist() {
return new Padding(
padding: const EdgeInsets.only(left: 40.0, right: 40.0, top: 20.0),
child: new RaisedButton(
color: Colors.blue,
textColor: Colors.white,
disabledColor: Colors.blue[100],
onPressed: (_phoneNum.isEmpty || _verifyCode.isEmpty) ? null : () {
showTips();
},
child: new Text(
"登 录",
style: new TextStyle(fontSize: 16.0),
),
),
);
}
TextSpan: 对一段文字实现不同的展示效果
Widget _buildProtocol() {
return new Padding(
padding: const EdgeInsets.only(left: 40.0, right: 40.0, top: 10.0),
child: new Container(
child: new Text.rich(
new TextSpan(
text: '注册知乎日报代表你已阅读并同意 ',
style: new TextStyle(
fontSize: 14.0,
color: Colors.grey[500],
fontWeight: FontWeight.w400),
children: [
new TextSpan(
recognizer: new TapGestureRecognizer()
..onTap = () {
CommonSnakeBar.buildSnakeBarByKey(
registKey, context, '点击了知乎协议');
},
text: '知乎协议',
style: new TextStyle(
fontSize: 14.0,
color: Colors.blue,
fontWeight: FontWeight.w400,
)),
new TextSpan(
text: ' 和 ',
style: new TextStyle(
fontSize: 14.0,
color: Colors.grey[500],
fontWeight: FontWeight.w400,
)),
new TextSpan(
recognizer: new TapGestureRecognizer()
..onTap = () {
CommonSnakeBar.buildSnakeBarByKey(
registKey, context, '点击了隐私政策');
},
text: '隐私政策',
style: new TextStyle(
fontSize: 14.0,
color: Colors.blue,
fontWeight: FontWeight.w400,
)),
]),
),
),
);
}
整体组合
image.png