TextField
TextField decoration
keyboardType
TextField textInputAction
TextField onChanged
TextField onEditingComplete
TextField onSubmitted
TextField inputFormatters
TextField controller
TextField
Flutter中的文本輸入框(TextField)就類似于Android中的EditText,但是用起來比EditText方便很多,改變樣式也更加的方便。下面我們來看一下TextField的構(gòu)造方法
構(gòu)造方法
const TextField({
? ? Key key,
? ? this.controller,? ? //編輯框的控制器,跟文本框的交互一般都通過該屬性完成,如果不創(chuàng)建的話默認(rèn)會自動創(chuàng)建
? ? this.focusNode,? //用于管理焦點(diǎn)
? ? this.decoration = const InputDecoration(),? //輸入框的裝飾器,用來修改外觀
? ? TextInputType keyboardType,? //設(shè)置輸入類型,不同的輸入類型鍵盤不一樣
? ? this.textInputAction,? //用于控制鍵盤動作(一般位于右下角,默認(rèn)是完成)
? ? this.textCapitalization = TextCapitalization.none,
? ? this.style,? ? //輸入的文本樣式
? ? this.textAlign = TextAlign.start,? //輸入的文本位置
? ? this.textDirection,? ? //輸入的文字排列方向,一般不會修改這個屬性
? ? this.autofocus = false,? //是否自動獲取焦點(diǎn)
? ? this.obscureText = false,? //是否隱藏輸入的文字,一般用在密碼輸入框中
? ? this.autocorrect = true,? //是否自動校驗(yàn)
? ? this.maxLines = 1,? //最大行
? ? this.maxLength,? //能輸入的最大字符個數(shù)
? ? this.maxLengthEnforced = true,? //配合maxLength一起使用,在達(dá)到最大長度時是否阻止輸入
? ? this.onChanged,? //輸入文本發(fā)生變化時的回調(diào)
? ? this.onEditingComplete,? //點(diǎn)擊鍵盤完成按鈕時觸發(fā)的回調(diào),該回調(diào)沒有參數(shù),(){}
? ? this.onSubmitted,? //同樣是點(diǎn)擊鍵盤完成按鈕時觸發(fā)的回調(diào),該回調(diào)有參數(shù),參數(shù)即為當(dāng)前輸入框中的值。(String){}
? ? this.inputFormatters,? //對輸入文本的校驗(yàn)
? ? this.enabled,? ? //輸入框是否可用
? ? this.cursorWidth = 2.0,? //光標(biāo)的寬度
? ? this.cursorRadius,? //光標(biāo)的圓角
? ? this.cursorColor,? //光標(biāo)的顏色
? ? this.keyboardAppearance,
? ? this.scrollPadding = const EdgeInsets.all(20.0),
? ? this.dragStartBehavior = DragStartBehavior.down,
? ? this.enableInteractiveSelection,
? ? this.onTap,? ? //點(diǎn)擊輸入框時的回調(diào)(){}
? ? this.buildCounter,
? })
可以看到,屬性還是很多的,但都比較簡單,下面我們來看一下常用的屬性。
TextField decoration
我們首先來看一下decoration
decoration(裝飾器)?接收一個InputDecoration類型的值,主要用于控制TextField的外觀以及提示信息等
我們來看看InputDecoration的構(gòu)造方法
InputDecoration({
? ? this.icon,? ? //位于裝飾器外部和輸入框前面的圖片
? ? this.labelText,? //用于描述輸入框,例如這個輸入框是用來輸入用戶名還是密碼的,當(dāng)輸入框獲取焦點(diǎn)時默認(rèn)會浮動到上方,
? ? this.labelStyle,? // 控制labelText的樣式,接收一個TextStyle類型的值
? ? this.helperText, //輔助文本,位于輸入框下方,如果errorText不為空的話,則helperText不會顯示
? ? this.helperStyle, //helperText的樣式
? ? this.hintText,? //提示文本,位于輸入框內(nèi)部
? ? this.hintStyle, //hintText的樣式
? ? this.hintMaxLines, //提示信息最大行數(shù)
? ? this.errorText,? //錯誤信息提示
? ? this.errorStyle, //errorText的樣式
? ? this.errorMaxLines,? //errorText最大行數(shù)
? ? this.hasFloatingPlaceholder = true,? //labelText是否浮動,默認(rèn)為true,修改為false則labelText在輸入框獲取焦點(diǎn)時不會浮動且不顯示
? ? this.isDense,? //改變輸入框是否為密集型,默認(rèn)為false,修改為true時,圖標(biāo)及間距會變小
? ? this.contentPadding, //內(nèi)間距
? ? this.prefixIcon,? //位于輸入框內(nèi)部起始位置的圖標(biāo)。
? ? this.prefix,? //預(yù)先填充的Widget,跟prefixText同時只能出現(xiàn)一個
? ? this.prefixText,? //預(yù)填充的文本,例如手機(jī)號前面預(yù)先加上區(qū)號等
? ? this.prefixStyle,? //prefixText的樣式
? ? this.suffixIcon, //位于輸入框后面的圖片,例如一般輸入框后面會有個眼睛,控制輸入內(nèi)容是否明文
? ? this.suffix,? //位于輸入框尾部的控件,同樣的不能和suffixText同時使用
? ? this.suffixText,//位于尾部的填充文字
? ? this.suffixStyle,? //suffixText的樣式
? ? this.counter,//位于輸入框右下方的小控件,不能和counterText同時使用
? ? this.counterText,//位于右下方顯示的文本,常用于顯示輸入的字符數(shù)量
? ? this.counterStyle, //counterText的樣式
? ? this.filled,? //如果為true,則輸入使用fillColor指定的顏色填充
? ? this.fillColor,? //相當(dāng)于輸入框的背景顏色
? ? this.errorBorder,? //errorText不為空,輸入框沒有焦點(diǎn)時要顯示的邊框
? ? this.focusedBorder,? //輸入框有焦點(diǎn)時的邊框,如果errorText不為空的話,該屬性無效
? ? this.focusedErrorBorder,? //errorText不為空時,輸入框有焦點(diǎn)時的邊框
? ? this.disabledBorder,? //輸入框禁用時顯示的邊框,如果errorText不為空的話,該屬性無效
? ? this.enabledBorder,? //輸入框可用時顯示的邊框,如果errorText不為空的話,該屬性無效
? ? this.border, //正常情況下的border
? ? this.enabled = true,? //輸入框是否可用
? ? this.semanticCounterText,?
? ? this.alignLabelWithHint,
? })
我們先來用一下InputDecoration,這里我們主要介紹一下常用的屬性
默認(rèn)樣式
TextField(
? ? ? decoration: InputDecoration(),
? ? );

