天天看點

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...

鍵盤樣式.png

phone

優化四:根據輸入文本框添加【溫馨提示】對話框

      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,還有很多不清楚和不了解的地方,如果又不對的地方還希望多多指出。以下是小菜公衆号,歡迎閑來吐槽~

公衆号

繼續閱讀