文本框TextField
屬性列表
TextEditingController controller,
FocusNode focusNode,
InputDecoration decoration = const InputDecoration(),
TextInputType keyboardType,
TextInputAction textInputAction,
TextStyle style,
TextAlign textAlign = TextAlign.start,
bool autofocus = false,
bool obscureText = false,
int maxLines = 1,
int maxLength,
bool maxLengthEnforced = true,
ValueChanged<String> onChanged,
VoidCallback onEditingComplete,
ValueChanged<String> onSubmitted,
List<TextInputFormatter> inputFormatters,
bool enabled,
this.cursorWidth = 2.0,
this.cursorRadius,
this.cursorColor,
屬性講解
`controller` :編輯框的控制器登失,通過(guò)它可以設(shè)置/獲取編輯框的內(nèi)容、選擇編輯內(nèi)容挖炬、監(jiān)聽(tīng)編輯文本改變事件揽浙。大多數(shù)情況下我們都需要顯式提供一個(gè)controller來(lái)與文本框交互。如果沒(méi)有提供controller意敛,則TextField內(nèi)部會(huì)自動(dòng)創(chuàng)建一個(gè)馅巷。
`focusNode`:用于控制TextField是否占有當(dāng)前鍵盤(pán)的輸入焦點(diǎn)。它是我們和鍵盤(pán)交互的一個(gè)handle草姻。
`InputDecoration`:用于控制TextField的外觀顯示钓猬,如提示文本、背景顏色撩独、邊框等敞曹。
`keyboardType`:用于設(shè)置該輸入框默認(rèn)的鍵盤(pán)輸入類(lèi)型,取值如下:
| TextInputType枚舉值 | 含義 | | ----- | -------- | | text | 文本輸入鍵盤(pán) | |
multiline | 多行文本综膀,需和maxLines配合使用(設(shè)為null或大于1) | | number
| 數(shù)字澳迫;會(huì)彈出數(shù)字鍵盤(pán) | | phone | 優(yōu)化后的電話號(hào)碼輸入鍵盤(pán);會(huì)彈出數(shù)
字鍵盤(pán)并顯示"* #" | | datetime | 優(yōu)化后的日期輸入鍵盤(pán)剧劝;Android上會(huì)顯
示“: -” | | emailAddress | 優(yōu)化后的電子郵件地址橄登;會(huì)顯示“@ .” | | url | 優(yōu)化
后的url輸入鍵盤(pán); 會(huì)顯示“/ .” |
`textInputAction` :鍵盤(pán)動(dòng)作按鈕圖標(biāo)(即回車(chē)鍵位圖標(biāo))担平,它是一個(gè)枚舉值示绊,有多個(gè)可選值,全部的取值列表讀者可以查看API文檔暂论,下面是當(dāng)值為T(mén)extInputAction.search時(shí),鍵盤(pán)右下角有搜索拌禾,前往等設(shè)置取胎。
`style`:正在編輯的文本樣式。
`textAlign`: 輸入框內(nèi)編輯文本在水平方向的對(duì)齊方式湃窍。
`autofocus`: 是否自動(dòng)獲取焦點(diǎn)闻蛀。
`obscureText`:是否隱藏正在編輯的文本,如用于輸入密碼的場(chǎng)景等您市,文本內(nèi)容會(huì)用“?”替換觉痛。
`maxLines`:輸入框的最大行數(shù),默認(rèn)為1茵休;如果為null薪棒,則無(wú)行數(shù)限制手蝎。
`maxLength`和`maxLengthEnforced` :maxLength代表輸入框文本的最大長(zhǎng)度,設(shè)置后輸入框右下角會(huì)顯示輸入的文本計(jì)數(shù)俐芯。maxLengthEnforced決定當(dāng)輸入文本長(zhǎng)度超過(guò)maxLength時(shí)是否阻止輸入棵介,為true時(shí)會(huì)阻止輸入,為false時(shí)不會(huì)阻止輸入但輸入框會(huì)變紅吧史。
`onChange`:輸入框內(nèi)容改變時(shí)的回調(diào)函數(shù)邮辽;注:內(nèi)容改變事件也可以通過(guò)controller來(lái)監(jiān)聽(tīng)。
`onEditingComplete`和`onSubmitted`:這兩個(gè)回調(diào)都是在輸入框輸入完成時(shí)觸發(fā)贸营,比如按了鍵盤(pán)的完成鍵(對(duì)號(hào)圖標(biāo))或搜索鍵(??圖標(biāo))吨述。不同的是兩個(gè)回調(diào)簽名不同,onSubmitted回調(diào)是ValueChanged<String>類(lèi)型钞脂,它接收當(dāng)前輸入內(nèi)容做為參數(shù)锐极,而onEditingComplete不接收參數(shù)。
`inputFormatters`:用于指定輸入格式芳肌;當(dāng)用戶輸入內(nèi)容改變時(shí)灵再,會(huì)根據(jù)指定的格式來(lái)校驗(yàn)。
`enable`:如果為false亿笤,則輸入框會(huì)被禁用翎迁,禁用狀態(tài)不接收輸入和事件,同時(shí)顯示禁用態(tài)樣式(在其decoration中定義)净薛。
`cursorWidth`汪榔、`cursorRadius`和`cursorColor`:這三個(gè)屬性是用于自定義輸入框光標(biāo)寬度、圓角和顏色的肃拜。
外觀設(shè)置
TextField(
controller: controller,
decoration: InputDecoration(
labelText: "密碼", ## labelText設(shè)置標(biāo)簽文字痴腌,這個(gè)標(biāo)簽在沒(méi)有輸入的時(shí)候是占滿輸入框的,當(dāng)輸入聚焦以后燃领,就會(huì)縮小到輸入框左上角:
hintText: "您的登錄密碼", ##placeholder
prefixIcon: Icon(Icons.lock) ## 前面的icon
fillColor: Colors.blue.shade100, ##填充顏色
filled: true, ## 充滿
errorText: 'error' ## 錯(cuò)誤提示
helperText: 'help', ##提示文本
suffixText: 'airport', ##后綴
// 邊框設(shè)置
// border: InputBorder.none //隱藏下劃線
contentPadding: EdgeInsets.all(10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.0),
borderSide: BorderSide(color: Colors.red, width: 3.0, style:
BorderStyle.solid)//沒(méi)什么卵效果
)),
),
maxLength: 30,//最大長(zhǎng)度士聪,設(shè)置此項(xiàng)會(huì)讓TextField右下角有一個(gè)輸入數(shù)量的統(tǒng)計(jì)字符串
maxLines: 1,//最大行數(shù)
autocorrect: true,//是否自動(dòng)更正
autofocus: true,//是否自動(dòng)對(duì)焦
obscureText: true,//是否是密碼
textAlign: TextAlign.center,//文本對(duì)齊方式
style: TextStyle(fontSize: 30.0, color: Colors.blue),//輸入文本的樣式
inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],//允許的輸入格式
enabled: true,//不禁用
);
監(jiān)聽(tīng)字符變化,設(shè)置默認(rèn)字符
要監(jiān)聽(tīng)就要有監(jiān)聽(tīng)控制器 TextEditingController()
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class TextFieldPage extends StatelessWidget {
Widget buildTextField(TextEditingController controller) {
return TextField(
controller: controller,
maxLength: 30,//最大長(zhǎng)度猛蔽,設(shè)置此項(xiàng)會(huì)讓TextField右下角有一個(gè)輸入數(shù)量的統(tǒng)計(jì)字符串
maxLines: 1,//最大行數(shù)
autocorrect: true,//是否自動(dòng)更正
autofocus: true,//是否自動(dòng)對(duì)焦
obscureText: true,//是否是密碼
textAlign: TextAlign.center,//文本對(duì)齊方式
style: TextStyle(fontSize: 30.0, color: Colors.blue),//輸入文本的樣式
inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],//允許的輸入格式
onChanged: (text) {//內(nèi)容改變的回調(diào)
print('change $text');
},
onSubmitted: (text) {//內(nèi)容提交(按回車(chē))的回調(diào)
print('submit $text');
},
enabled: true,//是否禁用
);
}
@override
Widget build(BuildContext context) {
final controller = TextEditingController();
controller.text="hello world!"; ## 設(shè)置默認(rèn)值
controller.selection=TextSelection(
baseOffset: 2, ###并從第三個(gè)字符開(kāi)始選中后面的字符
extentOffset: controller.text.length
);
controller.addListener(() { ## 監(jiān)聽(tīng)
print('input ${controller.text}');
});
return Scaffold(
appBar: AppBar(
title: Text('TextField'),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: buildTextField(controller),
),
);
}
}
鍵盤(pán)相關(guān)
FocusNode和FocusScopeNode兩個(gè)屬性控制
class FocusTestRoute extends StatefulWidget {
@override
_FocusTestRouteState createState() => new _FocusTestRouteState();
}
class _FocusTestRouteState extends State<FocusTestRoute> {
FocusNode focusNode1 = new FocusNode(); ## 初始化對(duì)象
FocusNode focusNode2 = new FocusNode(); ## 初始化對(duì)象
FocusScopeNode focusScopeNode;
// 監(jiān)聽(tīng)焦點(diǎn)變化
focusNode.addListener((){
print(focusNode.hasFocus);
});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
TextField(
autofocus: true,
focusNode: focusNode1, //關(guān)聯(lián)focusNode1
decoration: InputDecoration(
labelText: "input1"
),
),
TextField(
focusNode: focusNode2, //關(guān)聯(lián)focusNode2
decoration: InputDecoration(
labelText: "input2"
),
),
Builder(builder: (ctx) {
return Column(
children: <Widget>[
RaisedButton(
child: Text("移動(dòng)焦點(diǎn)"),
onPressed: () {
//將焦點(diǎn)從第一個(gè)TextField移到第二個(gè)TextField
// 這是一種寫(xiě)法 FocusScope.of(context).requestFocus(focusNode2);
// 這是第二種寫(xiě)法
if(null == focusScopeNode){
focusScopeNode = FocusScope.of(context); ##初始化焦點(diǎn)第一個(gè)剥悟,從全文按順序查找
}
focusScopeNode.requestFocus(focusNode2); ##移動(dòng)焦點(diǎn)到第二個(gè)
},
),
RaisedButton(
child: Text("隱藏鍵盤(pán)"),
onPressed: () {
// 當(dāng)所有編輯框都失去焦點(diǎn)時(shí)鍵盤(pán)就會(huì)收起
focusNode1.unfocus(); ### 取消焦點(diǎn)操作
focusNode2.unfocus(); ### 取消焦點(diǎn)操作
},
),
],
);
},
),
],
),
);
}
}
From
對(duì)一組文本進(jìn)行相同的校驗(yàn)
Form 的子空間必須是FormField(和textfild基本一樣)
Form屬性
Form({
@required Widget child,
bool autovalidate = false, ##是否自動(dòng)校驗(yàn)輸入內(nèi)容
WillPopCallback onWillPop, ##攔截返回按鈕
VoidCallback onChanged, ##Form的任意一個(gè)子FormField內(nèi)容發(fā)生變化時(shí)會(huì)觸發(fā)此回調(diào)
})
FormField
const FormField({
...
FormFieldSetter<T> onSaved, //保存回調(diào)
FormFieldValidator<T> validator, //驗(yàn)證回調(diào)
T initialValue, //初始值
bool autovalidate = false, //是否自動(dòng)校驗(yàn)。
})
FormState
FormState為Form的State類(lèi)曼库,可以通過(guò)Form.of()或GlobalKey獲得区岗。我們可以通過(guò)它來(lái)對(duì)Form的子孫FormField進(jìn)行統(tǒng)一操作。我們看看其常用的三個(gè)方法:
FormState.validate():調(diào)用此方法后毁枯,會(huì)調(diào)用Form子孫FormField的validate回調(diào)慈缔,如果有一個(gè)校驗(yàn)失敗,則返回false种玛,所有校驗(yàn)失敗項(xiàng)都會(huì)返回用戶返回的錯(cuò)誤提示藐鹤。
FormState.save():調(diào)用此方法后瓤檐,會(huì)調(diào)用Form子孫FormField的save回調(diào),用于保存表單內(nèi)容
FormState.reset():調(diào)用此方法后教藻,會(huì)將子孫FormField的內(nèi)容清空距帅。
例子
class FormTestRoute extends StatefulWidget {
@override
_FormTestRouteState createState() => new _FormTestRouteState();
}
class _FormTestRouteState extends State<FormTestRoute> {
TextEditingController _unameController = new TextEditingController();
TextEditingController _pwdController = new TextEditingController();
GlobalKey _formKey= new GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:Text("Form Test"),
),
body: Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 24.0),
child: Form(
key: _formKey, //設(shè)置globalKey,用于后面獲取FormState
autovalidate: true, //開(kāi)啟自動(dòng)校驗(yàn)
child: Column(
children: <Widget>[
TextFormField(
autofocus: true,
controller: _unameController,
decoration: InputDecoration(
labelText: "用戶名",
hintText: "用戶名或郵箱",
icon: Icon(Icons.person)
),
// 校驗(yàn)用戶名
validator: (v) {
return v
.trim()
.length > 0 ? null : "用戶名不能為空";
}
),
TextFormField(
controller: _pwdController,
decoration: InputDecoration(
labelText: "密碼",
hintText: "您的登錄密碼",
icon: Icon(Icons.lock)
),
obscureText: true,
//校驗(yàn)密碼
validator: (v) {
return v
.trim()
.length > 5 ? null : "密碼不能少于6位";
}
),
// 登錄按鈕
Padding(
padding: const EdgeInsets.only(top: 28.0),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
padding: EdgeInsets.all(15.0),
child: Text("登錄"),
color: Theme
.of(context)
.primaryColor,
textColor: Colors.white,
onPressed: () {
//在這里不能通過(guò)此方式獲取FormState括堤,context不對(duì)
//print(Form.of(context));
// 通過(guò)_formKey.currentState 獲取FormState后碌秸,
// 調(diào)用validate()方法校驗(yàn)用戶名密碼是否合法,校驗(yàn)
// 通過(guò)后再提交數(shù)據(jù)悄窃。
if((_formKey.currentState as FormState).validate()){
//驗(yàn)證通過(guò)提交數(shù)據(jù)
}
},
),
),
],
),
)
],
),
),
),
);
}
}