Flutter--TextField学习

一、TextField学习

TextField 是文本输入组件,即输入框,常用组件之一

二、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.textAlignVertical,//垂直对齐方式
    this.textDirection,
    this.readOnly = false,//是否只能读取
    ToolbarOptions toolbarOptions,//配置工具栏
    this.showCursor,
    this.autofocus = false,//自动获取焦点
    this.obscuringCharacter = '•',
    this.obscureText = false,//是否隐藏文本,密码类型
    this.autocorrect = true,//自动更正
    SmartDashesType smartDashesType,
    SmartQuotesType smartQuotesType,
    this.enableSuggestions = true,
    this.maxLines = 1,//最大行数
    this.minLines,//最小行数
    this.expands = false,
    this.maxLength,//最多输入数,不为0时右下角有计数器
    this.maxLengthEnforced = true,
    this.onChanged,//输入改变回调
    this.onEditingComplete,//输入完成时,配合TextInputAction.done使用
    this.onSubmitted,//提交时,配合TextInputAction
    this.onAppPrivateCommand,
    this.inputFormatters,//输入校验
    this.enabled,//是否可用
    this.cursorWidth = 2.0,//光标宽度
    this.cursorHeight,//光标高度
    this.cursorRadius,//光标圆角
    this.cursorColor,//光标颜色
    this.selectionHeightStyle = ui.BoxHeightStyle.tight,
    this.selectionWidthStyle = ui.BoxWidthStyle.tight,
    this.keyboardAppearance,
    this.scrollPadding = const EdgeInsets.all(20.0),
    this.dragStartBehavior = DragStartBehavior.start,
    this.enableInteractiveSelection = true,
    this.onTap,//点击事件
    this.mouseCursor,
    this.buildCounter,
    this.scrollController,
    this.scrollPhysics,
    this.autofillHints,
    this.restorationId,
  }) : assert(textAlign != null),
       assert(readOnly != null),
       assert(autofocus != null),
       assert(obscuringCharacter != null && obscuringCharacter.length == 1),
       assert(obscureText != null),
       assert(autocorrect != null),
       smartDashesType = smartDashesType ?? (obscureText ? SmartDashesType.disabled : SmartDashesType.enabled),
       smartQuotesType = smartQuotesType ?? (obscureText ? SmartQuotesType.disabled : SmartQuotesType.enabled),
       assert(enableSuggestions != null),
       assert(enableInteractiveSelection != null),
       assert(maxLengthEnforced != null),
       assert(scrollPadding != null),
       assert(dragStartBehavior != null),
       assert(selectionHeightStyle != null),
       assert(selectionWidthStyle != null),
       assert(maxLines == null || maxLines > 0),
       assert(minLines == null || minLines > 0),
       assert(
         (maxLines == null) || (minLines == null) || (maxLines >= minLines),
         "minLines can't be greater than maxLines",
       ),
       assert(expands != null),
       assert(
         !expands || (maxLines == null && minLines == null),
         'minLines and maxLines must be null when expands is true.',
       ),
       assert(!obscureText || maxLines == 1, 'Obscured fields cannot be multiline.'),
       assert(maxLength == null || maxLength == TextField.noMaxLength || maxLength > 0),
       // Assert the following instead of setting it directly to avoid surprising the user by silently changing the value they set.
       assert(!identical(textInputAction, TextInputAction.newline) ||
         maxLines == 1 ||
         !identical(keyboardType, TextInputType.text),
         'Use keyboardType TextInputType.multiline when using TextInputAction.newline on a multiline TextField.'),
       keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline),
       toolbarOptions = toolbarOptions ?? (obscureText ?
         const ToolbarOptions(
           selectAll: true,
           paste: true,
         ) :
         const ToolbarOptions(
           copy: true,
           cut: true,
           selectAll: true,
           paste: true,
         )),
       super(key: key);

三、TextField属性说明

