【Flutter 专题】08 小小优化【登录】页面

和尚前两天花了很久才搭建了一个最简单的【登录】页面,但依然还有很多需要优化的地方,和尚又花了很久的时间尝试做了一点点的优化,仅针对优化的部分简单整理一下。

优化一:解决 OverFlowed 遮挡文本框问题

1. 和尚刚开始在编辑内容块 content 时,以为涉及的 widget 元素不多,所占不会超过屏幕,所以根 widget 使用的是 body: new Container(),但是在点击文本框 TextField 时,弹出的键盘会挡住部分 widget,并提示 Bottom OverFlowed By 85 pixels,如图:

2. 和尚查了一下官网,调整方式很简单,将根 widget 调整为 body: new ListView()Flutter 中的 ListView 不仅代表列表 (ListView/RecycleView),还可以代表一个可滑动布局 (ScrollView),如图:

优化二:文本框 TextField 中尾部添加【清空数据】图标

方式一:使用层布局 Stack,在输入文本框 TextField 上一层添加一个【清空数据】图标;
new Padding(
  padding: new EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 15.0),
  child: new Stack(
    alignment: new Alignment(1.0, 1.0),
    //statck
    children: <Widget>[
      new Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            new Padding(
              padding:
                  new EdgeInsets.fromLTRB(0.0, 0.0, 5.0, 0.0),
              child: new Image.asset(
                'images/icon_username.png',
                width: 40.0,
                height: 40.0,
                fit: BoxFit.fill,
              ),
            ),
            new Expanded(
              child: new TextField(
                controller: _phonecontroller,
                keyboardType: TextInputType.phone,
                decoration: new InputDecoration(
                  hintText: '请输入用户名',
                ),
              ),
            ),
          ]),
      new IconButton(
        icon: new Icon(Icons.clear, color: Colors.black45),
        onPressed: () {
          _phonecontroller.clear();
        },
      ),
    ],
  ),
),
方式二:使用文本框 TextField 自带的属性【后缀图标 suffixIcon】,文本框 TextField 提供了很多便利的属性,例如:【前缀图标 prefixIcon】【文本框前图标 icon】;
new Expanded(
  child: new TextField(
    controller: _pwdcontroller,
    decoration: new InputDecoration(
      hintText: '请输入密码',
      suffixIcon: new IconButton(
        icon: new Icon(Icons.clear,
            color: Colors.black45),
        onPressed: () {
          _pwdcontroller.clear();
        },
      ),
    ),
    obscureText: true,
  ),
),

Tips: 和尚更倾向于方法二,方法一采用的是层布局,如果超过图标所在位置,若不做特别处理,之后输入的内容会被图标挡住,而且相较于方法二使用了更多的 widget。和尚为了测试,在【输入用户名】模块采用了方法一,【输入密码】模块采用了方法二。

优化三:调整键盘弹出样式

设置文本框 TextField 中 keyboardType: TextInputType.phone, Flutter 提供了多种弹出键盘的方式:text/datetime/phone/url/number/multiline/emailAddress…

优化四:根据输入文本框添加【温馨提示】对话框

Flutter 提供了创建和显示弹出对话框的功能,如:showDialog/showMenu/showModalBottomSheet 等,和尚采用的是对话框方式,可设置标题/内容/按钮等各属性。 Tips: 对话框中 barrierDismissible: false, 属性,若为false,点击对话框周围,对话框不会关闭;若为true,点击对话框周围,对话框自动关闭。

相关注意

Flutter 提供了很多便利的小图标,使用起来非常方便,和尚但就一个小【×】找到了好几个类似的图,希望可以多多尝试,体验一下。如图:

