登录页几乎是每个联网app必备的界面,下面以我工作中开发的百卓优采云进销存app软件的登录页为例使用Flutter来实现,具体效果图如下:


界面看起来很简单,但麻雀虽小五脏俱全,使用到了实际开发中所需的大多数控件,下面让我们开启实现之旅,首先我们先实现上面的banner,实现之前我们先做好准备工作,把界面中需要的图片资源导入,具体步骤如下:

  1. lib同级目录下创建目录assets/login/,将所需图片资源放入该目录,最终目录结构为
  2. 编辑pubspec.yaml , 将图片列表加入assets,编辑该文件时出现错误时,请检查前面缩进的空格

准备工作做好后,我们来一步一步实现登录界面,先上骨架代码

void main() => runApp(AbizApp ());class AbizApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Title',theme: ThemeData(primarySwatch: Colors.blue,),home://AppFuncBrowse(),LoginPage(),);}
}
class LoginPage extends StatefulWidget {@override_LoginPageState createState() {// TODO: implement createStatereturn _LoginPageState();}
}
class _LoginPageState extends State<LoginPage> {@overrideWidget build(BuildContext context) {return Scaffold(body: Column(crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[_buildTopBannerWidget(),],),);}
}

顶部banner实现很简单,就是显示一张图片, Image有fit属性,用来控制图片的显示方式,具体对应的值建议大家都亲自试一试来加深理解,我就不再赘述了

_buildTopBannerWidget() {return Container(child: Image.asset("assets/login/login_banner.png",fit: BoxFit.cover,),);}

中国制造网登录的账号提示,很简单,我就不再废话,直接上代码

  _buildAccountLoginTip() {return Padding(padding: EdgeInsets.all(15),child: Text("百卓采购网/中国制造网会员登录",maxLines: 1,textAlign: TextAlign.start,style: TextStyle(fontSize: 16, color: Colors.black54),),);}

下面实现关键部分,用户名和密码输入框,上代码

_buildEditWidget() {return Container(margin: EdgeInsets.only(left: 15, right: 15),decoration: BoxDecoration(borderRadius: BorderRadius.circular(4.0),border: Border.all(width: 1.0 / MediaQuery.of(context).devicePixelRatio,color: Colors.grey.withOpacity(0.5)),),);}

flutter中控件度量的单位是逻辑像素,和iOS中点的概念一样,为了使边框是1px宽,我们必须获取1个逻辑像素代表几个物理像素(px),MediaQuery.of(context).devicePixelRatio就是我们需要的,MediaQuery.of(context)返回MediaQueryData,MediaQueryData里包含屏幕大小(逻辑大小),padding等信息。

下面我们来实现用户名的输入框

class _LoginPageState extends State<LoginPage> {TextEditingController _pwdEditController;TextEditingController _userNameEditController;final FocusNode _userNameFocusNode = FocusNode();final FocusNode _pwdFocusNode = FocusNode();@overridevoid initState() {super.initState();_pwdEditController = TextEditingController();_userNameEditController = TextEditingController();_pwdEditController.addListener(() => setState(() => {}));_userNameEditController.addListener(() => setState(() => {}));}// 此处省略其他代码
}_buildLoginNameTextField() {return TextField(controller: _userNameEditController,focusNode: _userNameFocusNode,decoration: InputDecoration(hintText: "登录名/邮箱/手机",border: InputBorder.none,prefixIcon: Image.asset("assets/login/user_name.png",fit: BoxFit.none,),suffixIcon: (_userNameEditController.text ?? "").isEmpty? IconButton(icon: Image.asset("assets/login/qrcode_login.png",fit: BoxFit.cover,),onPressed: () => {},): IconButton(icon: Icon(Icons.cancel,color: Colors.grey,),onPressed: () {_userNameEditController.clear();_userNameFocusNode.unfocus();setState(() {});})),);}

TextField控件功能和原生iOS控件UITextField功能类似,不过大多数属性通过设置decoration来实现, placeholder和leftview,rightview对应hintText,prefixIcon,suffixIcon属性,为了实现输入内容不为空时输入框右边显示清空按钮,需要监听TextField的值,我们通过设置TextEditingController并监听它的值变化来实现,隐藏键盘我们通过FocusNode来设置,具体见代码,为了去除编辑框的下划线,设置 InputDecoration属性

      border: InputBorder.none,

登录名的介绍已经完了,密码框的实现和登录名几乎一样,唯一的不同就是设置属性 obscureText: true, 其他的就不再多说,上代码

_buildPwdTextField() {return TextField(controller: _pwdEditController,focusNode: _pwdFocusNode,obscureText: true,decoration: InputDecoration(hintText: "密码",border: InputBorder.none,prefixIcon: Image.asset("assets/login/password.png",fit: BoxFit.none,),suffixIcon: (_pwdEditController.text ?? "").isEmpty? FlatButton(child: Text("忘记密码"),onPressed: () {_pwdFocusNode.unfocus();_userNameFocusNode.unfocus();}): IconButton(icon: Icon(Icons.cancel,color: Colors.grey,),onPressed: () {_pwdEditController.clear();_pwdFocusNode.unfocus();setState(() {});}),));}

两个输入框之间有一条1px分割线,分割线在Flutter中也有控件:Divider,最后编辑框组的实现如下

_buildEditWidget() {return Container(margin: EdgeInsets.only(left: 15, right: 15),decoration: BoxDecoration(borderRadius: BorderRadius.circular(4.0),border: Border.all(width: 1.0 / MediaQuery.of(context).devicePixelRatio,color: Colors.grey.withOpacity(0.5)),),child: Column(children: <Widget>[_buildLoginNameTextField(),Divider(height: 1.0),_buildPwdTextField(),],),);}

现在只剩下最后的部件:登录按钮和注册按钮

  _buildLoginRegisterButton() {return Padding(padding: EdgeInsets.all(15),child: Row(crossAxisAlignment: CrossAxisAlignment.center,children: <Widget>[Expanded(child: Container(height: 44,decoration: BoxDecoration(borderRadius: BorderRadius.circular(4.0),color: Colors.grey.withOpacity(0.3),),child: FlatButton(onPressed: null,child: Text("登录",style: TextStyle(color: Colors.white),)),),),SizedBox(width: 15.0),Expanded(child: Container(height: 44,decoration: BoxDecoration(borderRadius: BorderRadius.circular(4.0),border: Border.all(width: 1.0, color: Colors.green),),child: FlatButton(onPressed: null,child: Text("立即注册",style: TextStyle(color: Colors.green),)),))],),);}

为了使按钮等分剩余空间,需要用到Expanded控件包裹,Expanded控件从Flexible派生,Flexible通过属性flex设置剩余空间的分配,熟悉android的一眼就看出类似于layout_weight属性

各个部件都实现好了,现在就是组装的时候了,我们的采取从上到下的线性布局,Flutter可以用Column来实现


@override
Widget build(BuildContext context) {return Scaffold(body: Column(crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[_buildTopBannerWidget(),_buildAccountLoginTip(),_buildEditWidget(),_buildLoginRegisterButton(),],),);
}

运行后一切正常,但是点击输入框问题来了

具体意思是布局重叠了,这时候SingleChildScrollView就派上用场了,它能在弹出键盘时将内容向上移动使输入框不被覆盖,优化后的代码如下


@override
Widget build(BuildContext context) {return Scaffold(body: SingleChildScrollView(child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: <Widget>[_buildTopBannerWidget(),_buildAccountLoginTip(),_buildEditWidget(),_buildLoginRegisterButton(),],),),);
}

至此我们的登录页就实现完了,至于实际的登录联网就不再说了,有什么问题欢迎大家指正