属性 说明
controller 控制器
为绑定的输入框 TextField 预设内容,TextEditingController(text:"初始化")
获取输入框内容,textEditingController.text
清空输入框内容,textEditingController.text ="",textEditingController.clear()
focusNode 焦点,用来控制TextField 焦点的获取与关闭,获取焦点FocusScope.of(context).requestFocus(focusNode),失去焦点,focusNode.unfocus()
decoration 装饰,InputDecoration详细见下文
keyboardType 键盘类型,输入类型
text:通用键盘
multiline:当TextField为多行时(maxLines设置大于1),右下角的为“换行” 按键。
number:数字键盘
phone:手机键盘,比数字键盘多"*"和 "#"
datetime:在ios上和text一样,在android上出现数字键盘、":"和 "-"
emailAddress:邮箱键盘,有"@" 和 "."按键
url:url键盘,有"/" 和 "."按键
visiblePassword:既有字幕又有数字的键盘
textInputAction 键盘右下角按钮(Android上显示的按钮大部分是不确定的)
none:android上显示返回键,ios不支持。
unspecified:让操作系统自己决定哪个合适,一般情况下,android显示“完成”或者“返回”。
done:android显示代表“完成”的按钮,ios显示“Done”(中文:完成)。
go:android显示表达用户去向目的地的图标,比如向右的箭头,ios显示“Go”(中文:前往)。
search:android显示表达搜索的按钮,ios显示"Search"(中文:搜索)。
send:android显示表达发送意思的按钮,比如“纸飞机”按钮,ios显示"Send"(中文:发送)。
next:android显示表达“前进”的按钮,比如“向右的箭头”,ios显示"Next"(中文:下一项)。
previous:android显示表达“后退”的按钮,比如“向左的箭头”,ios不支持。
continueAction:android 不支持,ios仅在ios9.0+显示"Continue"(中文:继续)。
join:Android和ios显示"Join"(中文:加入)。
route:android 不支持,ios显示"Route"(中文:路线)。
emergencyCall:android 不支持,ios显示"Emergency Call"(中文:紧急电话)。
newline:android显示表达“换行”的按钮,ios显示”换行“。
textCapitalization 大小写,仅仅是控制软键盘是大写模式还是小写模式,你也可以切换大小写
words:每一个单词的首字母大写。
sentences:每一句话的首字母大写。
characters:每个字母都大写
none:都小写
style 样式
textAlign 水平对齐方式
textAlignVertical 垂直对齐方式
readOnly 是否只能读,不可输入
toolbarOptions 长按时弹出的菜单,有copy、cut、paste、selectAll四个选项可配置
autofocus 是否自动获取焦点
obscuringCharacter 密码模式下显示文本
obscureText 是否隐藏文本,密码模式
autocorrect 自动更正
maxLines 最大行数
minLines /最小行数
maxLength 最多输入数,不为0时右下角有计数器
onChanged 输入改变回调
onEditingComplete 输入完成时,配合TextInputAction.done使用
onSubmitted 提交时,配合TextInputAction
inputFormatters 输入校验,限制用户输入的内容
enabled 是否可用
cursorWidth 光标宽度
cursorHeight 光标高度
cursorRadius 光标圆角
cursorColor 光标颜色
showCursor 是否显示光标
onTap 点击事件

四、InputDecoration的源码

