如何在TextField小部件中添加清除按钮

164

如何在TextField中添加清除按钮?就像Material设计指南中的这张图片一样:

enter image description here

我找到的方法是在InputDecorationsuffixIcon中设置一个清除IconButton。这是正确的方式吗?

17个回答

282

输出:

在此输入图像描述

创建一个变量

var _controller = TextEditingController();

还有你的TextField

TextField(
  controller: _controller,
  decoration: InputDecoration(
    hintText: 'Enter a message',
    suffixIcon: IconButton(
      onPressed: _controller.clear,
      icon: Icon(Icons.clear),
    ),
  ),
)

7
我想补充一下,如果“filled”属性设置为true,则图标点击的水波纹效果将呈现在文本字段后面。为避免这种情况,我发现最简单的解决方法是使用具有透明颜色的Material小部件将IconButton包装起来并对其进行裁剪:ClipOval( child: Material( color: Colors.transparent, child: IconButton( ... ), ), ) - Jeff S.
1
Jeff,你可以在IconButton小部件中添加属性“splashColor:Colors.transparent”。 - L. Chi
谢谢你通过_controller.clear拯救我的一天。我正在使用_controller.text = '',但不起作用。当textInputType为Number时,键盘停止向TextField中添加数字。 - Hitesh Sarsava
感谢您通过_controller.clear来拯救我的一天。我正在使用_controller.text = '',但它不起作用。当textInputType为Number时,键盘停止在文本字段中添加数字。 - undefined

83
        Container(
            margin: EdgeInsets.only(left: 16.0),
            child: TextFormField(
              controller: _username,
              decoration: InputDecoration(
                  hintText: '请输入工号',
                  filled: true,
                  prefixIcon: Icon(
                    Icons.account_box,
                    size: 28.0,
                  ),
                  suffixIcon: IconButton(
                      icon: Icon(Icons.remove),
                      onPressed: () {
                        debugPrint('222');
                      })),
            ),
          ),
使用IconButton。

2
要完成这个例子,如果文本值为空,请将颜色设置为透明: icon: Icon(Icons.cancel,color: _username.text.isNotEmpty ? Colors.grey : Colors.transparent ) - Chakib Temal
@ChakibTemal 这在 StatelessWidget 下无法工作。 - zionpi

45

试试这个 -

final TextEditingController _controller = new TextEditingController();
new Stack(
            alignment: const Alignment(1.0, 1.0),
            children: <Widget>[
              new TextField(controller: _controller,),
              new FlatButton(
                  onPressed: () {
                     _controller.clear();
                  },
                  child: new Icon(Icons.clear))
            ]
        )

6
这是错误的方法! - Anoop Thiruonam

20

这里是对@Vilokan Lab回答的进一步扩展,他的回答并没有完全解决我的问题,因为FlatButton的最小宽度为88.0,因此清除按钮并没有与TextField右对齐。

所以我自己写了一个按钮类,并使用堆栈来应用它,以下是我的流程:

按钮类:

class CircleIconButton extends StatelessWidget {
final double size;
final Function onPressed;
final IconData icon;

CircleIconButton({this.size = 30.0, this.icon = Icons.clear, this.onPressed});

@override
Widget build(BuildContext context) {
  return InkWell(
    onTap: this.onPressed,
    child: SizedBox(
        width: size,
        height: size,
        child: Stack(
          alignment: Alignment(0.0, 0.0), // all centered
          children: <Widget>[
            Container(
              width: size,
              height: size,
              decoration: BoxDecoration(
                  shape: BoxShape.circle, color: Colors.grey[300]),
            ),
            Icon(
              icon,
              size: size * 0.6, // 60% width for icon
            )
          ],
        )));
  }
}

然后将InputDecoration应用到你的TextField中,如下所示:

var myTextField = TextField(
  controller: _textController,
  decoration: InputDecoration(
      hintText: "Caption",
      suffixIcon: CircleIconButton(
        onPressed: () {
          this.setState(() {
            _textController.clear();
          });
        },
      )),
  },
);

要获得这样的效果:

未高亮状态

enter image description here

高亮/选定状态。

enter image description here

请注意,当您使用suffixIcon时,这种着色是免费的。


请注意,您还可以像这样在您的TextField中堆叠它,但是您不会获得使用suffixIcon时自动着色的效果:

var myTextFieldView = Stack(
  alignment: Alignment(1.0,0.0), // right & center
  children: <Widget>[
    TextField(
      controller: _textController,
      decoration: InputDecoration(hintText: "Caption"),
    ),
    Positioned(
      child: CircleIconButton(
        onPressed: () {
          this.setState(() {
            _textController.clear();
          });
        },
      ),
    ),
  ],
);

20

带图标和清除按钮的搜索文本框