Flutter 实现登录页相关推荐

  1. Flutter Web(一)新建项目和登录页

    flutter开发环境搭建略 如果是新搭建好的环境,需要开启web支持和windows支持 flutter config --enable-windows-desktop flutter config ...

  2. flutter微信登录

    1.在flutter中yaml文件中进行配置 fluwx: ^1.0.4 2.初始化: 在main.dart中进行初始化操作,尽可能早的初始化 await fluwx.register(appId: ...

  3. 为 Django admin 登录页添加验证码

    为什么80%的码农都做不了架构师?>>>    历史原因,使用上古版本 django 1.6.5,但新版本应该大同小异 首先添加自定义后台模块app, 如adm,并添加到 INSTA ...

  4. android 炫酷背景,炫酷-背景图垂直循环滚动登录页,Android RecyclerView实现

    炫酷-背景图上下循环滚动登录页,Android RecyclerView实现方法 某站的登录页背景不停循环滚动,和街边的广告箱很像,感觉不错我也心动了.决定高仿一下,参考了几篇文章后就动手了. 实现步 ...

  5. CAS单点登录3--服务端登录页个性化

    原理 cas的页面显示控制是集中在\WEB-INF\cas.properties中的cas.viewResolver.basename属性的,其默认值为default_views 所以cas会去cla ...

  6. springsecurity不拦截某个接口_SpringSecurity 默认表单登录页展示流程源码

    SpringSecurity 默认表单登录页展示流程源码 本篇主要讲解 SpringSecurity提供的默认表单登录页 它是如何展示的的流程,涉及1.FilterSecurityIntercepto ...

  7. 当session会话结束时,重定向到登录页显示在iframe框内的问题

    //检测到用户未登录 //方法1: 重定向到登录页,但是不支持跳出iframe //response.sendRedirect("/dormitory/toLoginPage"); ...

  8. 【实战 Ids4】小技巧篇:自定义登录页操作

    今天的内容很简单,1分钟就能看完,5分钟就能学会,但是却是在我们平时开发中必须要学会的一个小知识点,我就不让大家走弯路了,直接看操作. 在平时的IdentityServer4开发中呢,我们都是根据官方 ...

  9. 页面监听,一段时间内不操作网页,就自动跳转到登录页

    需求:用户在 5 分钟内没有操作网页,就自动跳转到登录页. 环境:jquery 项目,有公共的 js 文件 . 在所有页面都引用的 js 文件中添加下面代码: //判断用户是否在5分钟内未操作页面,如 ...

最新文章

  1. java 单链表约瑟夫环_java循环单链表实现约瑟夫环问题
  2. linux ubuntu如何解压rar文件?unrar
  3. 剑与远征的最新公告,玩家能获得什么?除了资源,体验怎么样?
  4. rsync的安装使用01
  5. what is ssao
  6. Scrapy爬虫报错AttributeError: ‘NoneType‘ object has no attribute ‘write‘
  7. openstack初探
  8. 开源java诊断工具,阿里开源Java 线上诊断工具 Arthas 实践
  9. 如何批量将 Excel 文档转为 Txt 文本格式
  10. 简单git用ssh方式下载代码
  11. Win11更新后电脑没有声音,声卡驱动失效,卸载重装依然无效
  12. 吃货在东京 -- 记那段吃不饱的日子 之三 筑地的生鱼刺身
  13. JAVA版农历和阳历相互转换源码
  14. python求偏导_python中几种自动微分库解析
  15. 光通信的再思考:5G流量爆发下的数据密度革命
  16. 线程死锁 导致 服务器cpu负载过高
  17. ubuntu20.04如何录制屏幕
  18. 网络编程“惊群“问题
  19. 全网最详细地介绍mybatis-plus框架
  20. 性能测试基础及loadRunner的使用(超详细)

热门文章

  1. 【HTLM作业】HTML网页设计--青春在线学校网站设计
  2. 计算机毕业设计Java动物防疫信息管理(源码+系统+mysql数据库+lW文档)
  3. Android 自定义 View:左右两边显示 text 的 TextView(RightAndLeftTextView)
  4. 利用Anusplin制作降雨数据插值
  5. 将8051单片机长数组存储在Flash中
  6. 计算机考研408需要带小刀吗,2021浙江考研要带小刀和固体胶吗
  7. 卡米洛特程 全景图:一种假说
  8. 吐血推荐 淘宝精品女装商城推荐 淘宝女装TOP 24 网购一定用得上的 淘宝女装皇冠大全...
  9. 制作地图的布局、元素和设计介绍
  10. ARM7与ARM Cortex比较