const InputDecoration({
    this.icon,//位于装饰器外部和输入框前面的图片
    this.labelText,//用于描述输入框
    this.labelStyle,// 控制labelText的样式
    this.helperText,//帮助文本
    this.helperStyle,//helperText的样式
    this.helperMaxLines,//帮助文本的最大行数
    this.hintText,//提示文本
    this.hintStyle,//hintText的样式
    this.hintMaxLines,//提示文本的最大行数
    this.errorText,//错误文本
    this.errorStyle,//errorText的样式
    this.errorMaxLines,//错误文本的最大行数
    @Deprecated(
      'Use floatingLabelBehavior instead. '
      'This feature was deprecated after v1.13.2.'
    )
    this.hasFloatingPlaceholder = true,//labelText是否浮动
    this.floatingLabelBehavior = FloatingLabelBehavior.auto,//浮动标签应该如何显示
    this.isCollapsed = false,//是否可折叠
    this.isDense,//改变输入框是否为密集型
    this.contentPadding,//内间距
    this.prefixIcon,//位于输入框内部起始位置的图标。
    this.prefixIconConstraints,//设置起始位置图片的大小
    this.prefix,//预先填充的Widget
    this.prefixText,//预填充的文本
    this.prefixStyle, //prefixText的样式
    this.suffixIcon,//位于输入框后面的图片
    this.suffix,//位于输入框尾部的控件
    this.suffixText,//位于尾部的填充文字
    this.suffixStyle, //suffixText的样式
    this.suffixIconConstraints,//设置输入框后面图片的大小
    this.counter,//位于输入框右下方的小控件
    this.counterText,//位于右下方显示的文本
    this.counterStyle,//counterText的样式
    this.filled,  //如果为true,则输入使用fillColor指定的颜色填充
    this.fillColor,//相当于输入框的背景颜色
    this.focusColor,//获取焦点时颜色
    this.hoverColor,
    this.errorBorder, //errorText不为空,输入框没有焦点时要显示的边框
    this.focusedBorder,//输入框有焦点时的边框
    this.focusedErrorBorder,//输入框有焦点时的边框
    this.disabledBorder,//输入框禁用时显示的边框
    this.enabledBorder,//输入框可用时显示的边框
    this.border,//正常情况下的边框
    this.enabled = true,//输入框是否可用
    this.semanticCounterText,
    this.alignLabelWithHint,
  }) : assert(enabled != null),
       assert(!(prefix != null && prefixText != null), 'Declaring both prefix and prefixText is not supported.'),
       assert(!(suffix != null && suffixText != null), 'Declaring both suffix and suffixText is not supported.');

五、InputDecoration的属性介绍

属性 说明
icon 位于装饰器外部和输入框前面的图片
labelText 用于描述输入框
labelStyle 控制labelText的样式,TextStyle类型
helperText 帮助文本
helperStyle helperText的样式,TextStyle类型
helperMaxLines 帮助文本的最大行数
hintText 提示文本
如果有设置labelText,输入框获取焦点,才能显示hintText
hintMaxLines 提示文本的最大行数
errorText 错误文本
如果同时设置errorText和helperText,那么helperText会隐藏
errorStyle errorText的样式,TextStyle类型
floatingLabelBehavior:FloatingLabelBehavior.auto时,且输入框获取焦点时,errorStyle设置颜色会覆盖labelText的颜色
如果同时设置errorStyle和helperStyle,helperStyle样式会隐藏
errorMaxLines 错误文本的最大行数
hasFloatingPlaceholder labelText是否浮动,bool类型(已弃用)
值为true,输入框获取焦点labelText会浮动到输入框顶部
值为false,输入框获取焦点,labelText会隐藏
floatingLabelBehavior 浮动标签应该如何显示
FloatingLabelBehavior.never:labelText显示在输入框内,不可浮动
FloatingLabelBehavior.auto:labelText可浮动
FloatingLabelBehavior.always:labelText一直浮动在输入框上部
isCollapsed 是否可折叠
isDense 改变输入框是否为密集型,主要约束前置和后置图标的BoxConstraints大小
contentPadding 内间距
prefixIcon 位于输入框内部起始位置的图标。
prefixIconConstraints 设置起始位置图片的大小
prefix 预先填充的Widget,和prefixText只能同时存在一个
prefixText 预填充的文本,和prefix只能同时存在一个
prefixStyle prefixText的样式
suffixIcon 位于输入框后面的图片
suffix 位于输入框尾部的控件,和suffixText只能同时存在一个
suffixText 位于尾部的填充文字,和suffix只能同时存在一个
suffixStyle suffixText的样式
suffixIconConstraints 设置输入框后面图片的大小
counter 位于输入框右下方的小控件,不能和counterText同时使用
counterText 位于右下方显示的文本,不能和counter同时使用
counterStyle counterText的样式
filled 如果为true,则输入使用fillColor指定的颜色填充
fillColor 相当于输入框的背景颜色
focusColor 获取焦点时颜色
hoverColor 和鼠标有关
errorBorder errorText不为空,输入框没有焦点时要显示的边框
focusedBorder 输入框有焦点时的边框
focusedErrorBorder errorText不为空,输入框有焦点时的边框
disabledBorder 输入框禁用时显示的边框
enabledBorder 输入框可用时显示的边框
border 正常情况下的边框
enabled 输入框是否可用
border的优先级
  1. 控件禁用时
    当enabled为false时,如果指定了disabledBorder,优先使用disabledBorder,没有的话设置disabledBorder则使用border的部分样式(颜色默认是灰色)
  2. 控件启用(enable为true),但errorText有值
    输入框没有焦点时,优先使用errorBorder的样式,输入框有焦点时,优先使用focusedErrorBorder,如果这两个都没有设置则使用border的部分样式(颜色默认是红色)
  3. 控件启用状态,且errorText没有值
    输入框没有焦点时,优先使用enabledBorder ,有焦点时,优先使用focusedBorder,两者均没有指定时,使用默认的border

