Flutter基礎組件<輸入框TextField>

Flutter入門筆記系列文章部分內容來源于《Flutter 實戰》,如有侵權請聯系刪除!

Material組件庫中為我們提供了輸入框組件TextField。不管是Web端還是移動端開發,輸入框都是最常用的組件之一,因此掌握輸入框的使用顯得尤為重要。

一、屬性介紹

TextField屬性比較多,本文只介紹其中比較常用的屬性,更多屬性請查閱SDK或官方文檔。

const TextField({
  Key key,
  this.controller,
  this.focusNode,
  this.decoration = const InputDecoration(),
  TextInputType keyboardType,
  this.textInputAction,
  this.textCapitalization = TextCapitalization.none,
  this.style,
  this.strutStyle,
  this.textAlign = TextAlign.start,
  this.textAlignVertical,
  this.textDirection,
  this.readOnly = false,
  ToolbarOptions toolbarOptions,
  this.showCursor,
  this.autofocus = false,
  this.obscureText = false,
  this.autocorrect = true,
  this.enableSuggestions = true,
  this.maxLines = 1,
  this.minLines,
  this.expands = false,
  this.maxLength,
  this.maxLengthEnforced = true,
  this.onChanged,
  this.onEditingComplete,
  this.onSubmitted,
  this.inputFormatters,
  this.enabled,
  this.cursorWidth = 2.0,
  this.cursorRadius,
  this.cursorColor,
  this.keyboardAppearance,
  this.scrollPadding = const EdgeInsets.all(20.0),
  this.dragStartBehavior = DragStartBehavior.start,
  this.enableInteractiveSelection = true,
  this.onTap,
  this.buildCounter,
  this.scrollController,
  this.scrollPhysics,
})
  • controller:編輯框的控制器,通過它可以設置/獲取編輯框的內容、選擇編輯內容、監聽編輯文本改變事件。大多數情況下我們都需要顯式提供一個controller來與文本框交互。如果沒有提供controller,則TextField內部會自動創建一個。

  • focusNode:用于控制TextField是否占有當前鍵盤的輸入焦點。它是我們和鍵盤交互的一個句柄(handle)。

  • InputDecoration:用于控制TextField的外觀顯示,如提示文本、背景顏色、邊框等。

  • keyboardType:用于設置該輸入框默認的鍵盤輸入類型,取值如下:

TextInputType枚舉值 含義
text 文本輸入鍵盤
multiline 多行文本,需和maxLines配合使用(設為null或大于1)
number 數字,會彈出數字鍵盤
phone 優化后的電話號碼輸入鍵盤;會彈出數字鍵盤并顯示“* #”
datetime 優化后的日期輸入鍵盤;Android上會顯示“: -”
emailAddress 優化后的電子郵件地址;會顯示“@ .”
url 優化后的url輸入鍵盤; 會顯示“/ .”
  • textInputAction:鍵盤動作按鈕圖標(即回車鍵位圖標),它是一個枚舉值,有多個可選值,全部的取值列表讀者可以查看API文檔,下面是當值為TextInputAction.search時,原生Android系統下鍵盤樣式如圖3-24所示:

    圖3-24
  • style:正在編輯的文本樣式。

  • textAlign: 輸入框內編輯文本在水平方向的對齊方式。

  • autofocus: 是否自動獲取焦點。

  • obscureText:是否隱藏正在編輯的文本,如用于輸入密碼的場景等,文本內容會用“?”替換。

  • maxLines:輸入框的最大行數,默認為1;如果為null,則無行數限制。

  • maxLengthmaxLengthEnforcedmaxLength代表輸入框文本的最大長度,設置后輸入框右下角會顯示輸入的文本計數。maxLengthEnforced決定當輸入文本長度超過maxLength時是否阻止輸入,為true時會阻止輸入,為false時不會阻止輸入但輸入框會變紅。

  • onChange:輸入框內容改變時的回調函數;注:內容改變事件也可以通過controller來監聽。

  • onEditingCompleteonSubmitted:這兩個回調都是在輸入框輸入完成時觸發,比如按了鍵盤的完成鍵(對號圖標)或搜索鍵(??圖標)。不同的是兩個回調簽名不同,onSubmitted回調是ValueChanged<String>類型,它接收當前輸入內容做為參數,而onEditingComplete不接收參數。

  • inputFormatters:用于指定輸入格式;當用戶輸入內容改變時,會根據指定的格式來校驗。

  • enable:如果為false,則輸入框會被禁用,禁用狀態不接收輸入和事件,同時顯示禁用態樣式(在其decoration中定義)。

  • cursorWidthcursorRadiuscursorColor:這三個屬性是用于自定義輸入框光標寬度、圓角和顏色的。