icon
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? icon: Icon(Icons.person),
? ? ? ),
? ? );

labelText
用于描述輸入框,例如這個輸入框是用來輸入用戶名還是密碼的,當(dāng)輸入框獲取焦點(diǎn)時默認(rèn)會浮動到上方
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? icon: Icon(Icons.person),
? ? ? ? labelText: "labelText",
? ? ? ),
? ? );
下面輸入框的用戶名對應(yīng)的就是labelText

labelStyle
設(shè)置labelText的樣式
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? ? icon: Icon(Icons.person),
? ? ? ? ? labelText: "labelText",
? ? ? ? ? labelStyle: TextStyle(
? ? ? ? ? ? color: Colors.red,
? ? ? ? ? ? fontSize: 20,
? ? ? ? ? )),
? ? );

helperText
輔助文本,位于輸入框下方,如果errorText不為空的話,則helperText不會顯示
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? icon: Icon(Icons.person),
? ? ? ? labelText: "labelText",
? ? ? ? helperText: "helperText",
? ? ? ),
? ? );

helperStyle
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? icon: Icon(Icons.person),
? ? ? ? labelText: "labelText",
? ? ? ? helperText: "helperText",
? ? ? ? helperStyle: TextStyle(
? ? ? ? ? color: Colors.green,//綠色
? ? ? ? ? fontSize: 20,//字體變大
? ? ? ? ),
? ? ? ),
? ? );

errorText
錯誤提示信息,如果該屬性不為null的話,labelText失效。

hintText
輸入框中的提示信息,這個沒啥好說的

hasFloatingPlaceholder
labelText是否浮動,默認(rèn)為true,修改為false則labelText在輸入框獲取焦點(diǎn)時不會浮動且不顯示
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? icon: Icon(Icons.person),
? ? ? ? hasFloatingPlaceholder: false,
? ? ? ? labelText: "labelText",
? ? ? ? helperText: "helperText",
? ? ? ? errorText: "errorText",
? ? ? ? hintText: "hintText",
? ? ? ),
? ? );

prefixIcon、prefixText
圖片和預(yù)填充的文字
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? icon: Icon(Icons.person),
? ? ? ? hasFloatingPlaceholder: false,
? ? ? ? labelText: "labelText",
? ? ? ? helperText: "helperText",
? ? ? ? errorText: "errorText",
? ? ? // hintText: "hintText",
? ? ? ? prefixIcon: Icon(Icons.perm_identity),
? ? ? ? prefixText: "prefixText",
? ? ? ),
? ? );