六、TextField、InputDecoration的demo

6.1、InputDecoration的使用
return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("TextField学习"),
          ),
          body: Container(
            padding: EdgeInsets.all(15),
            child: TextField(
                decoration: InputDecoration(
                  icon: Icon(Icons.person,size: 35,color: Colors.blue,),
                  labelText: "我是labelText",
                  labelStyle: TextStyle(
                    fontSize: 15
                  ),
                  helperText: "我是helperText",
                  helperStyle: TextStyle(
                    color: Colors.orange
                  ),
                  helperMaxLines: 2,
                  hintText: "我是hintText我是hintText我是hintText我是hintText我是hintText我是hintText我是hintText我是hintText我是hintText我是hintText",
                  hintMaxLines: 1,
                  errorText: "我是errorText",
                  errorStyle: TextStyle(
                    color: Colors.purpleAccent,
                    fontSize: 12
                  ),
                  //labelText是否会浮动
                  hasFloatingPlaceholder: true,
                  //labelText浮动的如何显示
                  floatingLabelBehavior:FloatingLabelBehavior.always,
                  //是否为密集型
                  isDense: false,
                  //内间距
                  contentPadding:EdgeInsets.fromLTRB(5, 0, 5, 0),
                  //位于输入框内部起始位置的图标
                  prefixIcon: Icon(Icons.search),
                    //设置起始位置图片的大小
                  prefixIconConstraints: BoxConstraints(minHeight: 5),
                  //预填充的widget
//                  prefix: Container(height: 10,width: 10,color: Colors.red,),
                    //预填充的文本
                  prefixText: "+86",
                    //位于输入框后面的图片
                  suffixIcon: Icon(Icons.cleaning_services),
                  //控制输入框后面的图片的大小
                    suffixIconConstraints:BoxConstraints(minHeight: 5),
                  //位于右下方显示的组件
//                  counter: Text("0/10"),
                  //位于右下方显示的文本
                  counterText: "0/10",
                  //是否使用fillColor颜色为输入框背景色
                  filled: true,
                  //输入框背景色
                  fillColor: Colors.white,
                  //有errorText,未获取焦点边框
                  errorBorder: OutlineInputBorder(
                      /*边角*/
                      borderRadius: BorderRadius.all(
                        Radius.circular(5), //边角为30
                      ),
                      borderSide: BorderSide(
                        color: Colors.yellow,
                        width: 1
                      )
                  ),
                  //有errorText,获取焦点边框
                  focusedErrorBorder: OutlineInputBorder(
                    /*边角*/
                      borderRadius: BorderRadius.all(
                        Radius.circular(5), //边角为30
                      ),
                      borderSide: BorderSide(
                          color: Colors.blue,
                          width: 1
                      )
                  ),
                ),
            ),
          )),
    );
