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:
class MyHomePage extends StatefulWidget { MyHomePage({Key key, this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { final TextEditingController _textEditingController = TextEditingController(); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Align( alignment: Alignment.bottomCenter, child: Container( padding: EdgeInsets.all(16), child: _getTextField() ) ), ); } TextField _getTextField() { return TextField( controller: _textEditingController, decoration: InputDecoration( hintText: "Enter a beautiful text" ), ); } }

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:
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:
bool _showClearButton = false; @override void initState() { super.initState(); _textEditingController.addListener(() { setState(() { _showClearButton = _textEditingController.text.length > 0; }); }); } TextField _getTextField() { return TextField( controller: _textEditingController, decoration: InputDecoration( hintText: "Enter a beautiful text", suffixIcon: _getClearButton(), ), ); } Widget _getClearButton() { if (!_showClearButton) { return null; } return IconButton( onPressed: () => _textEditingController.clear(), icon: Icon(Icons.clear), ); }
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?

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