这是我们需要做的设计图,关于设计图就不用说了。
直接上代码
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也是有自己的好处。
与设计图还是有点差距的,如果有问题还希望大佬指正…
来源:51CTO
作者:
链接:https://blog.csdn.net/mubowen666/article/details/101214890