打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Flutter 一个优美的用户体验的登录页面 抖动提示 文本提示

题记

—— 执剑天涯,从你的点滴积累开始,所及之处,必精益求精,优美的应用体验 来自于细节的处理,更源自于码农的自我要求与努力


Flutter是谷歌推出的最新的移动开发框架。

本文章实现Demo运行效果 如下:

1 Demo 实现开始如下

首先是来构建页面的主体

class HomePage extends StatefulWidget {  @override  _TestPageState createState() => _TestPageState();}
class _TestPageState extends State<HomePage> {
//用户名输入框的焦点控制 FocusNode _userNameFocusNode = new FocusNode(); FocusNode _passwordFocusNode = new FocusNode();
//文本输入框控制器 TextEditingController _userNameController = new TextEditingController(); TextEditingController _passwordController = new TextEditingController();
//抖动动画控制器 ShakeAnimationController _userNameAnimation = new ShakeAnimationController(); ShakeAnimationController _userPasswordAnimation = new ShakeAnimationController();
//Stream 更新操作控制器 StreamController<String> _userNameStream = new StreamController(); StreamController<String> _userPasswordStream = new StreamController();
@override Widget build(BuildContext context) { //手势识别点击空白隐藏键盘 return GestureDetector( onTap: () { hindKeyBoarder(); }, child: Scaffold( appBar: AppBar( title: Text("登录"), ), //登录页面的主体 body: buildLoginWidget(), ), ); } ... ...}

2 点击空白的用户体验

那就是把键盘隐藏了,代码如下:

  void hindKeyBoarder() {    //输入框失去焦点    _userNameFocusNode.unfocus();    _passwordFocusNode.unfocus();
//隐藏键盘 SystemChannels.textInput.invokeMethod('TextInput.hide');  }

3 线性布局排列

将用户名与密码还有登录按钮使用 Column 线性排列。

//登录页面的主体  Widget buildLoginWidget() {    return Container(      margin: EdgeInsets.all(30.0),      //线性布局      child: Column(        children: [          //用户名输入框          buildUserNameWidget(),          SizedBox(            height: 20,          ),          //用户密码输入框          buildUserPasswordWidget(),          SizedBox(            height: 40,          ),          //登录按钮          Container(            width: double.infinity,            height: 40,            child: ElevatedButton(              child: Text("登录"),              onPressed: () {                checkLoginFunction();              },            ),          )        ],      ),    );  }

4 输入框的构建

用户名输入框

  ///用户名输入框 Stream 局部更新 error提示  ///     ShakeAnimationWidget 抖动动画  ///  StreamBuilder<String> buildUserNameWidget() {    return StreamBuilder<String>(      stream: _userNameStream.stream,      builder: (BuildContext context, AsyncSnapshot<String> snapshot) {        return ShakeAnimationWidget(          //微左右的抖动          shakeAnimationType: ShakeAnimationType.LeftRightShake,          //设置不开启抖动          isForward: false,          //抖动控制器          shakeAnimationController: _userNameAnimation,          child: new TextField(            //焦点控制            focusNode: _userNameFocusNode,            //文本控制器            controller: _userNameController,            //键盘回车键点击回调            onSubmitted: (String value) {              //点击校验,如果有内容输入 输入焦点跳入下一个输入框              if (checkUserName()) {                _userNameFocusNode.unfocus();                FocusScope.of(context).requestFocus(_passwordFocusNode);              } else {                FocusScope.of(context).requestFocus(_userNameFocusNode);              }            },            //边框样式设置            decoration: InputDecoration(              //红色的错误提示文本              errorText: snapshot.data,              labelText: "用户名",              //设置上下左右 都有边框              //设置四个角的弧度              border: OutlineInputBorder(                //设置边框四个角的弧度                borderRadius: BorderRadius.all(Radius.circular(10)),              ),            ),          ),        );      },    );  }

密码输入框,两个输入框的构建类似

StreamBuilder<String> buildUserPasswordWidget() {  return StreamBuilder<String>(    stream: _userPasswordStream.stream,    builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {      return ShakeAnimationWidget(        //微左右的抖动        shakeAnimationType: ShakeAnimationType.LeftRightShake,        //设置不开启抖动        isForward: false,        //抖动控制器        shakeAnimationController: _userPasswordAnimation,        child: new TextField(          focusNode: _passwordFocusNode,          controller: _passwordController,          onSubmitted: (String value) {            if (checkUserPassword()) {              loginFunction();            } else {              FocusScope.of(context).requestFocus(_passwordFocusNode);            }          },          //隐藏输入的文本          obscureText: true,          //最大可输入1行          maxLines: 1,          //边框样式设置          decoration: InputDecoration(            labelText: "密码",            errorText: snapshot.data,            border: OutlineInputBorder(              borderRadius: BorderRadius.all(Radius.circular(10)),            ),          ),        ),      );    },  );}

5 校验用户名与密码的方法如下

  bool checkUserName() {    //获取输入框中的输入文本    String userName = _userNameController.text;    if (userName.length == 0) {      //Stream 事件流更新提示文案      _userNameStream.add("请输入用户名");      //抖动动画开启      _userNameAnimation.start();      return false;    } else {      //清除错误提示      _userNameStream.add(null);      return true;    }  }
bool checkUserPassword() { String userPassrowe = _passwordController.text; if (userPassrowe.length < 6) { _userPasswordStream.add("请输入标准密码"); _userPasswordAnimation.start(); return false; } else { _userPasswordStream.add(null); return true; }  }

以小编的性格,要实现百万Demo随时复制粘贴肯定是需要源码的 点击原文获取

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
超过百万的StackOverflow Flutter 问题
Flutter:使用复选框进行下拉多选
Flutter完整开发实战详解(十七、 实用技巧与填坑二)
flutter_boot android和flutter源码阅读记录
Flutter学习笔记(29)--Flutter如何与native进行通信
Android开发中常用的方法、类和接口大全
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服