suffixIcon、suffixText
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? //icon: Icon(Icons.person),
? ? ? ? hasFloatingPlaceholder: false,
? ? ? ? labelText: "labelText",
//? ? ? ? helperText: "helperText",
//? ? ? ? errorText: "errorText",
? ? ? ? // hintText: "hintText",
? ? ? ? prefixIcon: Icon(Icons.perm_identity),
? ? ? ? prefixText: "prefixText",
? ? ? ? suffixIcon: Icon(
? ? ? ? ? Icons.remove_red_eye,
? ? ? ? ),
? ? ? ? suffixText: "suffixText",
? ? ? ),
? ? );

counterText
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? //icon: Icon(Icons.person),
? ? ? ? hasFloatingPlaceholder: false,
? ? ? ? labelText: "labelText",
? ? ? ? // helperText: "helperText",
//? ? ? ? errorText: "errorText",
? ? ? ? // hintText: "hintText",
//? ? ? ? prefixIcon: Icon(Icons.perm_identity),
//? ? ? ? prefixText: "prefixText",
//? ? ? ? suffixIcon: Icon(
//? ? ? ? ? Icons.remove_red_eye,
//? ? ? ? ),
//? ? ? ? suffixText: "suffixText",
? ? ? ? counterText: "counterText",
? ? ? ),
? ? );

filled,fillColor
顏色填充
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? //icon: Icon(Icons.person),
? ? ? ? hasFloatingPlaceholder: false,
? ? ? ? labelText: "labelText",
? ? ? ? // helperText: "helperText",
//? ? ? ? errorText: "errorText",
? ? ? ? hintText: "hintText",
? ? ? ? prefixIcon: Icon(Icons.perm_identity),
//? ? ? ? prefixText: "prefixText",
//? ? ? ? suffixIcon: Icon(
//? ? ? ? ? Icons.remove_red_eye,
//? ? ? ? ),
//? ? ? ? suffixText: "suffixText",
? ? ? // counterText: "counterText",
? ? ? ? filled: true,
? ? ? ? fillColor: Colors.grey,
? ? ? ),
? ? );

下面來看一下兩個輸入框的對比:
上面的輸入框代碼:
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? icon: Icon(Icons.person),
? ? ? // hasFloatingPlaceholder: false,
? ? ? ? labelText: "labelText",
? ? ? ? helperText: "helperText",
? ? ? ? errorText: "errorText",
? ? ? ? hintText: "hintText",
? ? ? ? prefixIcon: Icon(Icons.perm_identity),
? ? ? ? prefixText: "prefixText",
? ? ? ? suffixIcon: Icon(
? ? ? ? ? Icons.remove_red_eye,
? ? ? ? ),
? ? ? ? suffixText: "suffixText",
? ? ? ? counterText: "counterText",
? ? ? ? filled: true,
? ? ? // fillColor: Colors.grey,
? ? ? ),
? ? );
下面的輸入框代碼:
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? icon: Icon(Icons.person),
? ? ? ? prefixIcon: Icon(Icons.perm_identity),
? ? ? ? labelText: "手機(jī)號",
? ? ? ? helperText: "用戶名為手機(jī)號或者郵箱",
? ? ? ? errorText: "手機(jī)號碼不正確",
? ? ? ? hintText: "請輸入手機(jī)號碼",
? ? ? ? prefixText: "+86",
? ? ? ? suffixIcon: Icon(
? ? ? ? ? Icons.remove_red_eye,
? ? ? ? ),
? ? ? ? suffixText: "隱藏輸入文本",
? ? ? ? counterText: "0/10",
? ? ? ? filled: true,
? ? ? ),
? ? );