二、登錄示例:手機號+密碼

1、編寫布局代碼

TextField(
  keyboardType: TextInputType.phone,
  maxLines: 1,
  autofocus: false,
  cursorColor: Colors.blue,
  maxLength: 11,
  maxLengthEnforced: true,
  focusNode: phoneFocusNode,
  decoration: InputDecoration(
    hintText: "請輸入手機號碼",
    labelText: "手機號",
    prefixIcon: Icon(Icons.phone),
    // 未獲得焦點下劃線設為灰色
    enabledBorder: UnderlineInputBorder(
      borderSide: BorderSide(color: Colors.grey),
    ),
    //獲得焦點下劃線設為藍色
    focusedBorder: UnderlineInputBorder(
      borderSide: BorderSide(color: Colors.blue),
    ),
  ),
),
TextField(
  keyboardType: TextInputType.text,
  obscureText: true,
  maxLines: 1,
  autofocus: false,
  cursorColor: Colors.blue,
  focusNode: passwordFocusNode,
  decoration: InputDecoration(
    hintText: "請輸入密碼",
    labelText: "密碼",
    prefixIcon: Icon(Icons.vpn_key),
    // 未獲得焦點下劃線設為灰色
    enabledBorder: UnderlineInputBorder(
      borderSide: BorderSide(color: Colors.grey),
    ),
    //獲得焦點下劃線設為藍色
    focusedBorder: UnderlineInputBorder(
      borderSide: BorderSide(color: Colors.blue),
    ),
  ),
),
Padding(
  padding: EdgeInsets.all(16),
  child: RaisedButton(
      child: Text("開始登錄"),
      onPressed: () {
        //開始登錄
      }),
)

運行效果


登錄頁面

2、獲取輸入內容

  • 使用onChanged監聽文本變化

最簡單直接的方法是使用TextFile的onChanged屬性監聽輸入框文本變化,從而獲取到手機號和密碼。

TextField(
  ……
  onChanged: (text) {
       print("phone=$text");
  },
)
TextField(
  ……
  onChanged: (text) {
       print("password=$text");
  },
)

運行效果


onChanged監聽文本
  • 使用controller監聽文本變化

controller使用步驟如下:
創建TextEditingController -> 設置TextFile的controller屬性controller: phoneController, -> 重寫方法initState()監聽文本變化。

class _MyHomePageState extends State<MyHomePage> {
  bool checkboxState = false; //CheckBox狀態
  bool switchState = false; //Switch狀態

  void _incrementCounter() {
    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  }

  TextEditingController phoneController = TextEditingController();
  TextEditingController passwordController = TextEditingController();

  @override
  initState(){
    //監聽輸入改變
    phoneController.addListener((){
      //通過controller獲取輸入框內容
      print("phone="+phoneController.text);
    });
    passwordController.addListener((){
    //通過controller獲取輸入框內容
      print("password="+passwordController.text);
    });
  }
  ……
}

設置TextField的controller屬性

TextField(
  ……
  controller: phoneController,
)

運行效果


controller監聽文本

以上兩種方法都可以成功獲取到用戶輸入的手機號和密碼。兩種方式相比,onChanged是專門用于監聽文本變化,而controller的功能卻多一些,除了能監聽文本變化外,它還可以設置默認值、選擇文本。因此我們應該根據實際需求選擇最合適的方法

