Flutter文本输入框TextField属性(InputDecoration、textInputAction、inputFormatters等等)详解

 

TextField

Flutter中的文本输入框(TextField)就类似于Android中的EditText,但是用起来比EditText方便很多,改变样式也更加的方便。下面我们来看一下TextField的构造方法

构造方法

  const TextField({
    Key key,
    this.controller,    //编辑框的控制器,跟文本框的交互一般都通过该属性完成,如果不创建的话默认会自动创建
    this.focusNode,  //用于管理焦点
    this.decoration = const InputDecoration(),   //输入框的装饰器,用来修改外观
    TextInputType keyboardType,   //设置输入类型,不同的输入类型键盘不一样
    this.textInputAction,   //用于控制键盘动作(一般位于右下角,默认是完成)
    this.textCapitalization = TextCapitalization.none,
    this.style,    //输入的文本样式
    this.textAlign = TextAlign.start,   //输入的文本位置
    this.textDirection,    //输入的文字排列方向,一般不会修改这个属性
    this.autofocus = false,   //是否自动获取焦点
    this.obscureText = false,   //是否隐藏输入的文字,一般用在密码输入框中
    this.autocorrect = true,   //是否自动校验
    this.maxLines = 1,   //最大行
    this.maxLength,   //能输入的最大字符个数
    this.maxLengthEnforced = true,  //配合maxLength一起使用,在达到最大长度时是否阻止输入
    this.onChanged,  //输入文本发生变化时的回调
    this.onEditingComplete,   //点击键盘完成按钮时触发的回调,该回调没有参数,(){}
    this.onSubmitted,  //同样是点击键盘完成按钮时触发的回调,该回调有参数,参数即为当前输入框中的值。(String){}
    this.inputFormatters,   //对输入文本的校验
    this.enabled,    //输入框是否可用
    this.cursorWidth = 2.0,  //光标的宽度
    this.cursorRadius,  //光标的圆角
    this.cursorColor,  //光标的颜色
    this.keyboardAppearance,
    this.scrollPadding = const EdgeInsets.all(20.0),
    this.dragStartBehavior = DragStartBehavior.down,
    this.enableInteractiveSelection,
    this.onTap,    //点击输入框时的回调(){}
    this.buildCounter,
  })

可以看到,属性还是很多的,但都比较简单,下面我们来看一下常用的属性。


TextField decoration

我们首先来看一下decoration
decoration(装饰器) 接收一个InputDecoration类型的值,主要用于控制TextField的外观以及提示信息等
我们来看看InputDecoration的构造方法

InputDecoration({
    this.icon,    //位于装饰器外部和输入框前面的图片
    this.labelText,  //用于描述输入框,例如这个输入框是用来输入用户名还是密码的,当输入框获取焦点时默认会浮动到上方,
    this.labelStyle,  // 控制labelText的样式,接收一个TextStyle类型的值
    this.helperText, //辅助文本,位于输入框下方,如果errorText不为空的话,则helperText不会显示
    this.helperStyle, //helperText的样式
    this.hintText,  //提示文本,位于输入框内部
    this.hintStyle, //hintText的样式
    this.hintMaxLines, //提示信息最大行数
    this.errorText,  //错误信息提示
    this.errorStyle, //errorText的样式
    this.errorMaxLines,   //errorText最大行数
    this.hasFloatingPlaceholder = true,  //labelText是否浮动,默认为true,修改为false则labelText在输入框获取焦点时不会浮动且不显示
    this.isDense,   //改变输入框是否为密集型,默认为false,修改为true时,图标及间距会变小
    this.contentPadding, //内间距
    this.prefixIcon,  //位于输入框内部起始位置的图标。
    this.prefix,   //预先填充的Widget,跟prefixText同时只能出现一个
    this.prefixText,  //预填充的文本,例如手机号前面预先加上区号等
    this.prefixStyle,  //prefixText的样式
    this.suffixIcon, //位于输入框后面的图片,例如一般输入框后面会有个眼睛,控制输入内容是否明文
    this.suffix,  //位于输入框尾部的控件,同样的不能和suffixText同时使用
    this.suffixText,//位于尾部的填充文字
    this.suffixStyle,  //suffixText的样式
    this.counter,//位于输入框右下方的小控件,不能和counterText同时使用
    this.counterText,//位于右下方显示的文本,常用于显示输入的字符数量
    this.counterStyle, //counterText的样式
    this.filled,  //如果为true,则输入使用fillColor指定的颜色填充
    this.fillColor,  //相当于输入框的背景颜色
    this.errorBorder,   //errorText不为空,输入框没有焦点时要显示的边框
    this.focusedBorder,  //输入框有焦点时的边框,如果errorText不为空的话,该属性无效
    this.focusedErrorBorder,  //errorText不为空时,输入框有焦点时的边框
    this.disabledBorder,  //输入框禁用时显示的边框,如果errorText不为空的话,该属性无效
    this.enabledBorder,  //输入框可用时显示的边框,如果errorText不为空的话,该属性无效
    this.border, //正常情况下的border
    this.enabled = true,  //输入框是否可用
    this.semanticCounterText,  
    this.alignLabelWithHint,
  })

