Flutter
中基礎的Widget
, 可是因爲篇幅的緣由, 這篇文章就主要介紹TextField
TextField
TextField
用於文本輸入,它提供了不少屬性,咱們先簡單介紹一下主要屬性的做用html
const TextField({
Key key,
// 編輯框的控制器,跟文本框的交互通常都經過該屬性完成,若是不建立的話默認會自動建立
this.controller,
// 用於控制`TextField`是否佔有當前鍵盤的輸入焦點, 使咱們和鍵盤交互的`handle`
this.focusNode,
// 用於控制`TextField`的外觀顯示,如提示文本、背景顏色、邊框等
this.decoration = const InputDecoration(),
// 鍵盤類型
TextInputType keyboardType,
// 決定鍵盤右下角按鈕顯示的內容
this.textInputAction,
// 設置什麼狀況下使用大寫字母, 默認不使用大寫字母
this.textCapitalization = TextCapitalization.none,
// 正在編輯的文本樣式, `TextStyle`
this.style,
// 輸入框文本的對其方式
this.textAlign = TextAlign.start,
// 輸入框文本的其實位置
this.textDirection,
// 是否自動獲取焦點, 默認`false`
this.autofocus = false,
// 是否隱藏正在編輯的文本,如用於輸入密碼的場景等,文本內容會用「•」替換, 默認`false`
this.obscureText = false,
// 是否自動校驗, 默認`false`
this.autocorrect = true,
// 輸入框能輸入的最大行數
this.maxLines = 1,
// 輸入框能輸入的最多字符個數
this.maxLength,
// 達到最大長度(`maxLength`)時是否阻止輸入, 默認`true`: 不能繼續輸入, `false`能夠繼續輸入
this.maxLengthEnforced = true,
// 輸入文本發生變化時的回調
this.onChanged,
// 點擊鍵盤完成按鈕時觸發的回調,該回調沒有參數,(){}
this.onEditingComplete,
// 點擊鍵盤完成按鈕時觸發的回調,該回調有參數,參數即爲當前輸入框中的值。(String){}
this.onSubmitted,
// 對輸入文本的校驗
this.inputFormatters,
// 輸入框是否可用, `false`則輸入框會被禁用
this.enabled,
// 光標的寬度
this.cursorWidth = 2.0,
// 光標的圓角
this.cursorRadius,
// 光標的顏色
this.cursorColor,
// 鍵盤的外觀, Brightness.light和dark
this.keyboardAppearance,
// 當TextField滾動時, 設置文本字段在滾動後的位置與可滾動項的邊緣的距離
this.scrollPadding = const EdgeInsets.all(20.0),
// 長按輸入的文本, 設置是否顯示剪切,複製,粘貼按鈕, 默認是顯示的
this.enableInteractiveSelection = true,
// 點擊輸入框時的回調(){}
this.onTap,
})
複製代碼
controller
來與文本框交互controller
,則TextField
內部會自動建立一個TextField
的取值和賦值的操做class TextFieldWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return ControllerText();
}
}
class ControllerText extends State<TextFieldWidget> {
TextEditingController _textController = TextEditingController();
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
width: 414.0,
height: 600.0,
color: Colors.white12,
child: Column(
children: <Widget>[
TextField(
controller: _textController,
decoration: InputDecoration(icon: Icon(Icons.phone_iphone), hintText: 'hintText'),
),
RaisedButton(
child: Text('賦值'),
onPressed: (){
setState(() {
_textController.text = "https://www.titanjun.top";
});
},
),
RaisedButton(
child: Text('取值'),
onPressed: (){
setState(() {});
},
),
Text(_textController.text)
],
),
);
}
}
複製代碼
用於控制TextField
是否佔有當前鍵盤的輸入焦點, 使咱們和鍵盤交互的handle
git
FocusNode focusNode1 = new FocusNode();
TextField(
autofocus: true,
focusNode: focusNode1,//關聯focusNode1
decoration: InputDecoration(
labelText: "input1"
),
),
RaisedButton(
child: Text("隱藏鍵盤"),
onPressed: () {
// 當全部編輯框都失去焦點時鍵盤就會收起
focusNode1.unfocus();
},
),
複製代碼
用於控制TextField
的外觀顯示,如提示文本、背景顏色、邊框等, 下面是InputDecoration
的構造方法github
const InputDecoration({
// 接收Widget, 在輸入框左側顯示的圖片
this.icon,
// String, 輸入框的描述, 當輸入框獲取焦點時默認會浮動到上方
this.labelText,
// TextStyle, 樣式
this.labelStyle,
// 輔助文本, 位於輸入框下方,若是errorText不爲空的話,則helperText不顯示
this.helperText,
this.helperStyle,
/// 提示文本,位於輸入框內部
this.hintText,
this.hintStyle,
// 錯誤信息提示文本
this.errorText,
this.errorStyle,
// errorText顯示的最大行數
this.errorMaxLines,
// errorText不爲空,輸入框沒有焦點時要顯示的邊框
this.errorBorder,
// labelText是否浮動,默認爲true,修改成false則labelText在輸入框獲取焦點時不會浮動且不顯示
this.hasFloatingPlaceholder = true,
// 改變輸入框是否爲密集型,默認爲false,修改成true時,圖標及間距會變小
this.isDense,
// 內間距
this.contentPadding,
// 位於輸入框內部起左側置的圖標
this.prefixIcon,
// 預先填充在輸入框左側的Widget,跟prefixText同時只能出現一個
this.prefix,
//預填充在輸入框左側的文本, 不可修改刪除,例如手機號前面預先加上區號等
this.prefixText,
this.prefixStyle,
// 位於輸入框內部右側位置的圖標
this.suffixIcon,
// 預先填充在輸入框右側的Widget,跟suffixText同時只能出現一個
this.suffix,
// 預填充在輸入框右側的文本, 不可修改刪除
this.suffixText,
this.suffixStyle,
// 位於右下方顯示的文本,經常使用於顯示輸入的字符數量
this.counterText,
this.counterStyle,
// 至關於輸入框的背景顏色
this.fillColor,
// 若是爲true,則輸入使用fillColor指定的顏色填充
this.filled,
// 輸入框有焦點時的邊框,若是errorText不爲空的話,該屬性無效
this.focusedBorder,
// errorText不爲空時,輸入框有焦點時的邊框
this.focusedErrorBorder,
// 輸入框禁用時顯示的邊框,若是errorText不爲空的話,該屬性無效
this.disabledBorder,
// 輸入框可用時顯示的邊框,若是errorText不爲空的話,該屬性無效
this.enabledBorder,
// 正常狀況下的邊框
this.border,
// 輸入框是否可用
this.enabled = true,
// counterText的語義標籤, 若是賦值將替換counterText, 可是我試了好像沒什麼效果
this.semanticCounterText,
})
複製代碼
用於設置該輸入框默認的鍵盤輸入類型,取值以下:api
keyboardType: TextInputType.number,
複製代碼
TextInputType |
含義 |
---|---|
text |
文本輸入鍵盤 |
multiline |
多行文本,需和maxLines 配合使用(設爲null 或大於1) |
number |
純數字鍵盤 |
phone |
電話號碼輸入鍵盤會彈出數字鍵盤並顯示* # |
datetime |
日期輸入鍵盤, Android 上會顯示: - |
emailAddress |
電子郵件地址,會顯示@ . |
url |
鏈接輸入鍵盤, 會顯示/ . |
決定鍵盤右下角按鈕顯示的內容, TextInputAction
枚舉值bash
textInputAction |
樣式 |
---|---|
none |
不支持iOS |
unspecified |
顯示return |
done |
顯示Done |
go |
顯示Go |
search |
顯示Search |
send |
顯示Send |
next |
顯示Next |
previous |
不支持iOS |
continueAction |
顯示Continue |
join |
顯示Join |
route |
顯示Route |
emergencyCall |
顯示Emergency Call |
newline
服務器
設置什麼狀態下使用大寫字母鍵盤TextCapitalization
枚舉值微信
enum TextCapitalization {
// 每一個單詞的第一個字母使用大寫字母
words,
// 默認爲每一個句子的第一個字母使用大寫鍵盤。
sentences,
// 每一個字符默認使用大寫鍵盤
characters,
/// 不使用大寫字母鍵盤
none,
}
複製代碼
輸入框內文本在水平方向的對齊方式markdown
// 默認值
this.textAlign = TextAlign.start
// 全部枚舉值
left: 左對齊
right: 右對齊
center: 居中
start: 起始位置, 和textDirection有關
end: 終點位置, 和textDirection有關
justify: 文本的拉伸行,以軟換行符結束,以填充容器的寬度
複製代碼
決定文本是從右向左對其仍是從左向右對齊iphone
enum TextDirection {
rtl,
ltr,
}
複製代碼
TextInputFormatter
類型的集合TextInputFormatter
是一個抽象類, 官方給咱們提供了他的三個子類,分別是
WhitelistingTextInputFormatter
: 白名單校驗,也就是隻容許輸入符合規則的字符BlacklistingTextInputFormatter
: 黑名單校驗,除了規定的字符其餘的均可以輸入LengthLimitingTextInputFormatter
: 長度限制,跟maxLength做用相似// 白名單校驗
WhitelistingTextInputFormatter(this.whitelistedPattern)
// 黑名單校驗
BlacklistingTextInputFormatter(
this.blacklistedPattern, {
// 當輸入禁止輸入的字符時候, 會被替換成設置的replacementString字符
this.replacementString = '',
})
// 長度校驗
LengthLimitingTextInputFormatter(this.maxLength)
// whitelistedPattern和blacklistedPattern都是Pattern類型的,
abstract class RegExp implements Pattern {
external factory RegExp(String source,
{bool multiLine: false, bool caseSensitive: true});
}
複製代碼
使用介紹ide
// 白名單
inputFormatters: [
// 只能輸入數字
WhitelistingTextInputFormatter.digitsOnly,
// 是能輸入小寫字母
WhitelistingTextInputFormatter(RegExp("[a-z]"))
],
// 黑名單
inputFormatters: [
// 不能輸入回車符
BlacklistingTextInputFormatter.singleLineFormatter,
// 不能輸入小寫字母
BlacklistingTextInputFormatter(RegExp("[a-z]"), replacementString: '-')
],
// 字符限制
[LengthLimitingTextInputFormatter(10)]
// 也但是三種或兩種一塊兒使用一塊兒使用
inputFormatters: [
// 不能輸入小寫字母
BlacklistingTextInputFormatter(RegExp("[a-z]")),
// 限制輸入10個字符
LengthLimitingTextInputFormatter(10)
],
複製代碼
設置輸入框光標的樣式
// 光標的寬度
this.cursorWidth = 2.0,
// 光標的圓角
this.cursorRadius,
// 光標的顏色
this.cursorColor,
// 示例以下
cursorWidth: 10,
cursorColor: Colors.cyan,
cursorRadius: Radius.circular(5),
複製代碼
長按輸入的文本, 設置是否顯示剪切,複製,粘貼按鈕, 默認是顯示的
// 默認值
this.enableInteractiveSelection = true,
複製代碼
// 輸入文本發生變化時的回調,參數即爲輸入框中的值
onChanged: (val) {
print(val);
},
// 點擊鍵盤的動做按鈕時的回調,沒有參數
onEditingComplete: (){
print("點擊了鍵盤上的動做按鈕");
},
// 點擊鍵盤的動做按鈕時的回調,參數爲當前輸入框中的值
onSubmitted: (val){
print("點擊了鍵盤上的動做按鈕,當前輸入框的值爲:${val}");
},
// 點擊輸入框時的回調(){}, 沒有參數
onTap: (){
print('點擊輸入框');
},
複製代碼
TextField
都分別進行校驗將會是一件很麻煩的事Flutter
提供了一個表單Form
,它能夠對輸入框進行分組,而後進行一些統一操做,如輸入內容校驗、輸入框重置以及輸入內容保存。Form
繼承自StatefulWidget
對象,它對應的狀態類爲FormState
// Form類的定義
const Form({
Key key,
@required this.child,
// 是否自動校驗輸入內容;當爲true時,每個子FormField內容發生變化時都會自動校驗合法性,並直接顯示錯誤信息。不然,須要經過調用FormState.validate()來手動校驗
this.autovalidate = false,
// 決定Form所在的路由是否能夠直接返回(如點擊返回按鈕),該回調返回一個Future對象,若是Future的最終結果是false,則當前路由不會返回;若是爲true,則會返回到上一個路由。此屬性一般用於攔截返回按鈕
this.onWillPop,
// Form的任意一個子FormField內容發生變化時會觸發此回調
this.onChanged,
})
複製代碼
Form
的子元素必須是FormField
類型,FormField
是一個抽象類,FormState
內部經過定義的屬性來完成操做,FormField
部分定義以下:
const FormField({
Key key,
@required this.builder,
// 保存回調
this.onSaved,
// 驗證回調
this.validator,
// 初始值
this.initialValue,
// 是否自動校驗。
this.autovalidate = false,
this.enabled = true,
})
複製代碼
爲了方便使用,Flutter
提供了一個TextFormField
,它繼承自FormField
類,也是TextField
的一個包裝類,因此除了FormField
定義的屬性以外,它還包括TextField
的屬性。
class TextFormField extends FormField<String> {
TextFormField({
Key key,
this.controller,
String initialValue,
FocusNode focusNode,
InputDecoration decoration = const InputDecoration(),
TextInputType keyboardType,
TextCapitalization textCapitalization = TextCapitalization.none,
TextInputAction textInputAction,
TextStyle style,
TextDirection textDirection,
TextAlign textAlign = TextAlign.start,
bool autofocus = false,
bool obscureText = false,
bool autocorrect = true,
bool autovalidate = false,
bool maxLengthEnforced = true,
int maxLines = 1,
int maxLength,
VoidCallback onEditingComplete,
ValueChanged<String> onFieldSubmitted,
FormFieldSetter<String> onSaved,
FormFieldValidator<String> validator,
List<TextInputFormatter> inputFormatters,
bool enabled = true,
Brightness keyboardAppearance,
EdgeInsets scrollPadding = const EdgeInsets.all(20.0),
bool enableInteractiveSelection = true,
})
}
複製代碼
FormState
爲Form
的State
類,能夠經過Form.of()
或GlobalKey
得到。Form
的子元素FormField
進行統一操做// 調用此方法後,會調用Form子元素FormField的save回調,用於保存表單內容
void save() {
for (FormFieldState<dynamic> field in _fields)
field.save();
}
/// 調用此方法後,會將子元素FormField的內容清空。
void reset() {
for (FormFieldState<dynamic> field in _fields)
field.reset();
_fieldDidChange();
}
/// 調用此方法後,會調用Form子元素FormField的validate回調,若是有一個校驗失敗,則返回false,全部校驗失敗項都會返回用戶返回的錯誤提示。
bool validate() {
_forceRebuild();
return _validate();
}
複製代碼
用戶登陸示例, 在提交以前校驗:
class TextStateWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return TextWidget();
}
}
class TextWidget extends State<TextStateWidget> {
TextEditingController _nameController = TextEditingController();
TextEditingController _psdController = TextEditingController();
GlobalKey _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 30),
child: Form(
key: _formKey,
autovalidate: true,
child: Column(
children: <Widget>[
TextFormField(
autofocus: true,
controller: _nameController,
decoration: InputDecoration(
labelText: '用戶名',
hintText: '用戶名或密碼',
icon: Icon(Icons.person)
),
validator: (value) {// 校驗用戶名
return value.trim().length > 0 ? null : '用戶名不能爲空';
},
),
TextFormField(
controller: _psdController,
obscureText: true,
decoration: InputDecoration(
labelText: '密碼',
hintText: '登陸密碼',
icon: Icon(Icons.lock)
),
validator: (psd) {
return psd.trim().length > 5 ? null : '密碼不能少於6位';
},
),
Padding(
padding: EdgeInsets.only(top: 30),
child: Row(
children: <Widget>[
Expanded(
child: RaisedButton(
padding: EdgeInsets.all(15),
child: Text('登陸'),
color: Theme.of(context).primaryColor,
textColor: Colors.white,
onPressed: () {
// 反正這裏我是沒看懂, 後面再慢慢學習吧
if((_formKey.currentState as FormState).validate()){
//驗證經過提交數據
}
},
),
)
],
),
)
],
),
),
);
}
}
複製代碼
好了, 到這裏
TextField
相關的知識已經介紹完了, 下一篇應該就是介紹容器類Widget
了, 拭目以待吧
歡迎您掃一掃下面的微信公衆號,訂閱個人博客!