Flutter从入门到奔溃(一):撸一个登陆界面

Flutter从入门到奔溃(一):撸一个登陆界面

前记

跨平台开发目前有3种途径:ReactNative,Weex,Flutter,至于他们之间的区别以及如何取舍,我以为这在移动端工程师的圈子里已经讨论烂了吧,这里就不赘述了,我就说下个人见解: 千万!千万!!千万!!!不要试图觉得你能够踩完weex的坑。 见解完毕,咱们来开始接触Flutter吧! Flutter是谷歌爸爸的新一代开发语音,主打的也是ios以及android两个端,可是不只仅是局限于这个,Flutter也是谷歌爸爸下一代操做系统的指定开发工具,身为安卓🐶,紧跟谷歌爸爸老是没错的,为此我仍是以为抛弃rn,weex这些es6的,专心投入dart的怀抱(不是由于我讨厌js和css)。css

学习指标

由于我比较懒...并且我是项目型驱动的懒鬼,个人学习方式能够总结为: 作项目+踩坑+填坑+踩坑+填坑...+骂娘=掌握一门知识 因此咱们用flutter来作一个项目吧!android

环境搭建

按照官网教程就能够了,过几天我写个详细点的ios

基础介绍

我也不是很基础...等我整明白了再出个详细点es6

weight介绍

同上weex

登陆界面的实现

页面逻辑讲解

870957617161924503.jpg

咱们能够看到页面很简洁:app

  • 一个logo
  • 一个帐号输入框
  • 一个密码输入框
  • 一个登陆按钮

如今咱们把页面拆解一下:less

  1. AppBar
  2. Body
    1. 帐号框
    2. 密码框
    3. 登陆按钮

能够看到页面主要分为2个层级: 最顶层的(只针对于代码层次的顶层,不包括window之类的层级)为: AppBar(标题栏) Body(主体栏) 而Body里面则包含了次级的widgetside

具体实现

咱们先贴代码,而后进行具体的讲解工具

import 'package:flutter/material.dart';

class LoginPage extends StatefulWidget {

  @override
  State<StatefulWidget> createState() {
    return new _LoginPageState();
  }
}

class _LoginPageState extends State<LoginPage> {
  var leftRightPadding = 30.0;
  var topBottomPadding = 4.0;
  var textTips = new TextStyle(fontSize: 16.0, color: Colors.black);
  var hintTips = new TextStyle(fontSize: 15.0, color: Colors.black26);
  static const LOGO = "images/oschina.png";

  var _userPassController = new TextEditingController();
  var _userNameController = new TextEditingController();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("登陆", style: new TextStyle(color: Colors.white)),
          iconTheme: new IconThemeData(color: Colors.white),
        ),
        body: new Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            new Padding(
              padding: new EdgeInsets.fromLTRB(
                  leftRightPadding, 50.0, leftRightPadding, 10.0),
              child: new Image.asset(LOGO),
            ),
            new Padding(
              padding: new EdgeInsets.fromLTRB(
                  leftRightPadding, 50.0, leftRightPadding, topBottomPadding),
              child: new TextField(
                style: hintTips,
                controller: _userNameController,
                decoration: new InputDecoration(hintText: "请输入用户名"),
                obscureText: true,
              ),
            ),
            new Padding(
              padding: new EdgeInsets.fromLTRB(
                  leftRightPadding, 30.0, leftRightPadding, topBottomPadding),
              child: new TextField(
                style: hintTips,
                controller: _userPassController,
                decoration: new InputDecoration(hintText: "请输入用户密码"),
                obscureText: true,
              ),
            ),
            new Container(
              width: 360.0,
              margin: new EdgeInsets.fromLTRB(10.0, 40.0, 10.0, 0.0),
              padding: new EdgeInsets.fromLTRB(leftRightPadding,
                  topBottomPadding, leftRightPadding, topBottomPadding),
              child: new Card(
                color: Colors.green,
                elevation: 6.0,
                child: new FlatButton(
                    onPressed: () {
                      print("the pass is" + _userNameController.text);
                    },
                    child: new Padding(
                      padding: new EdgeInsets.all(10.0),
                      child: new Text(
                        '立刻登陆',
                        style:
                            new TextStyle(color: Colors.white, fontSize: 16.0),
                      ),
                    )),
              ),
            )
          ],
        ));
  }
}
复制代码

如今咱们能够看到整个的布局了,怎么说呢...对于一个写习惯了android的人来讲,这种代码风格还真的是适应不了,特别是一串一串一串的 ),)),]})},说实在的,我很怀念xml,甚至是kotlin。布局