我们先来用一下InputDecoration,这里我们主要介绍一下常用的属性
默认样式

TextField(
      decoration: InputDecoration(),
    );

在这里插入图片描述

icon

TextField(
      decoration: InputDecoration(
        icon: Icon(Icons.person),
      ),
    );

在这里插入图片描述

labelText

用于描述输入框,例如这个输入框是用来输入用户名还是密码的,当输入框获取焦点时默认会浮动到上方

TextField(
      decoration: InputDecoration(
        icon: Icon(Icons.person),
        labelText: "labelText",
      ),
    );


下面输入框的用户名对应的就是labelText
在这里插入图片描述

labelStyle

设置labelText的样式

TextField(
      decoration: InputDecoration(
          icon: Icon(Icons.person),
          labelText: "labelText",
          labelStyle: TextStyle(
            color: Colors.red,
            fontSize: 20,
          )),
    );


在这里插入图片描述

helperText

辅助文本,位于输入框下方,如果errorText不为空的话,则helperText不会显示

TextField(
      decoration: InputDecoration(
        icon: Icon(Icons.person),
        labelText: "labelText",
        helperText: "helperText",
      ),
    );


在这里插入图片描述

helperStyle

TextField(
      decoration: InputDecoration(
        icon: Icon(Icons.person),
        labelText: "labelText",
        helperText: "helperText",
        helperStyle: TextStyle(
          color: Colors.green,//绿色
          fontSize: 20,//字体变大
        ),
      ),
    );



在这里插入图片描述

errorText

错误提示信息,如果该属性不为null的话,labelText失效。

TextField(
      decoration: InputDecoration(
        icon: Icon(Icons.person),
        labelText: "labelText",
        helperText: "helperText",
        errorText: "errorText",
      ),
    );




在这里插入图片描述

hintText

输入框中的提示信息,这个没啥好说的

TextField(
      decoration: InputDecoration(
        icon: Icon(Icons.person),
        hintText: "hintText",
      ),
    );



在这里插入图片描述

hasFloatingPlaceholder

labelText是否浮动,默认为true,修改为false则labelText在输入框获取焦点时不会浮动且不显示

TextField(
      decoration: InputDecoration(
        icon: Icon(Icons.person),
        hasFloatingPlaceholder: false,
        labelText: "labelText",
        helperText: "helperText",
        errorText: "errorText",
        hintText: "hintText",
      ),
    );


在这里插入图片描述

prefixIcon、prefixText

图片和预填充的文字

TextField(
      decoration: InputDecoration(
        icon: Icon(Icons.person),
        hasFloatingPlaceholder: false,
        labelText: "labelText",
        helperText: "helperText",
        errorText: "errorText",
       // hintText: "hintText",
        prefixIcon: Icon(Icons.perm_identity),
        prefixText: "prefixText",
      ),
    );