e57566e83b1925f3f7194041e6c6299.png
6.2、TextField设置内容,并且保持光标在末尾
void main() {
  runApp(TextFieldFul());
}


class TextFieldFul extends StatefulWidget {
  TextFieldFul({Key key}) : super(key: key);

  _TextFieldFulState createState() => _TextFieldFulState();
}

class _TextFieldFulState extends State<TextFieldFul> {
  var textEditingController = TextEditingController();

  @override
  void initState() {
    super.initState();
    //初始化输入框的内容
    String initStr = "ysl";
    //初始化光标在文本的后面
    textEditingController = TextEditingController.fromValue(
      //初始化文本的显示
        TextEditingValue(
          //设置初始化文本
          text:initStr,
          //设置光标的位置
          selection: TextSelection.fromPosition(
            //设置文本的位置
            TextPosition(
              affinity: TextAffinity.downstream,
                //光标向后移动的位置
                offset:initStr.length
            )
          )
        )

    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("TextField学习"),
          ),
          body: Container(
            padding: EdgeInsets.all(15),
            child: TextField(
              controller: textEditingController,
              onChanged: (value){
                print(textEditingController.text);
              },
              autofocus: true,
            ),
          )),
    );
  }
}
6.3、TextField焦点获取和失去
class _TextFieldFulState extends State<TextFieldFul> {
  //焦点组件
  FocusNode focusNode = FocusNode();

  @override
  void initState() {
    super.initState();

    focusNode.addListener(() {
      //是否获取焦点
      bool hasFocus = focusNode.hasFocus;
      //是否添加了监听
      bool hasListener = focusNode.hasListeners;

      print("ysl--hasFocus:${hasFocus},hasListener:${hasListener}");
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("TextField学习"),
          ),
          body: Container(
            padding: EdgeInsets.all(15),
            child: Column(
              children: [
                TextField(
                  autofocus: true,
                  focusNode: focusNode,
                ),
                SizedBox(
                  height: 15,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    OutlinedButton(child: Text("获取焦点"), onPressed: () {
                      FocusScope.of(context).requestFocus(focusNode);
                    }),
                    OutlinedButton(child: Text("失去焦点"), onPressed: () {
                      focusNode.unfocus();
                    })
                  ],
                )
              ],
            ),
          )),
    );
  }
}
09c0705afa19d880495b6fbee0aecac.png
6.4、TextField的简单使用
return MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: Text("TextField学习"),
          ),
          body: Container(
            padding: EdgeInsets.all(10),
            child: TextField(
              //键盘类型
              keyboardType: TextInputType.phone,
              //键盘右下角按钮
              textInputAction: TextInputAction.none,
              //大小写
              textCapitalization: TextCapitalization.words,
              //样式
              style: TextStyle(
                color: Colors.red
              ),
              //水平对齐方式
              textAlign: TextAlign.center,
              //垂直对齐方式
              textAlignVertical: TextAlignVertical.center,
              //是否只读
              readOnly: false,
              //长按时弹出的菜单
              toolbarOptions:ToolbarOptions(
                copy: true,
                cut: true,
                paste: true,
                selectAll: true
              ) ,
              //是否自动获取焦点
              autofocus: false,
              //密码模式
              obscureText: true,
              //密码模式下显示文本
              obscuringCharacter: "*",
              //光标宽度
              cursorWidth: 5,
              cursorHeight: 10,
              //是否显示光标
              showCursor: true,
              //最多输入数量
              maxLength: 11,
              onTap: (){
                print("点击了输入框");
              },


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

推荐阅读更多精彩内容