这是我们需要做的设计图,关于设计图就不用说了。
直接上代码
import 'package:flutter/material.dart';
//密码登陆
class Login extends StatefulWidget {
@override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
//焦点
FocusNode _focusNodeUName = new FocusNode();
FocusNode _focusNodePassword = new FocusNode();
//控制器 用户名电话号 密码
TextEditingController _UNameController = new TextEditingController();
TextEditingController _PasswordController = new TextEditingController();
var _username = ''; //用户名或者手机号
var _password = ''; //密码
var _isShowPassword = false; //是否显示密码
var _isShowClear = false; //是否显示输入框尾部的清除按钮,默认不显示
//监听焦点
Future<Null> _focusNodeListener() async{
if (_focusNodeUName.hasFocus){
print("用户名框获取焦点");
//取消密码框的焦点状态
_focusNodePassword.unfocus();
}
else if (_focusNodePassword.hasFocus){
print("密码框获取焦点");
//取消用户名框交电状态
_focusNodeUName.unfocus();
}
}
@override
void initState() {
//设置焦点监听
_focusNodeUName.addListener(_focusNodeListener);
_focusNodePassword.addListener(_focusNodeListener);
//监听用户矿的输入改变
_UNameController.addListener((){
print(_UNameController.text);
//监听文本框输入变化,当有内容时,显示尾部清除按钮,否则不显示
if (_UNameController.text.length > 0){
_isShowClear = true;
}else{
_isShowClear = false;
}
setState(() {
});
});
super.initState();
}
@override
void dispose() {
//移除焦点监听
_focusNodeUName.removeListener(_focusNodeListener);
_focusNodePassword.removeListener(_focusNodeListener);
_UNameController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: (){
print("点击了空白区域");
_focusNodeUName.unfocus();
_focusNodePassword.unfocus();
},
child: ListView(
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 44,top: 97),
child: Text('你好,',style: TextStyle(fontWeight: FontWeight.bold,fontSize: 23),),
),
Padding(
padding: EdgeInsets.only(left: 44,top: 10),
child: Text('欢迎来到注册界面',style: TextStyle(fontWeight: FontWeight.bold,fontSize: 23),),
),
Padding(
padding: EdgeInsets.only(top: 39),
child: Container(
height: 50,
width: MediaQuery.of(context).size.width,
child: Padding(
padding: EdgeInsets.fromLTRB(44, 0, 44, 0),
child: Container(
width: MediaQuery.of(context).size.width-88,
color: Color(0XFFF2F3F7),
child: Row(
children: <Widget>[
Container(
width: 40,
child: Padding(
padding: EdgeInsets.only(left: 10),
child: Text('+86'),
),
),
Container(
width: 20,
child: Image(
image: AssetImage("assets/Login_img/xiaZhankai.png"),
width: 12,
height: 7,
),
),
Container(
width: 197,
child: Padding(
padding: EdgeInsets.all(0),
child:Stack(
children: <Widget>[
Positioned(
child: TextField(
autofocus: true,
controller: _UNameController,
focusNode: _focusNodeUName,
keyboardType: TextInputType.number,
decoration: InputDecoration(
hintText: '请输入手机号',
border: InputBorder.none,
//尾部添加清除按钮
suffixIcon: (_isShowClear) ? IconButton(icon: Icon(Icons.clear),
onPressed: (){
//清空内容
_UNameController.clear();
_PasswordController.clear();
},) : null,
),
),
)
],
) ,
),
)
],
),
),
),
),
),
Padding(
padding: EdgeInsets.only(top: 15),
child: Container(
height: 50,
child: Padding(
padding: EdgeInsets.fromLTRB(44, 0, 44, 0),
child: Container(
width: 272,
color: Color(0XFFF2F3F7),
child: Row(
children: <Widget>[
Container(
width: 272,
child: Padding(
padding: EdgeInsets.all(0),
child: Stack(
children: <Widget>[
Positioned(
left: 10,
right: 0,
top: 0,
bottom: 0,
child: TextField(
autofocus: true,
controller: _PasswordController,
focusNode: _focusNodePassword,
keyboardType: TextInputType.text,
decoration: InputDecoration(
hintText: '请输入密码',
border: InputBorder.none,
),
),
),
],
),
),
),
],
),
),
),
),
),
Padding(
padding: EdgeInsets.only(left: 44,top: 24),
child: Container(
width: 272,
height: 30,
child: Stack(
children: <Widget>[
Positioned(
child: GestureDetector(
onTap: (){ Navigator.pushNamed(context, "login_checkCode"); },
child: Text('验证码登录'),
),
),
Positioned(
left: 192,
child: GestureDetector(
onTap: (){ Navigator.pushNamed(context, "login_forgetPassword"); },
child: Text('忘记密码 ?'),
),
),
],
),
),
),
Padding(
padding: EdgeInsets.only(left: 44,top: 66,right: 44),
child: Container(
height: 45,
child: Stack(
children: <Widget>[
Positioned(
left: 0,
right: 0,
top: 0,
bottom: 0,
child: FlatButton(
color: Colors.blue,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
highlightColor: Colors.blue[700],
colorBrightness: Brightness.dark,
splashColor: Colors.grey,
child: Text('进入修派'),
onPressed: (){
//点击后,解除焦点,回收键盘
_focusNodeUName.unfocus();
_focusNodePassword.unfocus();
}, //点击事件---回调函数
),
)
],
),
)
),
Padding(
padding: EdgeInsets.only(left: 44,top: 78,right: 44),
child: Container(
width: 272,
child: Stack(
children: <Widget>[
Positioned(
child: Text('------------------------- 第三方登录 -------------------------'),
)
],
),
),
),
Padding(
padding: EdgeInsets.only(top: 29),
child: Container(
width: MediaQuery.of(context).size.width, //屏幕的宽度
height: 40,
child: Stack(
children: <Widget>[
Positioned(
left: 80,
child: GestureDetector(
onTap: (){ Navigator.pushNamed(context, "login_third"); },
child: Image(
image: AssetImage("assets/Login_img/QQ.png"),
width: 40,
height: 40,
),
),
),
Positioned(
left: 160,
child: GestureDetector(
onTap: (){ Navigator.pushNamed(context, "login_third"); },
child: Image(
image: AssetImage("assets/Login_img/WeChat.png"),
width: 40,
height: 40,
),
),
),
Positioned(
left: 240,
child: GestureDetector(
onTap: (){ Navigator.pushNamed(context, "login_third"); },
child: Image(
image: AssetImage("assets/Login_img/weibo.png"),
width: 40,
height: 40,
),
),
),
],
),
),
),
],
),
),
);
}
}
很简单大部分的时候就是做界面,因为要做手机上的适配,所以控件的选择要正确,不然会出现运行的报错。不止是像素的溢出,控件的大小等等。
还有要想监听数据以及数据的变化,我们只需要建立
TextEditingController _UNameController = new TextEditingController();
TextEditingController _PasswordController = new TextEditingController();
相应的控制器即可,绑定在相关的控件上,如果想看实时的变化,就自己用print()函数可以在控制台看见数据的变化。但是有一点要记住这,数据的改变是通过setState()方法来改变数据。这就是Flutter的好处,就是在绘制界面的时候比较麻烦,因为要做适配,但是在数据方法比起Java和Android也是有自己的好处。
与设计图还是有点差距的,如果有问题还希望大佬指正…