flutter实现登录界面

直接上代码:

import 'package:flutter/material.dart';

class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() {
    return _LoginPageState();
  }
}

/// 登录相关
class _LoginPageState extends State<LoginPage> {
  // 焦点
  FocusNode _focusNodeUserName = FocusNode();
  FocusNode _focusNodePassWord = FocusNode();

  // 用户名输入框控制器,此控制器可以监听用户名输入框的操作
  TextEditingController _userNameController = TextEditingController();

  // 表单状态
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  // 用户名、密码
  String _username = "", _password = "";

  // 是否显示密码
  bool _isShowPwd = false;

  // 是否显示输入框尾部的清除按钮
  bool _isShowClear = false;

  /// 插入到渲染树时调用,只执行一次。(类似Android Fragment的onCreateView函数)
  @override
  void initState() {
    // TODO: implement initState
    // 设置焦点监听
    _focusNodeUserName.addListener(_focusNodeListener);
    _focusNodePassWord.addListener(_focusNodeListener);
    // 监听用户名框的输入改变
    _focusNodeUserName.addListener(() {
      print(_userNameController.text);

      // 监听输入变化,当有内容的时候,显示尾部清除按钮,否则不显示
      if (_userNameController.text.isNotEmpty) {
        _isShowClear = true;
      } else {
        _isShowClear = false;
      }
      // 调用setState 方法,重新调用build 进行渲染界面
      setState(() {});
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    // 返回按钮
    Widget backImageArea = Container(
      height: 45,
      alignment: Alignment.centerLeft,
      margin: EdgeInsets.only(left: 0),
      child: IconButton(
        icon: ImageIcon(AssetImage("assets/imgs/back.png")),
       onPressed: (){
          print("返回------");
       },
      ),
    );

    // logo图片区域
    Widget logoImageArea = Container(
      margin: EdgeInsets.only(top: 20),
      alignment: Alignment.topCenter,
      child: Image.asset(
        "assets/imgs/logo.png",
        width: 226,
        height: 130,
      ),
    );

    // 文本输入框区域
    Widget inputTextArea = Container(
      margin: EdgeInsets.only(left: 20, right: 20),
      // 文本输入框区域的装饰
      decoration: BoxDecoration(
          borderRadius: BorderRadius.all(Radius.circular(8)),
          color: Colors.white),
      // 使用Form将两个输入框包起来做控制
      child: Form(
        key: _formKey,
        // Form里面是一个垂直布局
        child: Column(
          mainAxisSize: MainAxisSize.min,
          // 控件
          children: <Widget>[
            // 用户名
            TextFormField(
              controller: _userNameController,
              // 焦点控制
              focusNode: _focusNodeUserName,
              // 设置键盘类型
              keyboardType: TextInputType.number,
              // 输入框的装饰
              decoration: InputDecoration(
                  labelText: "用户名",
                  hintText: "手机号或身份证号",
                  prefixIcon: Icon(Icons.person),
                  // 尾部添加清除按钮
                  suffixIcon: (_isShowClear)
                      ? IconButton(
                          icon: Icon(Icons.clear),
                          onPressed: () {
                            // 清空文本框的内容
                            _userNameController.clear();
                          })
                      : null),
              // 校验用户名
              validator: validateUserName,
              // 保持数据
              onSaved: (String value) {
                _username = value;
              },
            ),
            // 间隔
            SizedBox(height: 10),
            // 密码
            TextFormField(
              focusNode: _focusNodePassWord,
              decoration: InputDecoration(
                  labelText: "密码",
                  hintText: "请输入密码",
                  prefixIcon: Icon(Icons.lock),
                  // 是否显示密码
                  suffixIcon: IconButton(
                      icon: Icon(
                          _isShowPwd ? Icons.visibility : Icons.visibility_off),
                      onPressed: () {
                        setState(() {
                          _isShowPwd = !_isShowPwd;
                        });
                      })),
              obscureText: !_isShowPwd,
              // 校验密码
              validator: validatePassWord,
              // 保存数据
              onSaved: (String value) {
                _password = value;
              },
            )
          ],
        ),
      ),
    );

    // 忘记密码
    Widget forgetPwdArea = Container(
      margin: EdgeInsets.only(right: 20),
      child: Row(
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          FlatButton(
              child: Text(
                "忘记密码?",
                style: TextStyle(color: Colors.black54),
              ),
              onPressed: () {
                print('找回密码');
              })
        ],
      ),
    );

    // 登录按钮区域
    Widget loginButtonArea = Container(
      margin: EdgeInsets.only(left: 20, right: 20),
      height: 45,
      child: RaisedButton(
          color: Colors.blue[500],
          child: Text(
            "登录",
            style: TextStyle(color: Colors.white),
          ),
          // 设置圆角
          shape:
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
          onPressed: () {
            // 点击登录按钮,解除焦点,回收键盘
            _focusNodeUserName.unfocus();
            _focusNodePassWord.unfocus();

            if (_formKey.currentState.validate()) {
              // 输入验证通过
              _formKey.currentState.save();
              // todo 等录接口相关操作
              print("登陆------");
            }
          }),
    );

    // 组装widget组件,形成界面
    return Scaffold(
        backgroundColor: Colors.white,
        // 外层添加一个手势,用于点击空白部分,回收键盘
        body: GestureDetector(
          onTap: () {
            // 点击空白区域,回收键盘
            _focusNodeUserName.unfocus();
            _focusNodePassWord.unfocus();
          },
          child: ListView(
            children: <Widget>[
              backImageArea,
              logoImageArea,
              SizedBox(height: 60),
              inputTextArea,
              forgetPwdArea,
              SizedBox(height: 14),
              loginButtonArea
            ],
          ),
        ));
  }

  /// 销毁(类似于Android的onDestroy, 在执行Navigator.pop后会调用该办法, 表示组件已销毁;)
  @override
  void dispose() {
    // 移除焦点监听
    _focusNodeUserName.removeListener(_focusNodeListener);
    _focusNodePassWord.removeListener(_focusNodeListener);
    _userNameController.dispose();
    super.dispose();
  }

  // 监听焦点
  _focusNodeListener() async {
    if (_focusNodeUserName.hasFocus) {
      print("用户名框获取焦点");
      // 取消密码框的焦点状态
      _focusNodePassWord.unfocus();
    }

    if (_focusNodePassWord.hasFocus) {
      // 取消用户名框焦点状态
      _focusNodeUserName.unfocus();
    }
  }

  // 验证用户名
  String validateUserName(String value) {
    // 验证手机号
    if (value.isEmpty) {
      return "用户名不能为空!";
    } else {
      return null;
    }
  }

  // 验证密码
  String validatePassWord(String pwd) {
    // 正则验证密码
    RegExp exp = RegExp("[a-zA-Z0-9_]{6,20}");
    if (pwd.isEmpty) {
      return "密码不能为空";
    } else if (!exp.hasMatch(pwd)) {
      return "请输入正确的6-20位数字、字母或下划线的密码";
    } else {
      return null;
    }
  }
}

效果:
在这里插入图片描述

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值