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


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

表單組件是個包含表單元素的區域,表單元素允許用戶輸入內容,比如:文本區域,下拉表單,單選框、復選框等,常見的應用場景有:登陸、注冊、輸入信息等。表單里有兩個重要的組件,一個是Form組件用來做整個表單提交使用的,另一個是TextFormField組件用來做用戶輸入的。

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的屬性,來獲取表單對象:

 

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

 

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

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。


 

接下來的內容有興趣的可以繼續看一下,我想以Android中寫xml的布局方式理解一下Flutter中的頁面構建,因為我前面一直是在寫簡單的組件Demo,還沒有形成一個完整的構建意識,以下是我個人的理解,如果有不對的地方,還請留言批評、指正,不勝感謝!!!

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

注:在這里我先說明以下在Flutter中child里面只能放一個Widget,Children可以放多個Widget。

我們來把Android和Flutter對比着理解,這樣應該可以更容易理解一點,也更直觀一點:

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簡單使用

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM