When developing native pages, there is usually a requirement to hide the keyboard by clicking on the screen outside the input field. This requirement also needs to be implemented on Flutter.

The way to do this on Android is to implement event distribution in the base Activity class to determine whether the touch position is in the input box.

  /** * get the click event */
    @CallSuper
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.MotionEvent ) {
            View view = getCurrentFocus();
            if(isShouldHideKeyBord(view, ev)) { hideSoftInput(view.getWindowToken()); }}return super.dispatchTouchEvent(ev);
    }

    /** * Determine if you need to hide */
    protected boolean isShouldHideKeyBord(View v, MotionEvent ev) {
        if(v ! =null && (v instanceof EditText)) {
            int[] l = {0.0};
            v.getLocationInWindow(l);
            int left = l[0], top = l[1], bottom = top + v.getHeight(), right = left + v.getWidth();
            return! (ev.getX() > left && ev.getX() < right && ev.getY() > top && ev.getY() < bottom); }return false;
    }

    /** ** hide the soft keyboard */
    private void hideSoftInput(IBinder token) {
        if(token ! =null) { InputMethodManager manager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); manager.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS); }}Copy the code

So how does that happen with Flutter?

Many articles do this by wrapping the GestureDetector in each screen containing TextField and manually controlling the Focus. Once you lose focus, request that the keyboard be turned off. This is a temporary solution, error-prone, and generates a lot of code.

GestureDetector(
    behavior: HitTestBehavior.translucent,
    onTap: () {
        // Touch the keyboard
        FocusScope.of(context).requestFocus(FocusNode());
    },
    child: *******
}

Copy the code

Usually this requirement is for the entire app. Is there a way to fix it once and for all? Of course, we can use the MaterialApp’s Builder method to insert widgets above the Navigator but below the other widgets, adding only a “global” GestureDetector that will handle keyboard closing for us:

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      builder: (context, child) => Scaffold(
        // Global GestureDetector that will dismiss the keyboard
        body: GestureDetector(
          onTap: () {
         hideKeyboard(context);
          },
          child: child,
        ),
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page')); }void hideKeyboard(BuildContext context) {
    FocusScopeNode currentFocus = FocusScope.of(context);
    if(! currentFocus.hasPrimaryFocus && currentFocus.focusedChild ! =null) { FocusManager.instance.primaryFocus.unfocus(); }}}Copy the code

You can also use the following method to close the keyboard:

SystemChannels. (. InvokeMethod ('TextInput.hide');Copy the code

This is global control, no longer need to write on every page.