Flutter 之 输入框TextField

Material组件库中提供了输入框组件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, //水平方向对齐方式。  值为  left、  right  、center、  justify 、 start、  end
    this.textAlignVertical, // 文本垂直方向对齐方式 。 值为 top   、 center 、  bottom
    this.textDirection,   //文本方向  rtl(right to left)   ltr(left to right)
    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,  // 最多输入数,有值后右下角就会有一个计数器
    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, //确定[Scrollable]小部件的物理性质。
    this.autofillHints,//自动填充提示
    this.restorationId, //恢复ID以保存和恢复文本字段的状态。

属性详解

  • controller:编辑框的控制器,通过它可以设置/获取编辑框的内容、选择编辑内容、监听编辑文本改变事件。大多数情况下我们都需要显式提供一个controller来与文本框交互。如果没有提供controller,则TextField内部会自动创建一个。
  • focusNode:用于控制TextField是否占有当前键盘的输入焦点。它是我们和键盘交互的一个句柄(handle)
  • InputDecoration:用于控制TextField的外观显示,如提示文本、背景颜色、边框等。
  • keyboardType:用于设置该输入框默认的键盘输入类型

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

注意

prefix和prefixText 以及suffix和suffixText 不能同时存在



keyboardType

TextInputType枚举值 含义
text 文本输入键盘
multiline 多行文本,需和maxLines配合使用(设为null或大于1)
number 数字;会弹出数字键盘
phone 优化后的电话号码输入键盘;会弹出数字键盘并显示“* #”
datetime 优化后的日期输入键盘;Android上会显示“: -”
emailAddress 优化后的电子邮件地址;会显示“@ .”
url 优化后的url输入键盘; 会显示“/ .”

示例:登录输入框

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

main() {
  runApp(Myapp());
}

class Myapp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("基础组件"),
        ),
        body: YshContent(),
      ),
    );
  }
}

class YshContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            decoration: InputDecoration(
                labelText: "请输入用户名",
                icon: Icon(Icons.people),
                hintText: "请输入用户名",
                prefixIcon: Icon(Icons.people_alt_rounded)),
          ),
        ),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            obscureText: true,
            decoration: InputDecoration(
              labelText: "请输入密码",
              prefixIcon: Icon(Icons.lock),
              hintText: "请输入密码",
            ),
          ),
        ),
      ],
    );
  }
}

登录

获取输入内容

  • 获取输入内容有两种方式:
    • 定义两个变量,用于保存用户名和密码,然后在onChange触发时,各自保存一下输入内容。
    • 通过controller直接获取。

通过onChange获取
void onChanged(String value) {
print(value);
}

通过controller 获取
//定义一个controller
TextEditingController _controller = TextEditingController();
然后设置输入框controller:
TextField(
controller: _controller , //设置controller
...
)
通过controller获取输入框内容
print(_controller .text)

监听文本的变化

通过onChange回调
通过controller监听
_controller .addListener(() {
print(_controller .text);
});

两种方式相比,onChanged是专门用于监听文本变化,而controller的功能却多一些,除了能监听文本变化外,它还可以设置默认值、选择文本

文本选中
_controller .selection=TextSelection(
        baseOffset: 2,
        extentOffset: _controller .text.length
    );

控制焦点

这里我们就用到了focusNode

焦点可以通过FocusNode和FocusScopeNode来控制,默认情况下,焦点由FocusScope来管理,它代表焦点控制范围,可以在这个范围内可以通过FocusScopeNode在输入框之间移动焦点、设置默认焦点等。我们可以通过FocusScope.of(context) 来获取Widget树中默认的FocusScopeNode。

class FocusTestRoute extends StatefulWidget {
  @override
  _FocusTestRouteState createState() => new _FocusTestRouteState();
}

class _FocusTestRouteState extends State<FocusTestRoute> {
  FocusNode focusNode1 = new FocusNode();
  FocusNode focusNode2 = new FocusNode();
  FocusScopeNode focusScopeNode;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(16.0),
      child: Column(
        children: <Widget>[
          TextField(
            autofocus: true, 
            focusNode: focusNode1,//关联focusNode1
            decoration: InputDecoration(
                labelText: "input1"
            ),
          ),
          TextField(
            focusNode: focusNode2,//关联focusNode2
            decoration: InputDecoration(
                labelText: "input2"
            ),
          ),
          Builder(builder: (ctx) {
            return Column(
              children: <Widget>[
                RaisedButton(
                  child: Text("移动焦点"),
                  onPressed: () {
                    //将焦点从第一个TextField移到第二个TextField
                    // 这是一种写法 FocusScope.of(context).requestFocus(focusNode2);
                    // 这是第二种写法
                    if(null == focusScopeNode){
                      focusScopeNode = FocusScope.of(context);
                    }
                    focusScopeNode.requestFocus(focusNode2);
                  },
                ),
                RaisedButton(
                  child: Text("隐藏键盘"),
                  onPressed: () {
                    // 当所有编辑框都失去焦点时键盘就会收起  
                    focusNode1.unfocus();
                    focusNode2.unfocus();
                  },
                ),
              ],
            );
          },
          ),
        ],
      ),
    );
  }

}


// 监听焦点变化    
focusNode.addListener((){
   print(focusNode.hasFocus);
});

参考

Flutter实战
https://blog.csdn.net/yechaoa/article/details/90906689

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

推荐阅读更多精彩内容