1. TextField Widget
TextField用于接收用户的文本输入
1.1 基本属性
TextField
const TextField({
Key key,
this.controller,//控制器
this.focusNode,//焦点
this.decoration = const InputDecoration(),//装饰
TextInputType keyboardType,//键盘类型,即输入类型
this.textInputAction,//键盘按钮
this.textCapitalization = TextCapitalization.none,//大小写
this.style,//样式
this.strutStyle,
this.textAlign = TextAlign.start,//对齐方式
this.textDirection,
this.autofocus = false,//自动聚焦
this.obscureText = false,//是否隐藏文本,即显示密码类型
this.autocorrect = true,//自动更正
this.maxLines = 1,//最多行数,高度与行数同步
this.minLines,//最小行数
this.expands = false,
this.maxLength,//最多输入数,有值后右下角就会有一个计数器
this.maxLengthEnforced = true,
this.onChanged,//输入改变回调
this.onEditingComplete,//输入完成时,配合TextInputAction.done使用
this.onSubmitted,//提交时,配合TextInputAction
this.inputFormatters,//输入校验
this.enabled,//是否可用
this.cursorWidth = 2.0,//光标宽度
this.cursorRadius,//光标圆角
this.cursorColor,//光标颜色
this.keyboardAppearance,
this.scrollPadding = const EdgeInsets.all(20.0),
this.dragStartBehavior = DragStartBehavior.start,
this.enableInteractiveSelection,
this.onTap,//点击事件
this.buildCounter,
this.scrollPhysics,
})
InputDecoration
const InputDecoration({
this.icon,//左侧外的图标
this.labelText,//悬浮提示,可代替hintText
this.labelStyle,//悬浮提示文字的样式
this.helperText,//帮助文字
this.helperStyle,
this.hintText,//输入提示
this.hintStyle,
this.hintMaxLines,
this.errorText,//错误提示
this.errorStyle,
this.errorMaxLines,
this.hasFloatingPlaceholder = true,//是否显示悬浮提示文字
this.isDense,
this.contentPadding,//内填充
this.prefixIcon,//左侧内的图标
this.prefix,
this.prefixText,//左侧内的文字
this.prefixStyle,
this.suffixIcon,//右侧内图标
this.suffix,
this.suffixText,
this.suffixStyle,
this.counter,//自定义计数器
this.counterText,//计数文字
this.counterStyle,//计数样式
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 基础样式
TextField(),
style:TextStyle 可以修改文本样式
1.2.2 隐藏文本
修改obscureText的属性值
obscureText 设置为true时,输入的文本不可见,常用的密码类型
TextField(
obscureText: true,
),
1.2.3 键盘类型
keyboardType 即可输入类型,传入TextInputType类型,比如传入number即数字键盘
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 //发送或者send
TextInputAction.next //下一项或者next
TextInputAction.previous // 上一项 IOS 不支持
TextInputAction.continueAction //继续或者 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 // 默认无
1.2.6 光标
默认是一个蓝色竖线
TextField(
cursorColor: Colors.orange,
cursorWidth: 15,
cursorRadius: Radius.circular(15),
),
1.2.7 最多行数
TextField(
maxLines: 3,
),
从效果上看,TextField默认行数变成3行,如果我们想默认显示1行,最多输入3行,可以再加个参数 minLines
TextField(
maxLines: 3,
minLines: 1,
),
TextField的高度会自适应
1.2.8 计数器
TextField 右下角有个计数,超出数量限制无法输入
TextField(
maxLength: 8,
),
默认效果:当前输入长度/最大长度,我们可以自定义一个计数器
TextField(
maxLength: 8,
decoration: InputDecoration(
counter: Text("自定义计数 0/100"),
),
),
1.2.9 图标
图标有3种
- 左外侧图标
TextField(
decoration: InputDecoration(
icon: Icon(Icons.person),
),
),
- 左内侧图标
TextField(
decoration: InputDecoration(
prefixIcon: Icon(Icons.phone_android),
),
),
- 右内侧图标
TextField(
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(Icons.close),
onPressed: () {
controller.clear();
},
),
),
),
在右侧图标加了IconButton,可以点击
1.2.10 提示文字
提示文字有4种
- 输入提示文字
TextField(
controller: controller,
decoration: InputDecoration(
hintText: '请输入账号aaa',
),
),
- 悬浮提示文本
TextField(
controller: controller,
decoration: InputDecoration(
hintText: '请输入账号aaa',
labelText: '请输入账号',
),
),
可以看到默认显示labelText的,聚焦后显示hintText
- 帮助提示文本
TextField(
controller: controller,
decoration: InputDecoration(
helperText: "帮助文字",
helperStyle: TextStyle(color: Colors.blue)
),
),
- 错误提示文本
TextField(
controller: controller,
decoration: InputDecoration(
errorText: "你没有输入任何内容",
),
),
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 获取输入内容
有两种方式
- onChanged
onChanged 是输入文本发生变化时回调,返回是一个String,可以用变量记录下
TextField(
onChanged: (text) {
print("输入改变时" + text);
},
),
- controller
即控制器
初始化
var controller;
@override
void initState() {
super.initState();
controller = TextEditingController();
controller.addListener(() {});
}
配置给TextField
TextField(
controller: controller,
),
获取内容
controller.text
在事件中调用controller.text,即输入的文本
1.2.14 关闭软键盘
初始化
FocusNode userFocusNode = FocusNode();
配置
TextField(
focusNode: userFocusNode,
),
然后在需要的地方调用
userFocusNode.unfocus();
1.2.15 校验
RegExp 可以使用正则表达式来校验
String? validateMobile(String value) {
String patttern = r'(^[0-9]*$)';
RegExp regExp = new RegExp(patttern);
if (value.length == 0) {
return "手机号为空";
} else if (!regExp.hasMatch(value)) {
return "手机号格式不正确";
}
return null;
}
2、表单From
flutter提供一套表单校验框架Form,可以通过Form框架一步校验所有表单,非常方便,比较常用的用法是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,有一个widget 类型的child参数,证明Form是一个容器
FormState 里还有一个validate方法
bool validate() {
_hasInteractedByUser = true;
_forceRebuild();
return _validate();
}
一般通过GlobalKey来访问Form中validate方法,Form的validate方法用来校验所有Form里的FormField表单,validate方法返回值是bool类型,返回true表示所有表单校验成功;返回false表示有校验失败的表单;
TextFormField
class TextFormField extends FormField {
...
TextFormField({
...
FormFieldValidator validator,
...
})
TextFormField继承FormField,FormField后面源码分析会讲,所有Form可统一校验的表单都必须继承FormField,可以通过FormField自定义各种各样可校验表单,TextFormField只是FormField自定义表单中的一种。
表单校验必须实现的方法为validator,定义如下:
typedef FormFieldValidator = String? Function(T? value);
每个表单的校验规则都在validator里实现,通过返回值来判断是否校验成功。
返回null,表示表单校验成功
返回非null,表示表单校验失败,其实返回的非null还可以用来表示校验失败的错误提示信息,TextFormField内部实现就将返回的非null当成错误信息提示出来
2.2 使用步骤
1、用Form包在所有需要校验的表单最外层,如下:
Form(
key:xxx,
child:xxx
2、将GlobalKey传给Form,用于调用Form里方法,如下:
final GlobalKey _formKey = GlobalKey();
Form(
key:_formKey,
child:xxx
3、将TextFormField传给Form容器,如下:
final GlobalKey _formKey = GlobalKey();
Form(
key:_formKey,
child:
...
TextFormField
...
4、实现对应TextFormField的校验规则 ,如下:
final GlobalKey _formKey = GlobalKey();
Form(
key:_formKey,
child:
...
TextFormField(
validator: (value) {
...
return xxx;
},
)
...
5、最后调用Form校验所有表单方法validate,如下:
_formKey.currentState.validate()
2.3 Form 校验 示例
class _MSHomeContentState extends State {
final GlobalKey _formKey = GlobalKey();
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
hintText: "请输入手机号",
),
validator: (value) {
RegExp reg = new RegExp(r'^\d{11}$');
if (!reg.hasMatch(value!)) {
return '请输入11位手机号';
}
return null;
},
),
TextFormField(
decoration: InputDecoration(
hintText: "请输入用户名",
),
validator: (value) {
if (value!.isEmpty) {
return "请输入用户名";
}
return null;
},
),
SizedBox(
height: 20,
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("校验成功")));
// Scaffold.of(context).showSnackBar(snackbar)
}
},
child: Text("校验"),
),
],
),
);
}
}
2.4 Form 保存和获取表单数据 示例
class _MSHomeContentState extends State {
final GlobalKey _formKey = GlobalKey();
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: "请输入手机号",
),
onSaved: (value) {
phoneNum = value;
},
),
SizedBox(
height: 20,
),
TextFormField(
decoration: InputDecoration(
hintText: "请输入用户名",
),
onSaved: (value) {
userName = value;
},
),
SizedBox(
height: 20,
),
Container(
width: double.infinity,
height: 50,
padding: EdgeInsets.symmetric(horizontal: 16),
child: ElevatedButton(
onPressed: () {
// 保存和获取表单数据
_formKey.currentState!.save();
print("userName: $userName,phoneNum:$phoneNum");
},
child: Text("保存"),
),
),
],
),
),
);
}
}
参考:
[Button]https://blog.csdn.net/qq_41619796/article/details/115658314
[Image]https://www.jianshu.com/p/27394b02d4d6/
[TextFiled]https://blog.csdn.net/yechaoa/article/details/90906689
[From]https://www.jianshu.com/p/b5bc338b260b