如何将清除按钮添加到TextField小部件


83

是否有适当的方法向按钮添加清除按钮TextField

就像材料设计指南中的这张图片一样:

在此处输入图片说明

我发现是制定明确IconButtonInputDecorationsuffixIcon。这是正确的方法吗?

Answers:


112

输出:

在此处输入图片说明

创建一个变量

var _controller = TextEditingController();

而你的TextField

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

我想补充一下,如果将其图标的“ filled”属性设置为true,则会在文本字段后面呈现图标单击的飞溅效果。为避免这种情况,我找到的最简单的解决方案是用透明颜色的Material小部件包装IconButton并将其裁剪:ClipOval(child:Material(color:Colors.transparent,child:IconButton(...),))
Jeff S.

@JeffS。感谢您的输入。确保对答案进行
投票

63
        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


39

尝试这个 -

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

15

这是另一个回答,在@Vilokan Lab的回答上有所扩展,因为FlatButton的最小宽度为88.0,因此清除按钮根本没有与TextField右对齐,这对我而言并不是真正的事情。

因此,我继续制作自己的按钮类,并使用Stack进行了应用,这是我的过程:

按钮类:

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

为了得到这个:

未突出显示状态

在此处输入图片说明

突出显示/选定状态。

在此处输入图片说明

请注意,使用时此颜色是免费的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();
          });
        },
      ),
    ),
  ],
);

10

使用图标和清除按钮搜索TextField

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

搜索_1

搜索_2


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

                  ),
                )

6

在文本框内添加图标。您必须在Input装饰中使用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返回到后缀图标。这将为您提供onPressed事件。“ suffixIcon:IconButton(icon:Icon(Icons.arrow_back),onPressed:(){},),”
Tahseen Quraishi

4

不想走StatefulWidget路线。这是一个使用TextEditingController和StatelessWidget的示例(提供者推动更新)。我将控制器保持在静态字段中。

class _SearchBar extends StatelessWidget {
  static var _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    var dictionary = Provider.of<Dictionary>(context);

    return TextField(
        controller: _controller,
        autofocus: true,
        onChanged: (text) {
          dictionary.lookupWord = text;
        },
        style: TextStyle(fontSize: 20.0),
        decoration: InputDecoration(
            border: InputBorder.none,
            hintText: 'Search',
            suffix: GestureDetector(
              onTap: () {
                dictionary.lookupWord = '';
                _controller.clear();
              },
              child: Text('x'),
            )));
  }
}

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

1
在StackOverflow上的优良作法是添加有关解决方案为何起作用的说明。
Shree

1

这是我的代码的一部分。

它的作用:如果文本字段值不为空,则仅显示清除按钮

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

1

如果您想要一个现成的Widget,可以将其放入文件中,然后拥有一个可重用的元素,则可以通过插入ClearableTextField()在任何地方使用该代码,请使用以下代码:

import 'package:flutter/material.dart';

class ClearableTexfield extends StatefulWidget {
  ClearableTexfield({
    Key key,
    this.controller,
    this.hintText = 'Enter text'
  }) : super(key: key);

  final TextEditingController controller;
  final String hintText;

  @override
  State<StatefulWidget> createState() {
    return _ClearableTextfieldState();
  }
}

class _ClearableTextfieldState extends State<ClearableTexfield> {
  bool _showClearButton = false;

  @override
  void initState() {
    super.initState();
    widget.controller.addListener(() {
      setState(() {
        _showClearButton = widget.controller.text.length > 0;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return TextField(
      controller: widget.controller,
      decoration: InputDecoration(
        hintText: widget.hintText,
        suffixIcon: _getClearButton(),
      ),
    );
  }

  Widget _getClearButton() {
    if (!_showClearButton) {
      return null;
    }

    return IconButton(
      onPressed: () => widget.controller.clear(),
      icon: Icon(Icons.clear),
    );
  }
}

可以在此页面上找到更多说明:

https://www.flutterclutter.dev/flutter/tutorials/text-field-with-clear-button/2020/104/

它也建立在IconButton的基础上,但优点是仅当文本字段中有文本时才显示清除按钮

看起来像这样:

在此处输入图片说明


0
IconButton(
              icon: Icon(Icons.clear_all),
              tooltip: 'Close',
              onPressed: () { 
              },
            )
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.