Flutter學習筆記(13)--表單組件

如需轉載,請註明出處:Flutter學習筆記(13)--表單組件

表單組件是個包含表單元素的區域,表單元素容許用戶輸入內容,好比:文本區域,下拉表單,單選框、複選框等,常見的應用場景有:登錄、註冊、輸入信息等。表單裏有兩個重要的組件,一個是Form組件用來作整個表單提交使用的,另外一個是TextFormField組件用來作用戶輸入的。html

Form組件屬性
屬性 類型 說明
Key Key 組件在整個Widget樹中的key值
autovalidate bool 是否自動提交表單
child Widget 組件child只能有一個組件
onChange VoidCallback 當FormField值改變時的回調函數

 

 

 

 

 

 

 

 

 

TextFormFiled組件屬性
屬性名 類型 說明
autovalidate bool 自動驗證值
initalValue T 表單字段初始值,好比:輸入收穫地址時,默認回填本的地址信息
onSaved FormFieldSetter<T> 當Form表單調用保存方法Save時回調的函數
validator FormFieldValidator<T> Form表單驗證器

 

 

 

 

 

 

 

 

 

對於輸入框咱們最關心的時輸入內容是否合法,好比郵箱地址是否正確,電話號碼是不是數字等等,等用戶輸入完成後,咱們須要知道輸入框輸入的內容。那麼咱們要如何才能獲取到表單對象呢?爲了獲取表單的實例,咱們須要設置一個全局類型的key,經過這個key的屬性,來獲取表單對象:app

 

GlobalKey<FormState> globalKey = new GlobalKey<FormState>();

 

咱們來簡單的寫一個登錄頁面,校驗輸入框內的內容,當內容不合法時,並給出相應的提示:ide

import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';

void main() => runApp(DemoApp());

class DemoApp extends StatefulWidget{
  @override
  _DemoAppState createState() => new _DemoAppState();
}