主要源码

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: '轻签到',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: '极速登录'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool _phoneState, _pwdState = false;
  String _checkStr;
  TextEditingController _phonecontroller = new TextEditingController();
  TextEditingController _pwdcontroller = new TextEditingController();

  void _checkPhone() {
    if (_phonecontroller.text.isNotEmpty &&
        _phonecontroller.text.trim().length == 11) {
      _phoneState = true;
    } else {
      _phoneState = false;
    }
  }

  void _checkPwd() {
    if (_pwdcontroller.text.isNotEmpty &&
        _pwdcontroller.text.trim().length >= 6 &&
        _pwdcontroller.text.trim().length <= 10) {
      _pwdState = true;
    } else {
      _pwdState = false;
    }
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: '轻签到',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('极速登录'),
        ),
        body: new ListView(
          children: <Widget>[
            new Column(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.start,

              children: <Widget>[
                new Padding(
                    padding: new EdgeInsets.all(30.0),
                    child: new Image.asset(
                      'images/ic_launcher.png',
                      scale: 1.2,
                    )),
                new Padding(
                  padding: new EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 15.0),
                  child: new Stack(
                    alignment: new Alignment(1.0, 1.0),
                    //statck
                    children: <Widget>[
                      new Row(
                          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                          children: [
                            new Padding(
                              padding:
                                  new EdgeInsets.fromLTRB(0.0, 0.0, 5.0, 0.0),
                              child: new Image.asset(
                                'images/icon_username.png',
                                width: 40.0,
                                height: 40.0,
                                fit: BoxFit.fill,
                              ),
                            ),
                            new Expanded(
                              child: new TextField(
                                controller: _phonecontroller,
                                keyboardType: TextInputType.phone,
                                decoration: new InputDecoration(
                                  hintText: '请输入用户名',
                                ),
                              ),
                            ),
                          ]),
                      new IconButton(
                        icon: new Icon(Icons.clear, color: Colors.black45),
                        onPressed: () {
                          _phonecontroller.clear();
                        },
                      ),
                    ],
                  ),
                ),
                new Padding(
                  padding: new EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 40.0),
                  child: new Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: [
                        new Padding(
                          padding: new EdgeInsets.fromLTRB(0.0, 0.0, 5.0, 0.0),
                          child: new Image.asset(
                            'images/icon_password.png',
                            width: 40.0,
                            height: 40.0,
                            fit: BoxFit.fill,
                          ),
                        ),
                        new Expanded(
                          child: new TextField(
                            controller: _pwdcontroller,
                            decoration: new InputDecoration(
                              hintText: '请输入密码',
                              suffixIcon: new IconButton(
                                icon: new Icon(Icons.clear,
                                    color: Colors.black45),
                                onPressed: () {
                                  _pwdcontroller.clear();
                                },
                              ),
                            ),
                            obscureText: true,
                          ),
                        ),
                      ]),
                ),
                new Container(
                  width: 340.0,
                  child: new Card(
                    color: Colors.blue,
                    elevation: 16.0,
                    child: new FlatButton(
                      child: new Padding(
                        padding: new EdgeInsets.all(10.0),
                        child: new Text(
                          '极速登录',
                          style: new TextStyle(
                              color: Colors.white, fontSize: 16.0),
                        ),
                      ),
                      onPressed: () {
                        _checkPhone();
                        _checkPwd();
                        if (_phoneState && _pwdState) {
                          _checkStr = '页面跳转下期见咯!';
                        } else {
                          if (!_phoneState) {
                            _checkStr = '请输入11位手机号!';
                          } else if (!_pwdState) {
                            _checkStr = '请输入6-10位密码!';
                          }
                        }
                        print(_checkStr);
                        showDialog<Null>(
                          context: context,
                          barrierDismissible: false,
                          child: new AlertDialog(
                            title: new Text(
                              '温馨提示',
                              style: new TextStyle(
                                color: Colors.black54,
                                fontSize: 18.0,
                              ),
                            ),
                            content: new Text(_checkStr),
                            actions: <Widget>[
                              new FlatButton(
                                  onPressed: () {
                                    Navigator.pop(context);
                                  },
                                  child: new Text('确定')),
                            ],
                          ),
                        );
                      },
                    ),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

GitHub Demo


和尚也是刚接触 Flutter,还有很多不清楚和不理解的地方,如果又不对的地方还希望多多指出。

原文发布于微信公众号 - 阿策小和尚(gh_8297e718c166)

原文发表时间:2018-08-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券