1.属性
const TextField({
Key key,
TextEditingController controller, //编辑框的控制器,通过它可以设置/获取编辑框的内容、选择编辑内容、监听编辑文本改变事件。大多数情况下我们都需要显式提供一个controller来与文本框交互。如果没有提供controller,则TextField内部会自动创建一个
FocusNode focusNode, // 用于控制TextField是否占有当前键盘的输入焦点。它是我们和键盘交互的一个handle
InputDecoration decoration: const InputDecoration(), //于控制TextField的外观显示,如提示文本、背景颜色、边框
TextInputType keyboardType, // 用于设置该输入框默认的键盘输入类型,取值如下:
| TextInputType枚举值 | 含义 | | ------------------- | --------------------------------------------------- | | text | 文本输入键盘 | | multiline | 多行文本,需和maxLines配合使用(设为null或大于1) | | number | 数字;会弹出数字键盘 | | phone | 优化后的电话号码输入键盘;会弹出数字键盘并显示"* #" | | datetime | 优化后的日期输入键盘;Android上会显示“: -” | | emailAddress | 优化后的电子邮件地址;会显示“@ .” | | url | 优化后的url输入键盘; 会显示“/ .” |
TextInputAction textInputAction, // 键盘动作按钮图标(即回车键位图标),它是一个枚举值,有多个可选值
TextCapitalization textCapitalization: TextCapitalization.none,
TextStyle style, //正在编辑的文本样式
TextAlign textAlign: TextAlign.start, //输入框内编辑文本在水平方向的对齐方式
bool autofocus: false, //是否自动获取焦点
bool obscureText: false, //是否隐藏正在编辑的文本,如用于输入密码的场景等,文本内容会用“•”替换
bool autocorrect: true,
int maxLines: 1, //输入框的最大行数,默认为1;如果为null,则无行数限制
int maxLength, // maxLength代表输入框文本的最大长度,设置后输入框右下角会显示输入的文本计数
bool maxLengthEnforced: true, // maxLengthEnforced决定当输入文本长度超过maxLength时是否阻止输入,为true时会阻止输入,为false时不会阻止输入但输入框会变红
ValueChanged<String> onChanged, // 输入框内容改变时的回调函数
VoidCallback onEditingComplete, //输入框输入完成时触发,接收当前输入内容做为参数
ValueChanged<String> onSubmitted, //输入框输入完成时触发,无参数
List<TextInputFormatter> inputFormatters, //用于指定输入格式;当用户输入内容改变时,会根据指定的格式来校验
bool enabled, //如果为false,则输入框会被禁用,禁用状态不接收输入和事件,同时显示禁用态样式
//自定义输入框光标宽度、圆角和颜色
double cursorWidth: 2.0,
Radius cursorRadius,
Color cursorColor,
Brightness keyboardAppearance,
EdgeInsets scrollPadding: const EdgeInsets.all(20.0)
})
2.用户名密码输入框
import 'package:flutter/material.dart';
class MyInput extends StatelessWidget{
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("TextField"),),
body: Column(children: <Widget>[
//用户名
TextField(
autofocus: true,
decoration: InputDecoration(
labelText: "用户名",
hintText: "请输入用户名和密码",
hintStyle: TextStyle(fontSize: 12.0,color: Colors.grey),
labelStyle: TextStyle(
color: Colors.blueGrey,
fontSize: 16.0,
fontStyle: FontStyle.italic
),
prefixIcon: Icon(Icons.person)
),
),
//密码
TextField(
obscureText: true,
decoration: InputDecoration(
labelText: "密码",
hintText: "请输入密码",
hintStyle: TextStyle(fontSize: 12.0,color: Colors.grey),
labelStyle: TextStyle(
color: Colors.blueGrey,
fontSize: 16.0,
fontStyle: FontStyle.italic
),
prefixIcon: Icon(Icons.lock)
),
)
],),
);
}
}
3.获取输入框的值,两种方式
- 定义两个变量,用于保存用户名和密码,然后在onChange触发时,各自保存一下输入内容。
- 通过controller直接获取
import 'package:flutter/material.dart';
TextEditingController nameCtrl=new TextEditingController();
class MyInput extends StatefulWidget{
@override
_MyInputState createState() {
// TODO: implement createState
return _MyInputState();
}
}
class _MyInputState extends State<MyInput>{
String _userName; //用户名
//获取用户名
_setUserName(val){
setState(() {
_userName=val;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("TextField"),),
body:Column(children: <Widget>[
TextField(
controller: nameCtrl,
autofocus: true,
//监听文本的变化
onChanged:(val){
_setUserName(val);
},
decoration: InputDecoration(
labelText: "用户名",
hintText: "请输入用户名和密码",
hintStyle: TextStyle(fontSize: 12.0,color: Colors.grey),
labelStyle: TextStyle(
color: Colors.blueGrey,
fontSize: 16.0,
fontStyle: FontStyle.italic
),
prefixIcon: Icon(Icons.person)
),
),
TextField(
obscureText: true,
decoration: InputDecoration(
labelText: "密码",
hintText: "请输入密码",
hintStyle: TextStyle(fontSize: 12.0,color: Colors.grey),
labelStyle: TextStyle(
color: Colors.blueGrey,
fontSize: 16.0,
fontStyle: FontStyle.italic
),
prefixIcon: Icon(Icons.lock)
),
),
RaisedButton(
child: Text("获取TextField的值"),
onPressed: (){
//第三个字符开始选中后面的字符
nameCtrl.selection=TextSelection(
baseOffset: 2,
extentOffset: nameCtrl.text.length
);
print("userName state获取数据:$_userName");
print("control获取数据:${nameCtrl.text}");
},
)
],)
);
}
}
4.Form,FormField,FormState
1.Form继承自StatefulWidget对象,它对应的状态类为FormState
Form({
@required Widget child,
bool autovalidate = false, //是否自动校验输入内容;当为true时,每一个子FormField内容发生变化时都会自动校验合法性,并直接显示错误信息。否则,需要通过调用FormState.validate()来手动校验
WillPopCallback onWillPop, // 决定Form所在的路由是否可以直接返回(如点击返回按钮),该回调返回一个Future对象,如果Future的最终结果是false,则当前路由不会返回;如果为true,则会返回到上一个路由。此属性通常用于拦截返回按钮
VoidCallback onChanged, //Form的任意一个子FormField内容发生变化时会触发此回调
})
2.Form的子孙元素必须是FormField类型,FormField是一个抽象类,定义几个属性,FormState内部通过它们来完成操作,FormField部分定义如下:
const FormField({
...
FormFieldSetter<T> onSaved, //保存回调
FormFieldValidator<T> validator, //验证回调
T initialValue, //初始值
bool autovalidate = false, //是否自动校验。
})
为了方便使用,Flutter提供了一个TextFormField widget,它继承自FormField类,也是TextField的一个包装类,所以除了FormField定义的属性之外,它还包括TextField的属性
3.FormState为Form的State类,可以通过Form.of()或GlobalKey获得。我们可以通过它来对Form的子孙FormField进行统一操作。我们看看其常用的三个方法
FormState.validate():调用此方法后,会调用Form子孙FormField的validate回调,如果有一个校验失败,则返回false,所有校验失败项都会返回用户返回的错误提示
FormState.save():调用此方法后,会调用Form子孙FormField的save回调,用于保存表单内容
FormState.reset():调用此方法后,会将子孙FormField的内容清空
1.用户名不能为空,如果为空则提示“用户名不能为空”。
2.密码不能小于6位,如果小于6为则提示“密码不能少于6位”。
import 'package:flutter/material.dart';
class MyInput extends StatefulWidget{
@override
_MyInputState createState()=>_MyInputState();
}
class _MyInputState extends State<MyInput>{
String _fmResult; //成功失败提示
int _count=0; //成功计数
GlobalKey _formKey=new GlobalKey<FormState>(); //定义 FormState
TextEditingController _nameCtrl=new TextEditingController(); // 用户名的control
TextEditingController _pwdCtrl=new TextEditingController(); //密码的control
_setResult(val){
setState(() {
_count++;
_fmResult=val;
});
}
Widget _fmUserNameWidget(){
return TextFormField(
controller: _nameCtrl, // 用于获取用户名值
decoration: InputDecoration(
labelText: "用户名",
hintText: "请输入用户名和密码",
hintStyle: TextStyle(fontSize: 12.0,color: Colors.grey),
labelStyle: TextStyle(
color: Colors.blueGrey,
fontSize: 16.0,
fontStyle: FontStyle.italic
),
prefixIcon: Icon(Icons.person)
),
validator: (v){
return v.trim().length>0?null:"用户名不能为空";
},
);
}
Widget _fmPwdWidget(){
return TextFormField(
controller: _pwdCtrl, // 用于获取密码值
obscureText: true,
decoration: InputDecoration(
labelText: "密码",
hintText: "请输入密码",
hintStyle: TextStyle(fontSize: 12.0,color: Colors.grey),
labelStyle: TextStyle(
color: Colors.blueGrey,
fontSize: 16.0,
fontStyle: FontStyle.italic
),
prefixIcon: Icon(Icons.lock)
),
validator: (v){
return v.trim().length>3?null:"密码不能少于3位";
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("TextField"),),
body: Form(
key:_formKey,
// autovalidate: true,
child: Column(children: <Widget>[
_fmUserNameWidget(),
_fmPwdWidget(),
RaisedButton(
child: Text("登录"),
onPressed: (){
// 通过_formKey.currentState 获取FormState后,
// 调用validate()方法校验用户名密码是否合法,校验
// 通过后再提交数据。
if((_formKey.currentState as FormState).validate()){
_setResult("成功$_count");
}else{
_setResult("失败");
}
},
),
Text("${_fmResult==null?'':_fmResult}"),
],),
)
);
}
}