border、errorBorder、focusedBorder、focusedErrorBorder、disabledBorder、enabledBorder
不同狀態(tài)下的邊框樣式,他們接收值的類型都一樣,不過需要注意優(yōu)先級。
大致分為一下幾種情況
1. 控件禁用時
當(dāng)enabled為false時,如果指定了disabledBorder,優(yōu)先使用disabledBorder,沒有的話設(shè)置disabledBorder則使用border的部分樣式(顏色默認(rèn)是灰色)
2. 控件啟用(enable為true),但errorText有值
輸入框沒有焦點(diǎn)時,優(yōu)先使用errorBorder的樣式,輸入框有焦點(diǎn)時,優(yōu)先使用focusedErrorBorder,如果這兩個都沒有設(shè)置則使用border的部分樣式(顏色默認(rèn)是紅色)
3. 控件啟用狀態(tài),且errorText沒有值
輸入框沒有焦點(diǎn)時,優(yōu)先使用enabledBorder ,有焦點(diǎn)時,優(yōu)先使用focusedBorder,兩者均沒有指定時,使用默認(rèn)的border
總體來說,默認(rèn)的border優(yōu)先級別較低。
建議:
在開發(fā)過程中我們?nèi)绻枰猠rrorText的話,我們只需要設(shè)置 errorBorder、focusedErrorBorder這三個即可。不需要errorText的話
不需要errorText的話,只需要設(shè)置enabledBorder 、focusedBorder
下面我們來看一下border的值
1. InputBorder.none 沒有任何邊框
代碼:
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? border:InputBorder.none,
? ? ? ? labelText: "labelText",
? ? ? ? helperText: "helperText",
? ? ? // errorText: "errorText",
? ? ? ? hintText: "hintText",
? ? ? ? prefixIcon: Icon(Icons.perm_identity),
? ? ? ),
? ? );

2. OutlineInputBorder(外邊線)
代碼:
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? enabledBorder: OutlineInputBorder(
? ? ? ? ? /*邊角*/
? ? ? ? ? borderRadius: BorderRadius.all(
? ? ? ? ? ? Radius.circular(30), //邊角為30
? ? ? ? ? ),
? ? ? ? ? borderSide: BorderSide(
? ? ? ? ? ? color: Colors.amber, //邊線顏色為黃色
? ? ? ? ? ? width: 2, //邊線寬度為2
? ? ? ? ? ),
? ? ? ? ),
? ? ? ? focusedBorder: OutlineInputBorder(
? ? ? ? ? ? borderSide: BorderSide(
? ? ? ? ? color: Colors.green, //邊框顏色為綠色
? ? ? ? ? width: 5, //寬度為5
? ? ? ? )),
? ? ? ? labelText: "labelText",
? ? ? ? helperText: "helperText",
? ? ? ? // errorText: "errorText",
? ? ? ? hintText: "hintText",
? ? ? ? prefixIcon: Icon(Icons.perm_identity),
? ? ? ),
? ? );

2. UnderlineInputBorder(底邊線,默認(rèn)就是這個)
TextField(
? ? ? decoration: InputDecoration(
? ? ? ? errorBorder: UnderlineInputBorder(
? ? ? ? ? /*邊角*/
? ? ? ? ? borderRadius: BorderRadius.all(
? ? ? ? ? ? Radius.circular(30), //邊角為30
? ? ? ? ? ),
? ? ? ? ? borderSide: BorderSide(
? ? ? ? ? ? color: Colors.amber, //邊線顏色為黃色
? ? ? ? ? ? width: 2, //邊線寬度為2
? ? ? ? ? ),
? ? ? ? ),
? ? ? ? focusedErrorBorder: UnderlineInputBorder(
? ? ? ? ? ? borderSide: BorderSide(
? ? ? ? ? color: Colors.green, //邊框顏色為綠色
? ? ? ? ? width: 5, //寬度為5
? ? ? ? )),
? ? ? ? labelText: "labelText",
? ? ? ? helperText: "helperText",
? ? ? ? errorText: "errorText",
? ? ? ? hintText: "hintText",
? ? ? ? prefixIcon: Icon(Icons.perm_identity),
? ? ? ),
? ? );

到這里基本上InputDecoration的屬性都介紹完畢了。
keyboardType
鍵盤的類型,常用值如下,比較簡單

TextField(
? ? ? decoration: InputDecoration(
? ? ? ? labelText: "labelText",
? ? ? ? helperText: "helperText",
? ? ? ? errorText: "errorText",
? ? ? ? hintText: "hintText",
? ? ? ? prefixIcon: Icon(Icons.perm_identity),
? ? ? ),
? ? ? keyboardType: TextInputType.phone, //手機(jī)號
? ? );
可以看到 鍵盤變成了數(shù)字鍵盤,其他的值就不在演示了。