class _DemoAppState extends State<DemoApp> {
  String userName;
  String userPwd;
  GlobalKey<FormState> globalKey = new GlobalKey<FormState>();
  void check(){
    var loginForm = globalKey.currentState;
    //驗證表單
    if(loginForm.validate()){
      loginForm.save();
      Fluttertoast.showToast(msg: '信息提交成功',toastLength: Toast.LENGTH_LONG,gravity: ToastGravity.BOTTOM,textColor: Colors.white);
    }
  }
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'From表單Demo',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Form表單Demo'),
          leading: Icon(Icons.menu,size: 30,),
          actions: <Widget>[
            IconButton(icon: Icon(Icons.search),iconSize: 30, onPressed: null)
          ],
        ),
        body: new Column(
          children: <Widget>[
            new Form(
              key: globalKey,
              child: new Column(
                children: <Widget>[
                  new TextFormField(
                    decoration: new InputDecoration(
                      labelText: '請輸入用戶名',
                    ),
                    onSaved: (value){
                      userName = value;
                    },
                  ),
                  new TextFormField(
                    decoration: new InputDecoration(
                      contentPadding: EdgeInsets.only(left: 20,top: 10,right: 0,bottom: 0),
                      hintText: '請輸入密碼',
                      hintStyle: new TextStyle(fontSize: 30,color: Colors.amberAccent)
                    ),
                    obscureText: true,
                    validator: (value){
                      return value.length < 6 ? '密碼長度不夠6位' : null;
                    },
                    onSaved: (value){
                      userPwd = value;
                    },
                  )
                ],
              ),
            ),
            new Container(
              margin: new EdgeInsets.symmetric(vertical: 20,horizontal: 0),
              width: 330,
              height: 50,
              child: new SizedBox(
                child: new RaisedButton(
                  onPressed: check,
                  child: new Text(
                    '肯定',
                    style: new TextStyle(
                        fontSize: 20,
                        color: Colors.white
                    ),
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

 

先看一下上面代碼的效果截圖,而後我會給你們講一下代碼的內容函數

                                   

寫的比較醜,你們見諒,主要是由於我想多試試一些屬性怎麼用,總之是要多嘗試嘛~佈局

上面是輸入內容前和輸入內容後的對比圖,從直觀的表象上能夠看的出來,用戶名輸入框輸入內容後,提示內容被擠到上面去了,而密碼輸入框輸入內容後提示內容則消失了,這是由於兩個輸入框提示語的text的類型使用的不一樣,用戶名:labelText,密碼:hintText,這兩個都有style屬性,均可以對默認的提示內容字體進行屬性設置。在點擊確認按鈕後,會調用check()方法,在check()方法中提交表單驗證,這時候會觸發密碼輸入框中的validator: (value),從而實現咱們密碼輸入框內容的校驗,這個就是TextFromField中的驗證回調方法,在表單驗證的時候,會先驗證這個方法中的邏輯判斷,若是驗證失敗返回錯誤信息,若是驗證經過則返回null。post


 

接下來的內容有興趣的能夠繼續看一下,我想以Android中寫xml的佈局方式理解一下Flutter中的頁面構建,由於我前面一直是在寫簡單的組件Demo,尚未造成一個完整的構建意識,如下是我我的的理解,若是有不對的地方,還請留言批評、指正,不勝感謝!!!學習

從整個頁面來構思的話,能夠看作是一個大容器,容器裏面有三個組件,分別是兩個輸入框和一個按鈕,這3個組件是垂直方向排列的,寫Android的同窗看到這個頁面,很容易就會想到最外層放一個Linearlayout或者是一個RelativeLayout,而後在裏面垂直方向放上兩個EditText和一個Button,再寫一下控件的屬性的就完事兒了,其實寫Flutter也是這種思想。字體

注:在這裏我先說明如下在Flutter中child裏面只能放一個Widget,Children能夠放多個Widget。ui

咱們來把Android和Flutter對比着理解,這樣應該能夠更容易理解一點,也更直觀一點:url

1.Android:最外層垂直方向的Linearlayout或RelativeLayout。

   Flutter:最外層body咱們new了一個Column(Column也是一個容器,相似於Container)

2.Android:放上兩個EditText和一個Button

   Flutter:容器放置好了,咱們要開始往容器裏面加組件元素了,由於容器裏面咱們要放置多個組件,因此咱們要使用children,children裏面放一個Form表單和一個button,在Form表單裏面,咱們要放兩個輸入框,並且是垂直方向放置的,想到這裏是否是就該先考慮怎麼把方向設置好呢?因此Form表單裏的第一層widget就要放置一個Column容器,容器裏面放兩個輸入框,既然是兩個,那麼是否是兩個輸入框就應該被一個children包裹起來呢?

總的來講:根widget(column)->children(裏面包含Form和button)->Form表單(第一層)->child(column)->children(裏面包含了兩個輸入框TextFormField)->TextFormField(第三層)

 

最後看一下按鈕部分的代碼,說明一下爲何外面要包一層Container

new Container(
              margin: new EdgeInsets.symmetric(vertical: 20,horizontal: 0),
              width: 330,
              height: 50,
              child: new SizedBox(
                child: new RaisedButton(
                  onPressed: check,
                  child: new Text(
                    '肯定',
                    style: new TextStyle(
                        fontSize: 20,
                        color: Colors.white
                    ),
                  ),
                ),
              ),
            )

之因此最外層包了個Container,是由於SizedBox和RaiseButton這兩個組件都沒有margin或padding屬性,因此UI上要想控制邊距等操做,這是一種處理方式。

 

也不知道我上面大白話寫了那麼多,能不能表達清楚個人意思,若是有沒看懂的,還麻煩留言提問吧!!!

 

下一章節:Flutter學習筆記(14)--StatefulWidget簡單使用

相關文章
相關標籤/搜索