在这里插入图片描述

suffixIcon、suffixText

TextField(
      decoration: InputDecoration(
        //icon: Icon(Icons.person),
        hasFloatingPlaceholder: false,
        labelText: "labelText",
//        helperText: "helperText",
//        errorText: "errorText",
        // hintText: "hintText",
        prefixIcon: Icon(Icons.perm_identity),
        prefixText: "prefixText",
        suffixIcon: Icon(
          Icons.remove_red_eye,
        ),
        suffixText: "suffixText",
      ),
    );



在这里插入图片描述

counterText

TextField(
      decoration: InputDecoration(
        //icon: Icon(Icons.person),
        hasFloatingPlaceholder: false,
        labelText: "labelText",
        // helperText: "helperText",
//        errorText: "errorText",
        // hintText: "hintText",
//        prefixIcon: Icon(Icons.perm_identity),
//        prefixText: "prefixText",
//        suffixIcon: Icon(
//          Icons.remove_red_eye,
//        ),
//        suffixText: "suffixText",

        counterText: "counterText",
      ),
    );



在这里插入图片描述

filled,fillColor

颜色填充

TextField(
      decoration: InputDecoration(
        //icon: Icon(Icons.person),
        hasFloatingPlaceholder: false,
        labelText: "labelText",
        // helperText: "helperText",
//        errorText: "errorText",
         hintText: "hintText",
        prefixIcon: Icon(Icons.perm_identity),
//        prefixText: "prefixText",
//        suffixIcon: Icon(
//          Icons.remove_red_eye,
//        ),
//        suffixText: "suffixText",

       // counterText: "counterText",
        filled: true,
        fillColor: Colors.grey,
      ),
    );


在这里插入图片描述

下面来看一下两个输入框的对比:

上面的输入框代码:

TextField(
      decoration: InputDecoration(
        icon: Icon(Icons.person),
       // hasFloatingPlaceholder: false,
        labelText: "labelText",
        helperText: "helperText",
        errorText: "errorText",
        hintText: "hintText",
        prefixIcon: Icon(Icons.perm_identity),
        prefixText: "prefixText",
        suffixIcon: Icon(
          Icons.remove_red_eye,
        ),
        suffixText: "suffixText",
        counterText: "counterText",
        filled: true,
       // fillColor: Colors.grey,
      ),
    );


下面的输入框代码:

TextField(
      decoration: InputDecoration(
        icon: Icon(Icons.person),
        prefixIcon: Icon(Icons.perm_identity),
        labelText: "手机号",
        helperText: "用户名为手机号或者邮箱",
        errorText: "手机号码不正确",
        hintText: "请输入手机号码",
        prefixText: "+86",
        suffixIcon: Icon(
          Icons.remove_red_eye,
        ),
        suffixText: "隐藏输入文本",
        counterText: "0/10",
        filled: true,
      ),
    );


图示:
在这里插入图片描述

border、errorBorder、focusedBorder、focusedErrorBorder、disabledBorder、enabledBorder

不同状态下的边框样式,他们接收值的类型都一样,不过需要注意优先级。
大致分为一下几种情况

1. 控件禁用时
当enabled为false时,如果指定了disabledBorder,优先使用disabledBorder,没有的话设置disabledBorder则使用border的部分样式(颜色默认是灰色)

2. 控件启用(enable为true),但errorText有值
输入框没有焦点时,优先使用errorBorder的样式,输入框有焦点时,优先使用focusedErrorBorder,如果这两个都没有设置则使用border的部分样式(颜色默认是红色)

3. 控件启用状态,且errorText没有值
输入框没有焦点时,优先使用enabledBorder ,有焦点时,优先使用focusedBorder,两者均没有指定时,使用默认的border

总体来说,默认的border优先级别较低。
建议:

  1. 在开发过程中我们如果需要errorText的话,我们只需要设置 errorBorder、focusedErrorBorder这三个即可。不需要errorText的话
  2. 不需要errorText的话,只需要设置enabledBorder 、focusedBorder

下面我们来看一下border的值

1. InputBorder.none 没有任何边框

代码:

TextField(
      decoration: InputDecoration(
        border:InputBorder.none,
        labelText: "labelText",
        helperText: "helperText",
       // errorText: "errorText",
        hintText: "hintText",
        prefixIcon: Icon(Icons.perm_identity),
      ),
    );




在这里插入图片描述

2. OutlineInputBorder(外边线)
代码:

TextField(
      decoration: InputDecoration(
        enabledBorder: OutlineInputBorder(
          /*边角*/
          borderRadius: BorderRadius.all(
            Radius.circular(30), //边角为30
          ),
          borderSide: BorderSide(
            color: Colors.amber, //边线颜色为黄色
            width: 2, //边线宽度为2
          ),
        ),
        focusedBorder: OutlineInputBorder(
            borderSide: BorderSide(
          color: Colors.green, //边框颜色为绿色
          width: 5, //宽度为5
        )),
        labelText: "labelText",
        helperText: "helperText",
        // errorText: "errorText",
        hintText: "hintText",
        prefixIcon: Icon(Icons.perm_identity),
      ),
    );




在这里插入图片描述

2. UnderlineInputBorder(底边线,默认就是这个)

TextField(
      decoration: InputDecoration(
        errorBorder: UnderlineInputBorder(
          /*边角*/
          borderRadius: BorderRadius.all(
            Radius.circular(30), //边角为30
          ),
          borderSide: BorderSide(
            color: Colors.amber, //边线颜色为黄色
            width: 2, //边线宽度为2
          ),
        ),
        focusedErrorBorder: UnderlineInputBorder(
            borderSide: BorderSide(
          color: Colors.green, //边框颜色为绿色
          width: 5, //宽度为5
        )),
        labelText: "labelText",
        helperText: "helperText",
         errorText: "errorText",
        hintText: "hintText",
        prefixIcon: Icon(Icons.perm_identity),
      ),
    );



在这里插入图片描述

到这里基本上InputDecoration的属性都介绍完毕了。


keyboardType

键盘的类型,常用值如下,比较简单

在这里插入图片描述

TextField(
      decoration: InputDecoration(
        labelText: "labelText",
        helperText: "helperText",
        errorText: "errorText",
        hintText: "hintText",
        prefixIcon: Icon(Icons.perm_identity),
      ),

      keyboardType: TextInputType.phone, //手机号
    );



可以看到 键盘变成了数字键盘,其他的值就不在演示了。
在这里插入图片描述


TextField textInputAction

键盘操作按钮的类型,接收一个TextInputAction 类型的值。

TextInputAction 是一个枚举类型,值如下,其中有些值需要考虑Android和ios是否兼容的问题

enum TextInputAction {
//没有任何动作
  none,
  
//让操作系统决定哪个动作更合适
  unspecified,
  
//完成动作,一般会显示“完成”二字
  done,
  
  /// 跳转动作,一般用于输入了一个超链接后执行该动作。键盘上会显示“前往”二字
  go,
//搜索动作
  search,

//发送
  send,

  ///下个
  next,

  /// 返回前一个
  previous,

//继续动作,在Android上好像没反应,不显示键盘
  continueAction,

//在Android上好像没反应,不显示键盘
  route,

//拨打紧急电话,在Android上好像没反应,不显示键盘
  emergencyCall,

//换行
  newline,
}



例如:

textInputAction: TextInputAction.search,

在这里插入图片描述

textInputAction: TextInputAction.go,

在这里插入图片描述


TextField onChanged

输入文本发生变化时的回调,参数即为输入框中的值

 onChanged: (val) {
        print(val);
      },



TextField onEditingComplete

点击键盘的动作按钮时的回调,没有参数

  onEditingComplete: (){
        print("点击了键盘上的动作按钮");
      },



TextField onSubmitted