整个页面的基础

由于页面的须要变更的,因此咱们使用了**StatefulWidget **,而*StatefulWidget StatelessWidget *的区别,请看我以前的博文。 在State的build方法中,咱们开始进行页面的构建:

@override
  Widget build(BuildContext context) {
	  return new Scaffold(
			appBar:new AppBar(),
			body:new Column(),
		)
  }
复制代码

其中AppBar放导航信息, Body放主体信息,

主体子widgets的构建

body: new Column(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            new Padding(
              padding: new EdgeInsets.fromLTRB(
                  leftRightPadding, 50.0, leftRightPadding, 10.0),
              child: new Image.asset(LOGO),
            ),
            new Padding(
              padding: new EdgeInsets.fromLTRB(
                  leftRightPadding, 50.0, leftRightPadding, topBottomPadding),
              child: new TextField(
                style: hintTips,
                controller: _userNameController,
                decoration: new InputDecoration(hintText: "请输入用户名"),
                obscureText: true,
              ),
            ),
            new Padding(
              padding: new EdgeInsets.fromLTRB(
                  leftRightPadding, 30.0, leftRightPadding, topBottomPadding),
              child: new TextField(
                style: hintTips,
                controller: _userPassController,
                decoration: new InputDecoration(hintText: "请输入用户密码"),
                obscureText: true,
              ),
            ),
            new Container(
              width: 360.0,
              margin: new EdgeInsets.fromLTRB(10.0, 40.0, 10.0, 0.0),
              padding: new EdgeInsets.fromLTRB(leftRightPadding,
                  topBottomPadding, leftRightPadding, topBottomPadding),
              child: new Card(
                color: Colors.green,
                elevation: 6.0,
                child: new FlatButton(
                    onPressed: () {
                      print("the pass is" + _userNameController.text);
                    },
                    child: new Padding(
                      padding: new EdgeInsets.all(10.0),
                      child: new Text(
                        '立刻登陆',
                        style:
                            new TextStyle(color: Colors.white, fontSize: 16.0),
                      ),
                    )),
              ),
            )
          ],
        ));

复制代码

页面布局看得是真糟心...此时我又很怀念xml了... 页面从头到底我用白话文梳理一下:

  1. 一个从头开始排列的铺满父布局的数值排列的多布局父控件里面有一串子Widgets
  2. 第一个子Widgets是一个img Widgets,他被padding Widgets包裹着,以便于让它获得padding的属性
  3. 第二个子Widgets是一个TextFidld Widgets(Android佬们能够把他当作EditText),它也被padding Widgets包裹着,提供了四边的padding,同时它还经过InputDecoration设置了hint,经过controller设置了controller
  4. 第三个子Widgets同上,理论上应该抽取公共方法,第二个第三个不该该是copy过去的
  5. 第四个Widgets是一个FlatButton(实际上它上面还包裹着两个Widgets),它经过被Container包裹获得了宽高padding,margin的属性;经过被card包裹获得了阴影的属性。

至此布局完毕,总结一下: 第一次写以为很麻烦,特别麻烦! 第二次写以为还行,就是)){{{}}}看得眼睛痛 第三次写以为...挖草,神经病啊 第四次写以为...生活啊,反抗不了,你qj我吧 第五次写以为...咦,用着感受还有点点激动 第六次写以为,好像还挺方便 ... ... 第N次,爽!老子才不要xml。

页面交互

这个页面交互很少,无非2个:

  1. 拿到TextField的值
  2. 相应FlatButton的点击

嗯...我找不到id,也找不到findViewById,也找不到String mAccount=mEdLoginAccout.getText.toString()... 扑街...

不过还记得咱们刚刚定义的TextEditingController吗?操做TextField通常都是经过操控Controller来实现的,而咱们最简单最经常使用的就是

TextEditingController.text
// 等于EditText.getText()
复制代码

而点击事件可使用onPressed()

onPressed: () {
     print("the pass is" + _userNameController.text);
	            },
复制代码

总结

  1. 一不当心又水了一篇,没啥干货,由于我也是初学,边学边记录
  2. Flutter挺不错的,至少渲染方式不是跟weex(巨坑的!!!)和rn同样,而是走本身的一套,这点我很看好,由于其实rn和weex的体验并非特别好
  3. Flutter的listview在个人mx5上会有卡顿,我不知道是我没有优化好代码仍是怎么样...我先马克,带着这个问题继续学习
  4. 干巴爹
相关文章
相关标签/搜索