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 Jackson
sumber
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̶(̶)̶)̶;̶
Pascal
sumber
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());
Collin Jackson
sumber
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.

Andrey Turkovsky
sumber
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();
suztomo.dll
sumber
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;
}}
aamitarya
sumber
12

Kode berikut membantu saya menyembunyikan keyboard

   void initState() {
   SystemChannels.textInput.invokeMethod('TextInput.hide');
   super.initState();
   }
poonam
sumber
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

karan champaneri
sumber
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,
    );
  }
}
Vince Varga
sumber
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());
}
Evandro Ap. S.
sumber
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();
    }
}
dbyuvaraj
sumber
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>[/*...*/],
    ),
    ),
 );
}
Amit Prajapati
sumber
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.

CHANDUKA SAMARASINGHE.
sumber