Wie kann ich die Bildschirmtastatur schließen?


136

Ich sammle Benutzereingaben mit a TextFormFieldund wenn der Benutzer eine drückt FloatingActionButton, um anzuzeigen, dass sie fertig sind, möchte ich die Bildschirmtastatur schließen.

Wie kann ich die Tastatur automatisch ausschalten lassen?

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, Die zweite Antwort von @Pascal sollte die aktualisierte, korrigierte Antwort sein.
Jack

Antworten:


220

Ab Flutter v1.7.8 + hotfix.2 ist der richtige Weg:

FocusScope.of(context).unfocus()

Kommentar zu PR dazu:

Nachdem # 31909 (be75fb3) gelandet ist, sollten Sie FocusScope.of(context).unfocus()anstelle von verwenden FocusScope.of(context).requestFocus(FocusNode()), da FocusNodes sind ChangeNotifiersund ordnungsgemäß entsorgt werden sollten.

-> NICHT verwenden ̶r̶e̶q̶u̶e̶s̶t̶F̶o̶c̶u̶s̶(̶F̶o̶c̶u̶s̶N̶o̶d̶e̶(̶)̶mehr.

 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
Arbeitete für mich an Hotfix v1.7.8 + Hotfix.4
Rajesh Jr.

2
Arbeit für mich, diese Antwort sollte als die richtige maskiert werden
user3087360

@kine kannst du das bitte näher erläutern? Laut Dokumentation ist dies der richtige Weg (siehe api.flutter.dev/flutter/widgets/FocusNode/unfocus.html )
Pascal

@Pascal Ja, ich habe die Dokumentation gelesen und dies wäre meine bevorzugte Lösung gewesen, aber in meiner App funktioniert es nicht immer (ein recht komplexes Formular mit mehreren TextFields und anderen Bearbeitungs-Widgets). Ich weiß nicht warum, unfocushat aber manchmal keine Wirkung. Das Ersetzen durch die akzeptierte Lösung (keine weiteren Änderungen) behebt das Problem. Vielleicht hängt es mit dem Ort zusammen, von dem aus unfocusangerufen wird. Ich muss es z. B. von aufrufen CheckBoxListTile.onChanged, um die Tastatur zu schließen, wenn der Benutzer mit einem Kontrollkästchen-Widget interagiert, und von anderen ähnlichen Orten aus. Ich erinnere mich nicht an den genauen Ort des Problems.
Kine

@kine Danke für die Erklärung. Es wäre erstaunlich, dem Flutter-Team ein Beispiel zu geben ;-)
Pascal

206

Hinweis: Diese Antwort ist veraltet. Siehe die Antwort für neuere Versionen von Flutter .

Sie können die Tastatur schließen, indem Sie den Fokus der Tastatur entfernen TextFormFieldund sie einer nicht verwendeten Tastatur geben FocusNode:

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

Wo würden Sie diesen Code implementieren? Im TextFormField; Vielleicht nach onChanged:oder in der Aktion Ihrer benutzerdefinierten Schaltfläche?
Charles Jr

@CharlesJr Ich mache es in der Aktion meiner Taste.
Duncan Jones

Sie können mein Paket verwenden, wenn Sie möchten :) pub.dartlang.org/packages/keyboard_actions
diegoveloper

17
Dies ist vor Flutter v1.7.8 - siehe Antwort stackoverflow.com/a/56946311/8696915, die gibtFocusScope.of(context).unfocus()
Richard Johnson

1
Tun Sie dies nicht, wenn Sie Zugriff auf .unfocus () haben, da dies zu einem Speicherverlust führen kann. Dieser neue FocusNode () wird niemals aufgeräumt. Siehe Kommentar zu .unfocus ()
Michael Peterson

69

Die Lösung mit FocusScope funktioniert bei mir nicht. Ich habe einen anderen gefunden:

import 'package:flutter/services.dart';

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

Es hat mein Problem gelöst.


Wenn ich das anrufe, wird die Tastatur für mich nicht ausgeblendet. Sollte es sowohl auf Android als auch auf iOS funktionieren?
Jardo

Arbeitete für mich auf iOS (12.1, iPhone 5s) und Android (Pixel 3)
Jannie Theunissen

Wo legst du das hin? Ich habe versucht, es nur als erstes Stück Code in der App hinzuzufügen, und es hat nichts getan.
Justin808

Was meinst du - "das erste Stück Code"? Fügen Sie es buildzum Beispiel in die Methode ein.
Andrey Turkovsky

1
Gibt es dafür ein Äquivalent für das numerische Tastenfeld?
Daniel Maksimovich

18

Verwenden Sie für Flutter 1.17.3 (stabiler Kanal ab Juni 2020)

FocusManager.instance.primaryFocus.unfocus();

12

Keine der oben genannten Lösungen funktioniert bei mir nicht.

Flutter schlägt dies vor - Legen Sie Ihr Widget in einen neuen GestureDetector (), auf dem durch Tippen die Tastatur ausgeblendet wird, und onTap verwenden Sie FocusScope.of (Kontext) .requestFocus (neuer 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

Der folgende Code hat mir geholfen, die Tastatur auszublenden

   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'),
    ),
  ), })

Versuchen Sie dies mit einer Tippgeste


Danke ... nahm diese Lösung
Ajay Kumar

6

Da in Flutter alles ein Widget ist, habe ich beschlossen, das SystemChannels.textInput.invokeMethod('TextInput.hide');und das zu verpackenFocusScope.of(context).requestFocus(FocusNode()); Ansatz in ein kurzes Dienstprogrammmodul mit einem Widget und einem Mixin zu packen.

Mit dem Widget können Sie jedes Widget (sehr praktisch bei Verwendung einer guten IDE-Unterstützung) mit dem KeyboardHiderWidget umschließen:

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

Mit dem Mixin können Sie auslösen, dass die Tastatur bei jeder Interaktion vor einem beliebigen Status oder Widget versteckt wird:

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

Erstellen Sie einfach eine keyboard_hider.dartDatei und das Widget und das Mixin können verwendet werden:

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

Sie können eine unfocus()Methode aus der FocusNodeKlasse verwenden.

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
Hallo! Es wäre am besten, wenn Sie Ihre Antwort bearbeiten könnten, um Ihrer Antwort nur ein wenig mehr Kontext hinzuzufügen.
Grooveplex

1
Die beste Lösung mit der geringsten Menge an Codierung
Val

Ja, der Fokus wird entfernt, wenn Sie auf ein bestimmtes Widget tippen. Ich kann es nicht jedem Widget in meiner App hinzufügen.
Dpedrinha

Das Tippen auf ein Widget ist nur eine Möglichkeit, die unfocusMethode aufzurufen . Wenn Sie dies nicht in Ihrer App als Spam versenden möchten, können Sie eine andere Methode verwenden, z. B. das TextFormFieldÄnderungsereignis oder ein reaktives Muster. Dies hängt von der Architektur Ihrer App ab.
Evandro Ap. S.

4

Sieht nach unterschiedlichen Ansätzen für unterschiedliche Versionen aus. Ich verwende Flutter v1.17.1 und das Folgende funktioniert für mich.

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

Versuchen Sie es mit einem Textbearbeitungs-Controller. am Anfang,

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

und in der On-Press-Veranstaltung,

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

Dadurch wird das Keybord geschlossen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.