3.7 输入框和表单
输入框有TextField
、带有iOS
风格的CupertinoTextField
,还有表单form
.
3.7.1 TextField
TextField
默认带有下划线,无边框的,属性InputDecoration
可以设置默认文字,当编辑状态,文字已动画形式上浮至左上角,这是其他输入框所没有的。其他的看下属性:
const TextField({
...
this.controller,
this.focusNode,
this.decoration = const InputDecoration(),
TextInputType keyboardType,
this.textInputAction,
this.style,
this.textAlign = TextAlign.start,
this.textAlignVertical,
this.textDirection,
this.showCursor,
this.autofocus = false,
this.obscureText = false,
this.enableSuggestions = true,
this.maxLines = 1,
this.minLines,
this.expands = false,
this.maxLength,
this.onChanged,
this.onEditingComplete,
this.onSubmitted,
this.inputFormatters,
this.enabled,
this.cursorWidth = 2.0,
this.cursorRadius,
this.cursorColor,
...
})
controller
可以获取文字和设置文字,focusNode
获取焦点keyboardType
键盘类型textInputAction
输入键盘右下角的键onChanged
当textField
的value
变化回调函数onSubmitted
提交按键obscureText
true
则显示原点,否则显示原文字cursorWidth
光标宽度cursorRadius
光标圆圈半径cursorColor
光标颜色
textInputAction
有多个值,具体见下表格:
textInputAction | 备注 |
---|---|
none |
Android 是IME_ACTION_NONE ,iOS 没有 |
unspecified |
Android's IME_ACTION_UNSPECIFIED ,iOS 是return |
done |
Android's IME_ACTION_DONE iOS 是done |
go |
android and iOS 都是go |
search |
android and ios is Search |
send |
android and ios is send |
next |
android and ios is next |
previous |
iOS 没有,Android's IME_ACTION_PREVIOUS |
continueAction |
Android 没有,iOS 上是contion |
join |
android and ios is join |
route |
android 没有,ios is route |
emergencyCall |
android 没有,ios is Emergency Call |
newline |
android and ios 都没有,只是方便开发人员调试 |
例子:
_focusNode = new FocusNode();
_editingController = new TextEditingController();
_field = TextField(
focusNode: _focusNode,
onChanged: (v) {
setState(() {});
},
onSubmitted: (v) {
_focusNode.unfocus();
},
controller: _editingController,
obscureText: false, //是否是密码
decoration: InputDecoration(hintText: '手机号', labelText: '手机号'),
keyboardType: TextInputType.number,
);
Column(
children: <Widget>[
Text('TextField'),
_field,
Text(_editingController.value.text),
],
)
效果如下:
iOS-style
的组件CupertinoTextField
,属性和TextField
基本一致;
例子:
_editingController2 = new TextEditingController();
_focusNode2 = new FocusNode();
_cupertinoTextField = CupertinoTextField(
focusNode: _focusNode2,
controller: _editingController2,
placeholder: '密码',
prefix: Icon(Icons.lock),
textInputAction: TextInputAction.go,
obscureText: true,
);
Column(
children: <Widget>[
SizedBox(
height: 30,
),
Text('CupertinoTextField'),
_cupertinoTextField,
],
)
效果:
监听文本变化
_editingController = new TextEditingController()
..addListener(() {
print("${_editingController.value.text}");
});
或者
TextField(
focusNode: _focusNode,
onChanged: (v) {
print('onChange$v');
},
controller: _editingController,
...
);
收键盘
TextField(
focusNode: _focusNode,
);
/// 收键盘
_focusNode.unfocus();
收键盘之前必须在初始化的时候赋值给TextField
,另外官方还提供了编辑下一个textField
,当下边没有可以提供编辑的textField
则进行书键盘操作,有的话则跳至下一个textField
.
_focusNode.focusInDirection(TraversalDirection.down);
3.7.2 Form
Form
更新数据和获取数据需要使用_globalKey
获取当前的State
。
例子:
Form(
key: _globalKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter your email',
),
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: RaisedButton(
onPressed: () {
// Validate will return true if the form is valid, or false if
// the form is invalid.
if (_globalKey.currentState.validate()) {
// Process data.
}
},
child: Text('Submit'),
),
),
],
),
)
Form
子树中可以是多个TextFormField
,每个可以单个校验,所有的都校验过了,FormState
才是校验通过的,多用于多输入校验。那么我们写一个登陆的简单校验。
例子:
_form = Form(
key: _globalKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
decoration: const InputDecoration(
hintText: 'Enter your email', icon: Icon(Icons.mail)),
validator: (value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
TextFormField(
controller: _editingController3,
decoration: InputDecoration(
labelText: "密码", hintText: "您的登录密码", icon: Icon(Icons.lock)),
obscureText: true,
//校验密码
validator: (v) {
return v.trim().length > 5 ? null : "密码不能少于6位";
}),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: RaisedButton(
onPressed: () {
// Validate will return true if the form is valid, or false if
// the form is invalid.
if (_globalKey.currentState.validate()) {
// Process data.
print('校验通过');
}
setState(() {
_done = _globalKey.currentState.validate();
});
},
child: Text('Submit'),
),
),
],
),
);