1. TextField Widget
TextField用于接收用戶的文本輸入
1.1 基本屬性
TextField
const TextField({
Key key,
this.controller,//控制器
this.focusNode,//焦點(diǎn)
this.decoration = const InputDecoration(),//裝飾
TextInputType keyboardType,//鍵盤類型易阳,即輸入類型
this.textInputAction,//鍵盤按鈕
this.textCapitalization = TextCapitalization.none,//大小寫
this.style,//樣式
this.strutStyle,
this.textAlign = TextAlign.start,//對(duì)齊方式
this.textDirection,
this.autofocus = false,//自動(dòng)聚焦
this.obscureText = false,//是否隱藏文本蛮拔,即顯示密碼類型
this.autocorrect = true,//自動(dòng)更正
this.maxLines = 1,//最多行數(shù),高度與行數(shù)同步
this.minLines,//最小行數(shù)
this.expands = false,
this.maxLength,//最多輸入數(shù)隅俘,有值后右下角就會(huì)有一個(gè)計(jì)數(shù)器
this.maxLengthEnforced = true,
this.onChanged,//輸入改變回調(diào)
this.onEditingComplete,//輸入完成時(shí)沈自,配合TextInputAction.done使用
this.onSubmitted,//提交時(shí),配合TextInputAction
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.start,
this.enableInteractiveSelection,
this.onTap,//點(diǎn)擊事件
this.buildCounter,
this.scrollPhysics,
})
InputDecoration
const InputDecoration({
this.icon,//左側(cè)外的圖標(biāo)
this.labelText,//懸浮提示徐勃,可代替hintText
this.labelStyle,//懸浮提示文字的樣式
this.helperText,//幫助文字
this.helperStyle,
this.hintText,//輸入提示
this.hintStyle,
this.hintMaxLines,
this.errorText,//錯(cuò)誤提示
this.errorStyle,
this.errorMaxLines,
this.hasFloatingPlaceholder = true,//是否顯示懸浮提示文字
this.isDense,
this.contentPadding,//內(nèi)填充
this.prefixIcon,//左側(cè)內(nèi)的圖標(biāo)
this.prefix,
this.prefixText,//左側(cè)內(nèi)的文字
this.prefixStyle,
this.suffixIcon,//右側(cè)內(nèi)圖標(biāo)
this.suffix,
this.suffixText,
this.suffixStyle,
this.counter,//自定義計(jì)數(shù)器
this.counterText,//計(jì)數(shù)文字
this.counterStyle,//計(jì)數(shù)樣式
this.filled,//是否填充
this.fillColor,//填充顏色
this.errorBorder,
this.focusedBorder,
this.focusedErrorBorder,
this.disabledBorder,
this.enabledBorder,
this.border,//邊框
this.enabled = true,
this.semanticCounterText,
this.alignLabelWithHint,
})
1.2 樣式
1.2.1 基礎(chǔ)樣式
TextField(),
style:TextStyle 可以修改文本樣式
1.2.2 隱藏文本
修改obscureText的屬性值
obscureText 設(shè)置為true時(shí),輸入的文本不可見一罩,常用的密碼類型
TextField(
obscureText: true,
),
1.2.3 鍵盤類型
keyboardType 即可輸入類型莉测,傳入TextInputType類型,比如傳入number即數(shù)字鍵盤
TextField(
keyboardType: TextInputType.number,
),
TextInputType 可選類型
TextInputType.text
TextInputType.multiline
TextInputType.phone
TextInputType.datetime
TextInputType.emailAddress
TextInputType.url
TextInputType.visiblePassword
TextInputType.name
TextInputType.streetAddress
1.2.4 鍵盤按鈕
即鍵盤右下角按鈕樣式柔袁,比如完成或者Done
TextField(
textInputAction: TextInputAction.done,
),
textInputAction 可選類型
TextInputAction.none //為不彈出鍵盤
TextInputAction.unspecified //換行
TextInputAction.done //完成或者done
TextInputAction.go //前往或者go
TextInputAction.search //搜索或者search
TextInputAction.send //發(fā)送或者send
TextInputAction.next //下一項(xiàng)或者next
TextInputAction.previous // 上一項(xiàng) IOS 不支持
TextInputAction.continueAction //繼續(xù)或者 continue
TextInputAction.join //加入或者join
TextInputAction.route //路線或者route
TextInputAction.emergencyCall //緊急電話
TextInputAction.newline //換行或者newline
1.2.5 大小寫
即控制輸入英文字母大小寫呆躲,比如單詞首字母大寫
TextField(
textCapitalization: TextCapitalization.words,
),
textCapitalization 其他可選類型
TextCapitalization.words // 單詞首字母大寫
TextCapitalization.sentences // 句子首字母大寫
TextCapitalization.characters // 所有字母大寫
textCapitalization: TextCapitalization.none // 默認(rèn)無
1.2.6 光標(biāo)
默認(rèn)是一個(gè)藍(lán)色豎線
TextField(
cursorColor: Colors.orange,
cursorWidth: 15,
cursorRadius: Radius.circular(15),
),
1.2.7 最多行數(shù)
TextField(
maxLines: 3,
),
從效果上看,TextField默認(rèn)行數(shù)變成3行捶索,如果我們想默認(rèn)顯示1行插掂,最多輸入3行,可以再加個(gè)參數(shù) minLines
TextField(
maxLines: 3,
minLines: 1,
),
TextField的高度會(huì)自適應(yīng)
1.2.8 計(jì)數(shù)器
TextField 右下角有個(gè)計(jì)數(shù),超出數(shù)量限制無法輸入
TextField(
maxLength: 8,
),
默認(rèn)效果:當(dāng)前輸入長(zhǎng)度/最大長(zhǎng)度腥例,我們可以自定義一個(gè)計(jì)數(shù)器
TextField(
maxLength: 8,
decoration: InputDecoration(
counter: Text("自定義計(jì)數(shù) 0/100"),
),
),
1.2.9 圖標(biāo)
圖標(biāo)有3種
- 左外側(cè)圖標(biāo)
TextField(
decoration: InputDecoration(
icon: Icon(Icons.person),
),
),
- 左內(nèi)側(cè)圖標(biāo)
TextField(
decoration: InputDecoration(
prefixIcon: Icon(Icons.phone_android),
),
),
- 右內(nèi)側(cè)圖標(biāo)
TextField(
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(Icons.close),
onPressed: () {
controller.clear();
},
),
),
),
在右側(cè)圖標(biāo)加了IconButton辅甥,可以點(diǎn)擊
1.2.10 提示文字
提示文字有4種
- 輸入提示文字
TextField(
controller: controller,
decoration: InputDecoration(
hintText: '請(qǐng)輸入賬號(hào)aaa',
),
),
- 懸浮提示文本
TextField(
controller: controller,
decoration: InputDecoration(
hintText: '請(qǐng)輸入賬號(hào)aaa',
labelText: '請(qǐng)輸入賬號(hào)',
),
),
可以看到默認(rèn)顯示labelText的,聚焦后顯示hintText
- 幫助提示文本
TextField(
controller: controller,
decoration: InputDecoration(
helperText: "幫助文字",
helperStyle: TextStyle(color: Colors.blue)
),
),
- 錯(cuò)誤提示文本
TextField(
controller: controller,
decoration: InputDecoration(
errorText: "你沒有輸入任何內(nèi)容",
),
),
1.2.11 去掉下劃線
TextField(
decoration: InputDecoration.collapsed(hintText: "無下劃線的輸入框"),
),
也可以decoration:null,這樣的話就沒有提示文本
1.2.12 邊框
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
),
),
可以通過borderRadius 修改圓角
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(30)),
),
),
),
1.2.13 獲取輸入內(nèi)容
有兩種方式
- onChanged
onChanged 是輸入文本發(fā)生變化時(shí)回調(diào)燎竖,返回是一個(gè)String璃弄,可以用變量記錄下
TextField(
onChanged: (text) {
print("輸入改變時(shí)" + text);
},
),
- controller
即控制器
初始化
var controller;
@override
void initState() {
super.initState();
controller = TextEditingController();
controller.addListener(() {});
}
配置給TextField
TextField(
controller: controller,
),
獲取內(nèi)容
controller.text
在事件中調(diào)用controller.text,即輸入的文本
1.2.14 關(guān)閉軟鍵盤
初始化
FocusNode userFocusNode = FocusNode();
配置
TextField(
focusNode: userFocusNode,
),
然后在需要的地方調(diào)用
userFocusNode.unfocus();
1.2.15 校驗(yàn)
RegExp 可以使用正則表達(dá)式來校驗(yàn)
String? validateMobile(String value) {
String patttern = r'(^[0-9]*$)';
RegExp regExp = new RegExp(patttern);
if (value.length == 0) {
return "手機(jī)號(hào)為空";
} else if (!regExp.hasMatch(value)) {
return "手機(jī)號(hào)格式不正確";
}
return null;
}
2构回、表單From
flutter提供一套表單校驗(yàn)框架Form夏块,可以通過Form框架一步校驗(yàn)所有表單,非常方便纤掸,比較常用的用法是Form+TextFormField
2.1 Form & TextFormField 介紹
Form
class Form extends StatefulWidget {
final Widget child;
...
const Form({
Key? key,
required this.child,
this.onWillPop,
this.onChanged,
AutovalidateMode? autovalidateMode,
})
...
Form繼承StatefulWidget脐供,有一個(gè)widget 類型的child參數(shù),證明Form是一個(gè)容器
FormState 里還有一個(gè)validate方法
bool validate() {
_hasInteractedByUser = true;
_forceRebuild();
return _validate();
}
一般通過GlobalKey來訪問Form中validate方法借跪,F(xiàn)orm的validate方法用來校驗(yàn)所有Form里的FormField表單政己,validate方法返回值是bool類型,返回true表示所有表單校驗(yàn)成功掏愁;返回false表示有校驗(yàn)失敗的表單歇由;
TextFormField
class TextFormField extends FormField<String> {
...
TextFormField({
...
FormFieldValidator<String> validator,
...
})
TextFormField繼承FormField卵牍,F(xiàn)ormField后面源碼分析會(huì)講,所有Form可統(tǒng)一校驗(yàn)的表單都必須繼承FormField沦泌,可以通過FormField自定義各種各樣可校驗(yàn)表單辽慕,TextFormField只是FormField自定義表單中的一種。
表單校驗(yàn)必須實(shí)現(xiàn)的方法為validator赦肃,定義如下:
typedef FormFieldValidator<T> = String? Function(T? value);
每個(gè)表單的校驗(yàn)規(guī)則都在validator里實(shí)現(xiàn)溅蛉,通過返回值來判斷是否校驗(yàn)成功。
返回null他宛,表示表單校驗(yàn)成功
返回非null船侧,表示表單校驗(yàn)失敗,其實(shí)返回的非null還可以用來表示校驗(yàn)失敗的錯(cuò)誤提示信息厅各,TextFormField內(nèi)部實(shí)現(xiàn)就將返回的非null當(dāng)成錯(cuò)誤信息提示出來
2.2 使用步驟
1镜撩、用Form包在所有需要校驗(yàn)的表單最外層,如下:
Form(
key:xxx,
child:xxx
2队塘、將GlobalKey傳給Form袁梗,用于調(diào)用Form里方法,如下:
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Form(
key:_formKey,
child:xxx
3憔古、將TextFormField傳給Form容器遮怜,如下:
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Form(
key:_formKey,
child:
...
TextFormField
...
4、實(shí)現(xiàn)對(duì)應(yīng)TextFormField的校驗(yàn)規(guī)則 鸿市,如下:
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
Form(
key:_formKey,
child:
...
TextFormField(
validator: (value) {
...
return xxx;
},
)
...
5锯梁、最后調(diào)用Form校驗(yàn)所有表單方法validate,如下:
_formKey.currentState.validate()
2.3 Form 校驗(yàn) 示例
class _MSHomeContentState extends State<MSHomeContent> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
hintText: "請(qǐng)輸入手機(jī)號(hào)",
),
validator: (value) {
RegExp reg = new RegExp(r'^\d{11}$');
if (!reg.hasMatch(value!)) {
return '請(qǐng)輸入11位手機(jī)號(hào)';
}
return null;
},
),
TextFormField(
decoration: InputDecoration(
hintText: "請(qǐng)輸入用戶名",
),
validator: (value) {
if (value!.isEmpty) {
return "請(qǐng)輸入用戶名";
}
return null;
},
),
SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("校驗(yàn)成功")));
// Scaffold.of(context).showSnackBar(snackbar)
}
},
child: Text("校驗(yàn)"),
),
],
),
);
}
}
2.4 Form 保存和獲取表單數(shù)據(jù) 示例
class _MSHomeContentState extends State<MSHomeContent> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String? phoneNum;
String? userName;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
hintText: "請(qǐng)輸入手機(jī)號(hào)",
),
onSaved: (value) {
phoneNum = value;
},
),
SizedBox(
height: 20,
),
TextFormField(
decoration: InputDecoration(
hintText: "請(qǐng)輸入用戶名",
),
onSaved: (value) {
userName = value;
},
),
SizedBox(
height: 20,
),
Container(
width: double.infinity,
height: 50,
padding: EdgeInsets.symmetric(horizontal: 16),
child: ElevatedButton(
onPressed: () {
// 保存和獲取表單數(shù)據(jù)
_formKey.currentState!.save();
print("userName: $userName,phoneNum:$phoneNum");
},
child: Text("保存"),
),
),
],
),
),
);
}
}
參考:
[Button]https://blog.csdn.net/qq_41619796/article/details/115658314
[Image]http://www.reibang.com/p/27394b02d4d6/
[TextFiled]https://blog.csdn.net/yechaoa/article/details/90906689
[From]http://www.reibang.com/p/b5bc338b260b