Flutter 之 表单Widget(TextField & Form)(七)

1. TextField Widget

TextField用于接收用户的文本输入

20190605135257203.png

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 可以修改文本样式


20190605155222258.png
1.2.2 隐藏文本

修改obscureText的属性值
obscureText 设置为true时,输入的文本不可见,常用的密码类型

TextField(
  obscureText: true,
),
image.png
1.2.3 键盘类型

keyboardType 即可输入类型,传入TextInputType类型,比如传入number即数字键盘

TextField(
  keyboardType: TextInputType.number,
),
image.png

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,
),
截屏2022-04-13 上午9.34.25.png

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,
),
image.png

textCapitalization 其他可选类型

TextCapitalization.words // 单词首字母大写
TextCapitalization.sentences // 句子首字母大写
TextCapitalization.characters // 所有字母大写
textCapitalization: TextCapitalization.none // 默认无
1.2.6 光标

默认是一个蓝色竖线

TextField(
  cursorColor: Colors.orange,
  cursorWidth: 15,
  cursorRadius: Radius.circular(15),
),
截屏2022-04-13 上午9.45.31.png
1.2.7 最多行数
TextField(
  maxLines: 3,
),
image.png

从效果上看,TextField默认行数变成3行,如果我们想默认显示1行,最多输入3行,可以再加个参数 minLines

TextField(
  maxLines: 3,
  minLines: 1,
),

TextField的高度会自适应

1.2.8 计数器

TextField 右下角有个计数,超出数量限制无法输入

TextField(
  maxLength: 8,
),
image.png

默认效果:当前输入长度/最大长度,我们可以自定义一个计数器

TextField(
  maxLength: 8,
  decoration: InputDecoration(
    counter: Text("自定义计数 0/100"),
  ),
),
image.png
1.2.9 图标

图标有3种

  • 左外侧图标
TextField(
  decoration: InputDecoration(
    icon: Icon(Icons.person),
  ),
),
image.png
  • 左内侧图标
TextField(
  decoration: InputDecoration(
    prefixIcon: Icon(Icons.phone_android),
  ),
),
image.png
  • 右内侧图标
TextField(
  decoration: InputDecoration(
    suffixIcon: IconButton(
      icon: Icon(Icons.close),
      onPressed: () {
        controller.clear();
      },
    ),
  ),
),

在右侧图标加了IconButton,可以点击

image.png
1.2.10 提示文字

提示文字有4种

  • 输入提示文字
TextField(
  controller: controller,
  decoration: InputDecoration(
    hintText: '请输入账号aaa',
  ),
),
image.png
  • 悬浮提示文本
TextField(
  controller: controller,
  decoration: InputDecoration(
    hintText: '请输入账号aaa',
    labelText: '请输入账号',
  ),
),
image.png

可以看到默认显示labelText的,聚焦后显示hintText

  • 帮助提示文本
TextField(
  controller: controller,
  decoration: InputDecoration(
    helperText: "帮助文字",
    helperStyle: TextStyle(color: Colors.blue)
  ),
),
image.png
  • 错误提示文本
TextField(
  controller: controller,
  decoration: InputDecoration(
    errorText: "你没有输入任何内容",
  ),
),

image.png
1.2.11 去掉下划线
TextField(
  decoration: InputDecoration.collapsed(hintText: "无下划线的输入框"),
),
image.png

也可以decoration:null,这样的话就没有提示文本

1.2.12 边框
TextField(
  decoration: InputDecoration(
    border: OutlineInputBorder(),
  ),
),
image.png

可以通过borderRadius 修改圆角

TextField(
  decoration: InputDecoration(
    border: OutlineInputBorder(
      borderRadius: BorderRadius.all(Radius.circular(30)),
    ),
  ),
),
image.png
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("校验"),
          ),
        ],
      ),
    );
  }
}

截屏2022-04-13 下午12.00.20的副本.png

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("保存"),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

截屏2022-04-13 下午12.22.37.png

参考:
[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

你可能感兴趣的:(Flutter 之 表单Widget(TextField & Form)(七))