三、控制輸入框焦點

焦點可以通過FocusNode和FocusScopeNode來控制,默認情況下,焦點由FocusScope來管理,它代表焦點控制范圍,可以在這個范圍內可以通過FocusScopeNode在輸入框之間移動焦點、設置默認焦點等。我們可以通過FocusScope.of(context) 來獲取Widget樹中默認的FocusScopeNode。

在上面登錄的例子中可以看到TextField中有一個屬性focusNode,它的值是FocusNode。簡單介紹一下FocusNode中幾個比較常用的成員變量和方法:

  • hasFocus
    判斷當前Node是否擁有輸入焦點
  • nextFocus()
    焦點移動到下一個FocusNode
  • previousFocus()
    焦點移動到上一個FocusNode
  • requestFocus([FocusNode node])
    指定某個FocusNode獲得焦點
  • unfocus({ bool focusPrevious = false })
    從具有主要焦點的FocusNode上刪除焦點,并取消所有未完成的聚焦請求。
    如果[focusPrevious]為true,焦點將會被移至FocusScopeNode覺得最合適的節點。當然FocusScopeNode會根據使用[FocusScopeNode.setFirstFocus]設置為首先關注節點的節點的歷史記錄,判斷出最合適的節點。
    這一段我翻譯得可能不太準確,所有附上官方解釋吧!
    if [focusPrevious] is true, then rather than losing all focus, the focus will be moved to the node that the [enclosingScope] thinks should have it, based on its history of nodes that were set as first focus on it using [FocusScopeNode.setFirstFocus].
  • addListener(VoidCallback listener)
    FocusNode繼承自ChangeNotifier,可以監聽焦點的改變事件
// 創建 focusNode   
FocusNode focusNode = new FocusNode();

// focusNode綁定輸入框   
TextField(focusNode: focusNode);

// 監聽焦點變化    
focusNode.addListener((){
   print(focusNode.hasFocus);
});

獲得焦點時focusNode.hasFocus值為true,失去焦點時為false。

四、自定義輸入框樣式

我們可以通過decoration屬性來定義輸入框樣式:

TextField(
  decoration: InputDecoration(
    //在這里定義樣式的屬性
    ……
  )
)

InputDecoration屬性比較多,我們通過幾個簡單的例子來介紹它們。

1、下劃線

下面是與下劃線有關的屬性

屬性 InputDecoration持有焦點 InputDecoration顯示errorText
errorBorder NO YES
focusedBorder YES NO
focusedErrorBorder YES YES
屬性 InputDecoration可用 InputDecoration顯示errorText
disabledBorder NO NO
enabledBorder YES NO

例子:獲取焦點時下劃線為藍色,失去焦點下劃線為灰色

TextField(
  keyboardType: TextInputType.phone,
  maxLines: 1,
  autofocus: false,
  cursorColor: Colors.blue,
  textInputAction: TextInputAction.next,
  onSubmitted: (value) {
    print("onSubmitted$value");
    phoneFocusNode.nextFocus();
  },
  maxLength: 11,
  maxLengthEnforced: true,
  focusNode: phoneFocusNode,
//              onChanged: (text) {
//                print("phone=$text");
//              },
  controller: phoneController,
  decoration: InputDecoration(
    hintText: "請輸入手機號碼",
    labelText: "手機號",
    prefixIcon: Icon(Icons.phone),
    // 未獲得焦點下劃線設為灰色
    enabledBorder: UnderlineInputBorder(
      borderSide: BorderSide(color: Colors.grey),
    ),
    //獲得焦點下劃線設為藍色
    focusedBorder: UnderlineInputBorder(
      borderSide: BorderSide(color: Colors.blue),
    ),
  ),
),

運行效果


獲得焦點

失去焦點

2、其他屬性

InputDecoration還有很多其他的屬性,下圖所示為比較常用的一些屬性,更多屬性請查閱文檔:


其他屬性
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容