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
,則無行數限制。maxLength
和maxLengthEnforced
:maxLength
代表輸入框文本的最大長度,設置后輸入框右下角會顯示輸入的文本計數。maxLengthEnforced
決定當輸入文本長度超過maxLength
時是否阻止輸入,為true
時會阻止輸入,為false
時不會阻止輸入但輸入框會變紅。onChange
:輸入框內容改變時的回調函數;注:內容改變事件也可以通過controller
來監聽。onEditingComplete
和onSubmitted
:這兩個回調都是在輸入框輸入完成時觸發,比如按了鍵盤的完成鍵(對號圖標)或搜索鍵(??圖標)。不同的是兩個回調簽名不同,onSubmitted
回調是ValueChanged<String>
類型,它接收當前輸入內容做為參數,而onEditingComplete
不接收參數。inputFormatters
:用于指定輸入格式;當用戶輸入內容改變時,會根據指定的格式來校驗。enable
:如果為false
,則輸入框會被禁用,禁用狀態不接收輸入和事件,同時顯示禁用態樣式(在其decoration
中定義)。cursorWidth
、cursorRadius
和cursorColor
:這三個屬性是用于自定義輸入框光標寬度、圓角和顏色的。
二、登錄示例:手機號+密碼
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");
},
)
運行效果
-
使用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,
)
運行效果
以上兩種方法都可以成功獲取到用戶輸入的手機號和密碼。兩種方式相比,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還有很多其他的屬性,下圖所示為比較常用的一些屬性,更多屬性請查閱文檔: