Flutter 组件篇之 TextField

TextField

TextField decoration

keyboardType

TextField textInputAction

TextField onChanged

TextField onEditingComplete

TextField onSubmitted

TextField inputFormatters

TextField controller

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失效。

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优先级别较低。

建议:

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

不需要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

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

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),

          ],

        ),

      ),

    );

  }

}

如下:

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容