import 'package:flutter/material.dart';

  class SearchTextField extends StatefulWidget{
    @override
    State<StatefulWidget> createState() {
      // TODO: implement createState
      return new SearchTextFieldState();
    }
  }

  class SearchTextFieldState extends State<SearchTextField>{
    final TextEditingController _textController = new TextEditingController();

    @override
    Widget build(BuildContext context) {
      // TODO: implement build
      return new Row(children: <Widget>[
        new Icon(Icons.search, color: _textController.text.length>0?Colors.lightBlueAccent:Colors.grey,),
        new SizedBox(width: 10.0,),
        new Expanded(child: new Stack(
            alignment: const Alignment(1.0, 1.0),
            children: <Widget>[
              new TextField(
                decoration: InputDecoration(hintText: 'Search'),
                onChanged: (text){
                  setState(() {
                    print(text);
                  });
                },
                controller: _textController,),
              _textController.text.length>0?new IconButton(icon: new Icon(Icons.clear), onPressed: () {
                setState(() {
                  _textController.clear();
                });
              }):new Container(height: 0.0,)
            ]
        ),),
      ],);
    }
  }

search_1

search_2


好的观点,没有人在得到赞同的答案中提到清除按钮应该只在用户输入时显示。 - Rafik EL YAAGOUBI
正是我想要的。 - Rohan Arora
确切地说,这正是我想要的。 - undefined

10

TextEditingController 用于检查文本框的当前状态,我们可以根据文本框是否有内容来决定是否显示取消图标。

  var _usernameController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Center(
          child: TextField(
            controller: _usernameController,
            onChanged: (text) {
              setState(() {});
            },
            decoration: InputDecoration(
                labelText: 'Username',
                suffixIcon: _usernameController.text.length > 0
                    ? IconButton(
                        onPressed: () {
                          _usernameController.clear();
                          setState(() {});
                        },
                        icon: Icon(Icons.cancel, color: Colors.grey))
                    : null),
          ),
        ),
      ),
    );
  }

输出:

enter image description here


8
TextFormField(
                  controller:_controller
                  decoration: InputDecoration(
                    suffixIcon: IconButton(
                      onPressed: (){
                        _controller.clear();
                      },
                      icon: Icon(
                      Icons.keyboard,
                      color: Colors.blue,
                    ),
                    ),

                  ),
                )

8
这里是我的代码片段,它能正常运行。
功能:仅在文本字段值不为空时显示清除按钮。
class _MyTextFieldState extends State<MyTextField> {
  TextEditingController _textController;
  bool _wasEmpty;

  @override
  void initState() {
    super.initState();
    _textController = TextEditingController(text: widget.initialValue);
    _wasEmpty = _textController.text.isEmpty;
    _textController.addListener(() {
      if (_wasEmpty != _textController.text.isEmpty) {
        setState(() => {_wasEmpty = _textController.text.isEmpty});
      }
    });
  }

  @override
  void dispose() {
    _textController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return TextFormField(
          controller: _textController,
          decoration: InputDecoration(
            labelText: widget.label,
            suffixIcon: _textController.text.isNotEmpty
                ? Padding(
                    padding: const EdgeInsetsDirectional.only(start: 12.0),
                    child: IconButton(
                      iconSize: 16.0,
                      icon: Icon(Icons.cancel, color: Colors.grey,),
                      onPressed: () {
                        setState(() {
                          _textController.clear();
                        });
                      },
                    ),
                  )
                : null,
          ),);
...

这很简单,而且只是起作用。 - Charles

7
TextField(
  decoration: InputDecoration(
    suffixIcon: IconButton(
      icon: Icon(
        Icons.cancel,
      ),
      onPressed: () {
        _controllerx.text = '';
      }
    ),
  )
)

3
在StackOverflow上,给出解决方案的同时,附带解释为什么这个方案可行是一个好习惯。 - 4b0

6

要在文本框中添加图标,您必须在输入装饰内使用 suffixIcon 或 prefixIcon。

TextFormField(
    autofocus: false,
    obscureText: true,
    decoration: InputDecoration(
       labelText: 'Password',
       suffixIcon: Icon(
                    Icons.clear,
                    size: 20.0,
                  ),
       border: OutlineInputBorder(
       borderRadius: BorderRadius.all(Radius.circular(0.0)),
     ),
      hintText: 'Enter Password',
      contentPadding: EdgeInsets.all(10.0),
    ),
  );

1
如何检测图标的点击以清除整个文本?通过实现onTap来检测点击,但不重新绘制视图。需要调用setState(),但找不到方法。 - Hitesh Dhamshaniya
1
你可以将IconButton返回给suffixicon。这将为您提供onPressed事件。 "suffixIcon: IconButton( icon: Icon(Icons.arrow_back), onPressed: () { }, )," - Tahseen Quraishi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接