TextField textInputAction
鍵盤操作按鈕的類型,接收一個TextInputAction 類型的值。
TextInputAction 是一個枚舉類型,值如下,其中有些值需要考慮Android和ios是否兼容的問題:
enum TextInputAction {
//沒有任何動作
? none,
//讓操作系統(tǒng)決定哪個動作更合適
? unspecified,
//完成動作,一般會顯示“完成”二字
? done,
? /// 跳轉(zhuǎn)動作,一般用于輸入了一個超鏈接后執(zhí)行該動作。鍵盤上會顯示“前往”二字
? go,
//搜索動作
? search,
//發(fā)送
? send,
? ///下個
? next,
? /// 返回前一個
? previous,
//繼續(xù)動作,在Android上好像沒反應(yīng),不顯示鍵盤
? continueAction,
//在Android上好像沒反應(yīng),不顯示鍵盤
? route,
//撥打緊急電話,在Android上好像沒反應(yīng),不顯示鍵盤
? emergencyCall,
//換行
? newline,
}
例如:
textInputAction: TextInputAction.search,

textInputAction: TextInputAction.go,

TextField onChanged
輸入文本發(fā)生變化時的回調(diào),參數(shù)即為輸入框中的值
onChanged: (val) {
? ? ? ? print(val);
? ? ? },
TextField onEditingComplete
點(diǎn)擊鍵盤的動作按鈕時的回調(diào),沒有參數(shù)
onSubmitted: (val){
? ? ? ? print("點(diǎn)擊了鍵盤上的動作按鈕,當(dāng)前輸入框的值為:${val}");
? ? ? },
TextField inputFormatters
用于限制輸入的內(nèi)容,接收一個TextInputFormatter 類型的集合。
TextInputFormatter是一個抽象類,
源碼如下:

繼承關(guān)系如下
官方給我們提供了三種校驗(yàn)方法,分別是
1.WhitelistingTextInputFormatter 白名單校驗(yàn),也就是只允許輸入符合規(guī)則的字符
2.BlacklistingTextInputFormatter 黑名單校驗(yàn),除了規(guī)定的字符其他的都可以輸入
3.LengthLimitingTextInputFormatter 長度限制,跟maxLength作用類似

WhitelistingTextInputFormatter
首先我們來看看白名單,
部分源碼如下:

他接受一個Pattern類型的參數(shù),Pattern是一個接口,而RegExp實(shí)現(xiàn)了Pattern接口,

看到RegExp是不是很熟悉了,這不就是正則表達(dá)式么,那這樣就好辦了。
下面我們用一下白名單:
inputFormatters: [WhitelistingTextInputFormatter(RegExp("[a-z]"))],
例如,我們只允許輸入小寫的a到z。

BlacklistingTextInputFormatter
黑名單跟白名單用法類似,這里我就直接用了
inputFormatters: [BlacklistingTextInputFormatter(RegExp("[a-z]"))],
除了小寫的a到z都可以輸入

LengthLimitingTextInputFormatter
限制輸入的長度
這里我們配合之前的黑名單一起使用
inputFormatters: [
? ? ? ? BlacklistingTextInputFormatter(RegExp("[a-z]")),
? ? ? ? LengthLimitingTextInputFormatter(5)
? ? ? ],

TextField controller
controller常用于賦值和取值操作
示例代碼:
import 'package:flutter/material.dart';
class TextFieldWidget extends StatefulWidget {
? @override
? State<StatefulWidget> createState() {
? ? return _TextFieldState();
? }
}
class _TextFieldState extends State<TextFieldWidget> {
? TextEditingController _userEtController = TextEditingController();
? @override
? Widget build(BuildContext context) {
? ? return Scaffold(
? ? ? appBar: AppBar(
? ? ? ? title: Text("TextField"),
? ? ? ),
? ? ? body: Container(
? ? ? ? padding: EdgeInsets.all(10),
? ? ? ? child: Column(
? ? ? ? ? children: <Widget>[
? ? ? ? ? ? TextField(
? ? ? ? ? ? ? controller: _userEtController,
? ? ? ? ? ? ),
? ? ? ? ? ? RaisedButton(
? ? ? ? ? ? ? child: Text("賦值"),
? ? ? ? ? ? ? onPressed: () {
? ? ? ? ? ? ? ? setState(() {
? ? ? ? ? ? ? ? ? _userEtController.text = "15937600635";
? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? },
? ? ? ? ? ? ),
? ? ? ? ? ? RaisedButton(
? ? ? ? ? ? ? child: Text("獲取值"),
? ? ? ? ? ? ? onPressed: () {
? ? ? ? ? ? ? ? setState(() {});
? ? ? ? ? ? ? },
? ? ? ? ? ? ),
? ? ? ? ? ? Text(_userEtController.text),
? ? ? ? ? ],
? ? ? ? ),
? ? ? ),
? ? );
? }
}
如下:
