Bagaimana cara menutup keyboard di layar?


139

Saya mengumpulkan input pengguna dengan a TextFormFielddan ketika pengguna menekan tanda FloatingActionButtonbahwa mereka sudah selesai, saya ingin menutup keyboard di layar.

Bagaimana cara membuat keyboard hilang secara otomatis?

import 'package:flutter/material.dart';

class MyHomePage extends StatefulWidget {
  MyHomePageState createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  TextEditingController _controller = new TextEditingController();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.send),
        onPressed: () {
          setState(() {
            // send message
            // dismiss on screen keyboard here
            _controller.clear();
          });
        },
      ),
      body: new Container(
        alignment: FractionalOffset.center,
        padding: new EdgeInsets.all(20.0),
        child: new TextFormField(
          controller: _controller,
          decoration: new InputDecoration(labelText: 'Example Text'),
        ),
      ),
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

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

Collin, Jawaban kedua dari @Pascal harus menjadi jawaban yang diperbarui dan dikoreksi.
Jack

Jawaban:


226

Pada Flutter v1.7.8 + hotfix.2, cara yang harus dilakukan adalah:

FocusScope.of(context).unfocus()

Komentar PR tentang itu:

Sekarang # 31909 (be75fb3) telah mendarat, Anda harus menggunakan FocusScope.of(context).unfocus()bukan FocusScope.of(context).requestFocus(FocusNode()), karena FocusNodes adalah ChangeNotifiers, dan harus dibuang dengan benar.

-> JANGAN gunakan ̶r̶e̶q̶u̶e̶s̶t̶F̶o̶c̶u̶s̶(̶F̶o̶c̶u̶s̶N̶o̶d̶e̶(̶)̶lagi.

 F̶o̶c̶u̶s̶S̶c̶o̶p̶e̶.̶o̶f̶(̶c̶o̶n̶t̶e̶x̶t̶)̶.̶r̶e̶q̶u̶e̶s̶t̶F̶o̶c̶u̶s̶(̶F̶o̶c̶u̶s̶N̶o̶d̶e̶(̶)̶)̶;̶

1
Bekerja untuk saya di hotfix v1.7.8 + hotfix.4
Rajesh Jr.

2
bekerja untuk saya, jawaban ini harus disamarkan sebagai jawaban yang benar
user3087360

@kine bisakah kamu menjelaskan? A per dokumentasi, ini adalah cara untuk melakukannya (lihat api.flutter.dev/flutter/widgets/FocusNode/unfocus.html )
Pascal

@Pascal Ya, saya telah membaca dokumentasi dan ini akan menjadi solusi pilihan saya, tetapi di aplikasi saya itu tidak selalu berfungsi (bentuk yang cukup kompleks dengan beberapa TextFieldwidget dan edit lainnya). Saya tidak tahu kenapa tapi kadang unfocustidak berpengaruh. Menggantinya dengan solusi yang diterima (tidak ada perubahan lain) akan memperbaiki masalah. Mungkin itu terkait dengan lokasi asal unfocuspanggilan. Saya perlu menyebutnya misalnya dari CheckBoxListTile.onChangeduntuk menutup keyboard saat pengguna berinteraksi dengan widget kotak centang, dan dari lokasi serupa lainnya. Saya tidak ingat persis lokasi masalah.
kine

@kine Terima kasih atas penjelasannya. Memberikan contoh kepada tim Flutter akan luar biasa ;-)
Pascal

207

Catatan: Jawaban ini sudah ketinggalan zaman. Lihat jawabannya untuk Flutter versi terbaru .

Anda dapat menutup keyboard dengan menghilangkan fokus TextFormFielddan memberikannya ke yang tidak digunakan FocusNode:

FocusScope.of(context).requestFocus(FocusNode());

Di mana Anda akan menerapkan kode ini? Di TextFormField; mungkin setelah onChanged:atau dalam tindakan tombol kustom Anda?
Charles Jr

@CharlesJr Saya melakukannya dalam aksi tombol saya.
Duncan Jones

Anda dapat menggunakan paket saya jika Anda mau :) pub.dartlang.org/packages/keyboard_actions
diegoveloper

17
Ini sebelum Flutter v1.7.8 - lihat jawaban stackoverflow.com/a/56946311/8696915 yang memberikanFocusScope.of(context).unfocus()
Richard Johnson

1
Jangan lakukan ini jika Anda memiliki akses ke .unfocus () karena itu akan menyebabkan kebocoran memori. FocusNode () baru itu tidak akan pernah dibersihkan. Lihat komentar tentang .unfocus ()
Michael Peterson

70

Solusi dengan FocusScope tidak berhasil untuk saya. Saya menemukan yang lain:

import 'package:flutter/services.dart';

SystemChannels.textInput.invokeMethod('TextInput.hide');

Itu memecahkan masalah saya.


Memanggil ini tidak menyembunyikan keyboard untuk saya. Haruskah itu berfungsi di Android dan iOS?
Jardo

Bekerja untuk saya di iOS (12.1, iPhone 5s) dan Android (Pixel 3)
Jannie Theunissen

Di mana kamu meletakkan ini? Saya hanya mencoba menambahkannya sebagai bit pertama kode di aplikasi dan tidak melakukan apa-apa.
Justin808

Apa maksud Anda - "bit pertama dari kode"? Sisipkan dalam buildmetode misalnya.
Andrey Turkovsky

1
apakah ada padanan untuk ini untuk keybaord numerik?
Daniel Maksimovich

19

Untuk Flutter 1.17.3 (saluran stabil per Juni 2020), gunakan

FocusManager.instance.primaryFocus.unfocus();

12

Tidak ada solusi di atas yang tidak berhasil untuk saya.

Flutter menyarankan ini - Letakkan widget Anda di dalam GestureDetector baru () di mana ketukan akan menyembunyikan keyboard dan onTap menggunakan FocusScope.of (konteks) .requestFocus (new FocusNode ())

class Home extends StatelessWidget {
@override
  Widget build(BuildContext context) {
    var widget = new MaterialApp(
        home: new Scaffold(
            body: new Container(
                height:500.0,
                child: new GestureDetector(
                    onTap: () {
                        FocusScope.of(context).requestFocus(new FocusNode());
                    },
                    child: new Container(
                        color: Colors.white,
                        child:  new Column(
                            mainAxisAlignment:  MainAxisAlignment.center,
                            crossAxisAlignment: CrossAxisAlignment.center,

                            children: [
                                new TextField( ),
                                new Text("Test"),                                
                            ],
                        )
                    )
                )
            )
        ),
    );

    return widget;
}}

12

Kode berikut membantu saya menyembunyikan keyboard

   void initState() {
   SystemChannels.textInput.invokeMethod('TextInput.hide');
   super.initState();
   }


8
GestureDetector(
          onTap: () {
            FocusScope.of(context).unfocus();
          },
          child:Container(
    alignment: FractionalOffset.center,
    padding: new EdgeInsets.all(20.0),
    child: new TextFormField(
      controller: _controller,
      decoration: new InputDecoration(labelText: 'Example Text'),
    ),
  ), })

coba ini pada gerakan ketuk


Terima kasih ... mengambil solusi ini
Ajay Kumar

6

Karena di Flutter semuanya adalah widget, saya memutuskan untuk membungkus SystemChannels.textInput.invokeMethod('TextInput.hide');dan FocusScope.of(context).requestFocus(FocusNode());pendekatan dalam modul utilitas singkat dengan widget dan mixin di dalamnya.

Dengan widget, Anda dapat menggabungkan widget apa pun (sangat nyaman jika menggunakan dukungan IDE yang bagus) dengan KeyboardHiderwidget:

class SimpleWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return KeyboardHider(
      /* Here comes a widget tree that eventually opens the keyboard,
       * but the widget that opened the keyboard doesn't necessarily
       * takes care of hiding it, so we wrap everything in a
       * KeyboardHider widget */
      child: Container(),
    );
  }
}

Dengan mixin, Anda dapat memicu persembunyian keyboard dari status atau widget apa pun pada interaksi apa pun:

class SimpleWidget extends StatefulWidget {
  @override
  _SimpleWidgetState createState() => _SimpleWidgetState();
}

class _SimpleWidgetState extends State<SimpleWidget> with KeyboardHiderMixin {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        // Hide the keyboard:
        hideKeyboard();
        // Do other stuff, for example:
        // Update the state, make an HTTP request, ...
      },
    );
  }
}

Cukup buat keyboard_hider.dartfile dan widget dan mixin siap digunakan:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

/// Mixin that enables hiding the keyboard easily upon any interaction or logic
/// from any class.
abstract class KeyboardHiderMixin {
  void hideKeyboard({
    BuildContext context,
    bool hideTextInput = true,
    bool requestFocusNode = true,
  }) {
    if (hideTextInput) {
      SystemChannels.textInput.invokeMethod('TextInput.hide');
    }
    if (context != null && requestFocusNode) {
      FocusScope.of(context).requestFocus(FocusNode());
    }
  }
}

/// A widget that can be used to hide the text input that are opened by text
/// fields automatically on tap.
///
/// Delegates to [KeyboardHiderMixin] for hiding the keyboard on tap.
class KeyboardHider extends StatelessWidget with KeyboardHiderMixin {
  final Widget child;

  /// Decide whether to use
  /// `SystemChannels.textInput.invokeMethod('TextInput.hide');`
  /// to hide the keyboard
  final bool hideTextInput;
  final bool requestFocusNode;

  /// One of hideTextInput or requestFocusNode must be true, otherwise using the
  /// widget is pointless as it will not even try to hide the keyboard.
  const KeyboardHider({
    Key key,
    @required this.child,
    this.hideTextInput = true,
    this.requestFocusNode = true,
  })  : assert(child != null),
        assert(hideTextInput || requestFocusNode),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      behavior: HitTestBehavior.opaque,
      onTap: () {
        hideKeyboard(
          context: context,
          hideTextInput: hideTextInput,
          requestFocusNode: requestFocusNode,
        );
      },
      child: child,
    );
  }
}

4

Anda dapat menggunakan unfocus()metode dari FocusNodekelas.

import 'package:flutter/material.dart';

class MyHomePage extends StatefulWidget {
  MyHomePageState createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  TextEditingController _controller = new TextEditingController();
  FocusNode _focusNode = new FocusNode(); //1 - declare and initialize variable

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.send),
        onPressed: () {
            _focusNode.unfocus(); //3 - call this method here
        },
      ),
      body: new Container(
        alignment: FractionalOffset.center,
        padding: new EdgeInsets.all(20.0),
        child: new TextFormField(
          controller: _controller,
          focusNode: _focusNode, //2 - assign it to your TextFormField
          decoration: new InputDecoration(labelText: 'Example Text'),
        ),
      ),
    );
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

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

1
Hai! Akan lebih baik jika Anda dapat mengedit jawaban Anda untuk menambahkan lebih banyak konteks pada jawaban Anda.
grooveplex

1
Solusi terbaik dengan jumlah pengkodean paling sedikit
Val

Ya, ini menghilangkan fokus jika mengetuk widget tertentu. Tidak dapat menambahkannya ke setiap widget di aplikasi saya.
Dpedrinha

Mengetuk widget hanyalah salah satu cara untuk memanggil unfocusmetode. Jika Anda tidak ingin melakukan spam ini di aplikasi Anda, Anda dapat menggunakan cara lain, seperti TextFormFieldperistiwa perubahan atau pola reaktif, itu tergantung pada arsitektur aplikasi Anda.
Evandro Ap. S.

4

Sepertinya pendekatan berbeda untuk versi berbeda. Saya menggunakan Flutter v1.17.1 dan yang di bawah ini berfungsi untuk saya.

onTap: () {
    FocusScopeNode currentFocus = FocusScope.of(context);
    if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
       currentFocus.focusedChild.unfocus();
    }
}

1
_dismissKeyboard(BuildContext context) {
   FocusScope.of(context).requestFocus(new FocusNode());
}

@override
Widget build(BuildContext context) {

return new GestureDetector(
    onTap: () {
    this._dismissKeyboard(context);
    },
    child: new Container(
    color: Colors.white,
    child: new Column(
        children: <Widget>[/*...*/],
    ),
    ),
 );
}

0

coba gunakan pengontrol pengeditan teks. di awal,

    final myController = TextEditingController();
     @override
  void dispose() {
    // Clean up the controller when the widget is disposed.
    myController.dispose();
    super.dispose();
  }

dan di acara pers,

onPressed: () {
            commentController.clear();}

ini akan menutup keybord.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.