点击键盘的动作按钮时的回调,参数为当前输入框中的值

  onSubmitted: (val){
        print("点击了键盘上的动作按钮,当前输入框的值为:${val}");
      },


TextField inputFormatters

用于限制输入的内容,接收一个TextInputFormatter 类型的集合。

TextInputFormatter是一个抽象类,
源码如下:
在这里插入图片描述

继承关系如下
官方给我们提供了三种校验方法,分别是

  1. WhitelistingTextInputFormatter 白名单校验,也就是只允许输入符合规则的字符
  2. BlacklistingTextInputFormatter 黑名单校验,除了规定的字符其他的都可以输入
  3. LengthLimitingTextInputFormatter 长度限制,跟maxLength作用类似

在这里插入图片描述

WhitelistingTextInputFormatter

首先我们来看看白名单,
部分源码如下:
在这里插入图片描述
他接受一个Pattern类型的参数,Pattern是一个接口,而RegExp实现了Pattern接口,

在这里插入图片描述

看到RegExp是不是很熟悉了,这不就是正则表达式么,那这样就好办了。

下面我们用一下白名单:

inputFormatters: [WhitelistingTextInputFormatter(RegExp("[a-z]"))],


例如,我们只允许输入小写的a到z。

在这里插入图片描述

BlacklistingTextInputFormatter
黑名单跟白名单用法类似,这里我就直接用了

  inputFormatters: [BlacklistingTextInputFormatter(RegExp("[a-z]"))],


除了小写的a到z都可以输入

在这里插入图片描述

LengthLimitingTextInputFormatter

限制输入的长度
这里我们配合之前的黑名单一起使用

 inputFormatters: [
        BlacklistingTextInputFormatter(RegExp("[a-z]")),
        LengthLimitingTextInputFormatter(5)
      ],



在这里插入图片描述


TextField controller

controller常用于赋值和取值操作

示例代码:

import 'package:flutter/material.dart';

class TextFieldWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _TextFieldState();
  }
}

class _TextFieldState extends State<TextFieldWidget> {
  TextEditingController _userEtController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("TextField"),
      ),
      body: Container(
        padding: EdgeInsets.all(10),
        child: Column(
          children: <Widget>[
            TextField(
              controller: _userEtController,
            ),
            RaisedButton(
              child: Text("赋值"),
              onPressed: () {
                setState(() {
                  _userEtController.text = "15937600635";
                });
              },
            ),
            RaisedButton(
              child: Text("获取值"),
              onPressed: () {
                setState(() {});
              },
            ),
            Text(_userEtController.text),
          ],
        ),
      ),
    );
  }
}




如下:
在这里插入图片描述


如果你觉得本文对你有帮助,麻烦动动手指顶一下,算是对本文的一个认可。也可以关注我的  Flutter 博客专栏,我会不定期的更新,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!

 

 

 

Flutter TextField详解

Realank
52018.10.23 11:48:50字数 497阅读 62,299

实现TextField说简单也简单,说有坑,坑也不小,下面从易到难介绍一下使用

1.最简单的就是无参数调用构造方法:

TextField()
 

2.光有输入框还不行,还得获取其中的内容,所以需要传递controller:

import 'package:flutter/material.dart';

