Hey there 😊

If you like what you read, feel free to …

🥗Buy me a salad
Share this 💬

Text field: Add trailing clear button

Text field: Add trailing clear button

The typical app user is used to having the possibility to clear the whole text inside of a text field with one tap. Both iOS and Android natively display a respective button at the end of the text field whenever the user starts typing.

This functionality is not mandatory and so Flutter does not provide it to TextFields by default but makes it very easy to implement it.

Let’s setup a simple app with a TextField at the bottom:

 1class MyHomePage extends StatefulWidget {
 2  MyHomePage({Key key, this.title}) : super(key: key);
 3  final String title;
 4
 5  @override
 6  _MyHomePageState createState() => _MyHomePageState();
 7}
 8
 9class _MyHomePageState extends State<MyHomePage> {
10  final TextEditingController _textEditingController = TextEditingController();
11
12  @override
13  Widget build(BuildContext context) {
14      return Scaffold(
15        appBar: AppBar(
16        title: Text(widget.title),
17      ),
18        body: Align(
19          alignment: Alignment.bottomCenter,
20          child: Container(
21            padding: EdgeInsets.all(16),
22            child: _getTextField()
23          )
24        ),
25      );
26    }
27
28  TextField _getTextField() {
29    return TextField(
30      controller: _textEditingController,
31      decoration: InputDecoration(
32        hintText: "Enter a beautiful text"
33      ),
34    );
35  }
36}
Screen with a single TextField at the bottom
An app with a single TextField

It gives us this simple screen.

In order to display something that’s located at the end of the TextField, we can use the suffixIcon argument of the widget. The title is misleading to a certain degree as it’s not necessarily an icon. In fact, the expected type is a Widget. So we’re not limited in any way:

In Flutter, everything's a `Widget`
In Flutter, everything’s a Widget

Show it only when there’s text

That also enables us to easily show the button only under certain conditions. In this case: when the text field is not empty:

 1bool _showClearButton = false;
 2
 3@override
 4void initState() {
 5  super.initState();
 6  _textEditingController.addListener(() {
 7    setState(() {
 8      _showClearButton = _textEditingController.text.length > 0;
 9    });
10  });
11}
12
13TextField _getTextField() {
14  return TextField(
15    controller: _textEditingController,
16    decoration: InputDecoration(
17      hintText: "Enter a beautiful text",
18      suffixIcon: _getClearButton(),
19    ),
20  );
21}
22
23Widget _getClearButton() {
24  if (!_showClearButton) {
25    return null;
26  }
27
28  return IconButton(
29    onPressed: () => _textEditingController.clear(),
30    icon: Icon(Icons.clear),
31  );
32}

So what I did:

  • I added a variable _showClearButton that’s storing whether the clear button is to be shown or not
  • In the setState() method I attached a listener to the controller of the TextField that updates the above mentioned value once there was a change
  • Lastly, I created a method that returns a button. If _showClearButton is false, it returns null, resulting in the button not being displayed. Otherwise, the button is displayed. onPressed has a function assigned to clear the text

What does it look like?

Animation showing TextField with clear button in action
TextField with clear button in action

As a standalone Widget

If you want a standalone Widget which you can use everywhere by typing ClearableTextfield(), use this piece of code and ideally put it in a separate file called clearable_textfield.dart:

 1import 'package:flutter/material.dart';
 2
 3class ClearableTexfield extends StatefulWidget {
 4  ClearableTexfield({
 5    Key key,
 6    this.controller,
 7    this.hintText = 'Enter text'
 8  }) : super(key: key);
 9
10  final TextEditingController controller;
11  final String hintText;
12
13  @override
14  State<StatefulWidget> createState() {
15    return _ClearableTextfieldState();
16  }
17}
18
19class _ClearableTextfieldState extends State<ClearableTexfield> {
20  bool _showClearButton = false;
21
22  @override
23  void initState() {
24    super.initState();
25    widget.controller.addListener(() {
26      setState(() {
27        _showClearButton = widget.controller.text.length > 0;
28      });
29    });
30  }
31
32  @override
33  Widget build(BuildContext context) {
34    return TextField(
35      controller: widget.controller,
36      decoration: InputDecoration(
37        hintText: widget.hintText,
38        suffixIcon: _getClearButton(),
39      ),
40    );
41  }
42
43  Widget _getClearButton() {
44    if (!_showClearButton) {
45      return null;
46    }
47
48    return IconButton(
49      onPressed: () => widget.controller.clear(),
50      icon: Icon(Icons.clear),
51    );
52  }
53}

Comment this 🤌

You are replying to 's commentRemove reference