Flutter - Hide Keyboard on Tap Outside Text Field

This tutorial shows you how to hide the on-screen keyboard in Flutter when the user taps outside a text field.

A keyboard will be shown when the user is interacting with a text field. However, tapping outside a text field doesn't hide the keyboard by default. If you want to make the keyboard disappear by tapping outside, it can be done with ease. Below you can read the explanation and examples.

Hide Keyboard by Changing Focus

When a user taps on a text field, Flutter automatically changes the current focus to the tapped text field. At that time, the virtual keyboard will be shown so that the user can type on the text field. When the user clicks anywhere outside the text field, the expected behavior is the current focus is no longer set to any text field. However, Flutter doesn't change the focus automatically. Therefore, the focus is still on the last tapped text field and the keyboard remains visible. That means you have to add the code for hiding the keyboard.

To hide the keyboard, the focus should not be set to the text field. In Flutter, changing the focus can be done in various ways. One of which is using FocusManager. First, you need to get the instance of FocusManager. Then, you can get the node that has the primary focus from the primaryFocus property whose type is FocusNode. If the primaryFocus is not null, you can call the unfocus() method of the FocusNode instance. Those can be done in a single line of code as shown below.

  FocusManager.instance.primaryFocus?.unfocus()

The next question is when the code above should be executed. You need another widget that can detect the tap. For that purpose, you can use either GestureDetector or Listener.

Using GestureDetector

GestureDetector is a widget that can detect various types of gestures. You can set a callback when a particular gesture type occurs. For example, you can call the unfocus method inside a function passed as the onTap argument. The text field widget must be placed under the GestureDetector in the tree. Not only the text field, the other widgets where the tap outside could occur should be under the GestureDetector as well. Otherwise, the gesture will not be detected. Therefore, if you want to detect the tap outside anywhere including in the AppBar, the Scaffold widget has to be passed as the child argument of the GestureDetector.

  GestureDetector(
    onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
    child: Scaffold(
      appBar: AppBar(
        title: const Text('Woolha.com Flutter Tutorial'),
      ),
      body: Padding(
        padding: EdgeInsets.all(15),
        child: Center(
          child: _buildForm(),
        ),
      ),
    ),
  )

If you only use onTap like the code above, when the user performs another gesture type such as vertical drag, the gesture will not be detected unless you also pass a callback for the respective gesture. Many smartphone users have already used to tap outside in order to hide the keyboard. But if you also want to handle other gesture types, you also need to pass a callback for each gesture type. For a better understanding, you can read our tutorial about GestureDetector.

Output:

Flutter - Hide Keyboard on Tap Outside - Gesture Detector

In particular cases, if it doesn't work, you can try to change the hitTestBehavior argument of the GestureDetector to opaque.

Using Listener

Listener is a widget that calls callbacks based on the received pointer events. The usage is similar to GestureDetector. You need to pass the text field and the widgets where the tap outside events for dismissing the keyboard should be handled as the child argument of Listener. Listener can detect various pointer events. Below is an example using Listener's onTapDown callback.

  Listener(
    onPointerDown: (PointerDownEvent event) => FocusManager.instance.primaryFocus?.unfocus(),
    child: Scaffold(
      appBar: AppBar(
        title: const Text('Woolha.com Flutter Tutorial'),
      ),
      body: Padding(
        padding: EdgeInsets.all(15),
        child: Center(
          child: _buildForm(),
        ),
      ),
    ),
  );

Output:

Flutter - Hide Keyboard on Tap Outside - Listener

Full Code

  import 'package:flutter/gestures.dart';
  import 'package:flutter/material.dart';
  
  void main() => runApp(MyApp());
  
  class MyApp extends StatelessWidget {
  
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Woolha.com Flutter Tutorial',
        home: HIdeKeyboardExample(),
        debugShowCheckedModeBanner: false,
      );
    }
  }
  
  class HIdeKeyboardExample extends StatelessWidget {
  
    final _formKey = GlobalKey<FormState>();
  
    Widget _buildForm() {
      return Form(
        key: _formKey,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            TextFormField(
              key: Key('name'),
              autofillHints: [AutofillHints.name],
              decoration: InputDecoration(labelText: 'Name'),
            ),
          ],
        ),
      );
    }
  
    @override
    Widget build(BuildContext context) {
      return GestureDetector(
        onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
        onVerticalDragEnd: (DragEndDetails details) => FocusManager.instance.primaryFocus?.unfocus(),
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Woolha.com Flutter Tutorial'),
          ),
          body: Padding(
            padding: EdgeInsets.all(15),
            child: Center(
              child: _buildForm(),
            ),
          ),
        ),
      );
      // return Listener(
      //   onPointerDown: (PointerDownEvent event) => FocusManager.instance.primaryFocus?.unfocus(),
      //   child: Scaffold(
      //     appBar: AppBar(
      //       title: const Text('Woolha.com Flutter Tutorial'),
      //     ),
      //     body: Padding(
      //       padding: EdgeInsets.all(15),
      //       child: Center(
      //         child: _buildForm(),
      //       ),
      //     ),
      //   ),
      // );
    }
  }

Summary

That's how to hide the on-screen keyboard when the user taps outside a text field. You need to remove the focus from the text field when the user taps outside a text field which can be done with the help of GestureDetector or Listener.