class TextFieldPage extends StatelessWidget {
  Widget buildTextField(TextEditingController controller) {
    return TextField(
      controller: controller,
    );
  }

  

我通过给controller添加通知来获取TextField的值,这种使用场景不一定合适,更多的时候是在点击按钮的时候直接读取controller.text的值

3.另外TextFiled还有一下小的属性:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class TextFieldPage extends StatelessWidget {
  Widget buildTextField(TextEditingController controller) {
    return TextField(
      controller: controller,
      maxLength: 30,//最大长度,设置此项会让TextField右下角有一个输入数量的统计字符串
      maxLines: 1,//最大行数
      autocorrect: true,//是否自动更正
      autofocus: true,//是否自动对焦
      obscureText: true,//是否是密码
      textAlign: TextAlign.center,//文本对齐方式
      style: TextStyle(fontSize: 30.0, color: Colors.blue),//输入文本的样式
      inputFormatters: [WhitelistingTextInputFormatter.digitsOnly],//允许的输入格式
      onChanged: (text) {//内容改变的回调
        print('change $text');
      },
      onSubmitted: (text) {//内容提交(按回车)的回调
        print('submit $text');
      },
      enabled: true,//是否禁用
    );
  }

  
 

4.接着我还能显示placeholder

decoration可以给TextField添加装饰

TextField(
      decoration:
          InputDecoration(fillColor: Colors.blue.shade100, filled: true, labelText: 'Hello'),
    );

fillColor设置填充颜色,labelText设置标签文字,这个标签在没有输入的时候是占满输入框的,当输入聚焦以后,就会缩小到输入框左上角:

 

 

 
TextField(
      decoration: InputDecoration(
          fillColor: Colors.blue.shade100, filled: true, hintText: 'Hello', errorText: 'error'),
    );

hintText就是普通的placeholder,输入后就不显示了,errorText是错误提示

 

 

 

5.还能显示一些别的装饰

import 'package:flutter/material.dart';

class TextFieldPage extends StatelessWidget {
  Widget buildTextField() {
    return TextField(
      decoration: InputDecoration(
          fillColor: Colors.blue.shade100,
          filled: true,
          helperText: 'help',
          prefixIcon: Icon(Icons.local_airport),
          suffixText: 'airport'),
    );
  }

  
 

6.这些还不过瘾,我不喜欢这个安卓风格的下面的装饰线,我想变成圆角矩形的边框

import 'package:flutter/material.dart';

class TextFieldPage extends StatelessWidget {
  Widget buildTextField() {
    return TextField(
      decoration: InputDecoration(
          contentPadding: EdgeInsets.all(10.0),
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(15.0),
//            borderSide: BorderSide(color: Colors.red, width: 3.0, style: BorderStyle.solid)//没什么卵效果
          )),
    );
  }

  
 

7.改变装饰线颜色

无论是下面的装饰线,还是矩形边框装饰线,对焦后显示的颜色,都是主题颜色的primaryColor,失去焦点以后就是黑色,这显然不能满足自定义的需求,但是通过各种努力发现,改变边框颜色很困难,最后发现了这个答案:https://stackoverflow.com/questions/49600139/how-to-change-textfield-underline-color

所以正确的设置边框颜色的方式是这样的:

import 'package:flutter/material.dart';

class TextFieldPage extends StatelessWidget {
  Widget buildTextField() {
    return Theme(
      data: new ThemeData(primaryColor: Colors.red, hintColor: Colors.blue),
      child: TextField(
        decoration: InputDecoration(
            contentPadding: EdgeInsets.all(10.0),
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(15.0),
//            borderSide: BorderSide(color: Colors.red, width: 3.0, style: BorderStyle.solid)//没什么卵效果
            )),
      ),
    );
  }

  
 

8.改变边框的粗细

这些TextField的decoration彻底不能满足要求了,需要重构成这种方式:


import 'package:flutter/material.dart';

class TextFieldPage extends StatelessWidget {
  Widget buildTextField() {
    return Container(
      padding: const EdgeInsets.all(8.0),
      alignment: Alignment.center,
      height: 60.0,
      decoration: new BoxDecoration(
          color: Colors.blueGrey,
          border: new Border.all(color: Colors.black54, width: 4.0),
          borderRadius: new BorderRadius.circular(12.0)),
      child: new TextFormField(
        decoration: InputDecoration.collapsed(hintText: 'hello'),
      ),
    );
  }

  
 

InputDecoration.collapsed可以禁用装饰线,而是使用外面包围的Container的装饰线

致此,所有的输入框的坑都趟完了,欢迎大家多多交流

 

posted @ 2020-08-25 15:58  sundayswift  阅读(2696)  评论(0编辑  收藏  举报