Comment puis-je ignorer le clavier à l'écran?

139

Je recueille les commentaires des utilisateurs avec un TextFormField et lorsque l'utilisateur appuie sur a pour FloatingActionButtonindiquer qu'il a terminé, je souhaite fermer le clavier à l'écran.

Comment faire disparaître automatiquement le clavier?

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
la source
Collin, La deuxième réponse de @Pascal devrait être la réponse mise à jour et corrigée.
Jack

Réponses:

227

À partir de Flutter v1.7.8 + hotfix.2, le chemin à parcourir est:

FocusScope.of(context).unfocus()

Commentez les relations publiques à ce sujet:

Maintenant que # 31909 (be75fb3) a atterri, vous devez utiliser à la FocusScope.of(context).unfocus()place de FocusScope.of(context).requestFocus(FocusNode()), car les FocusNodes sont ChangeNotifierset doivent être éliminés correctement.

-> NE PAS utiliser ̶r̶e̶q̶u̶e̶s̶t̶F̶o̶c̶u̶s̶(̶F̶o̶c̶u̶s̶N̶o̶d̶e̶(̶)̶plus.

 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
la source
1
A travaillé pour moi sur le hotfix v1.7.8 + hotfix.4
Rajesh Jr.
2
travailler pour moi, cette réponse doit être masquée comme la bonne
user3087360
@kine pouvez-vous préciser? A par documentation, c'est la façon de faire (voir api.flutter.dev/flutter/widgets/FocusNode/unfocus.html )
Pascal
@Pascal Oui, j'ai lu la documentation et cela aurait été ma solution préférée, mais dans mon application, cela ne fonctionne pas toujours (une forme assez complexe avec plusieurs TextFields et autres widgets d'édition). Je ne sais pas pourquoi mais unfocusn'a parfois aucun effet. Le remplacer par la solution acceptée (aucune autre modification) résout le problème. C'est peut-être lié à l'endroit d'où unfocusest appelé. Je dois l'appeler par exemple de CheckBoxListTile.onChangedpour ignorer le clavier lorsque l'utilisateur interagit avec un widget de case à cocher, et à partir d'autres emplacements similaires. Je ne me souviens pas de l'emplacement exact du problème.
kine le
@kine Merci pour l'explication. Donner un exemple à l'équipe Flutter serait incroyable ;-)
Pascal
207

Remarque: cette réponse est obsolète. Voir la réponse pour les nouvelles versions de Flutter .

Vous pouvez ignorer le clavier en supprimant le focus du TextFormFieldet en le donnant à un utilisateur non utilisé FocusNode:

FocusScope.of(context).requestFocus(FocusNode());
Collin Jackson
la source
Où implémenteriez-vous ce code? Dans le TextFormField; peut-être après onChanged:ou dans l'action de votre bouton personnalisé?
Charles Jr
@CharlesJr Je le fais dans l'action de mon bouton.
Duncan Jones
vous pouvez utiliser mon package si vous le souhaitez :) pub.dartlang.org/packages/keyboard_actions
diegoveloper
17
C'est avant Flutter v1.7.8 - voir la réponse stackoverflow.com/a/56946311/8696915 qui donneFocusScope.of(context).unfocus()
Richard Johnson
1
Ne faites pas cela si vous avez accès à .unfocus () car cela provoquera une fuite de mémoire. Ce nouveau FocusNode () ne sera jamais nettoyé. Voir le commentaire sur .unfocus ()
Michael Peterson
70

La solution avec FocusScope ne fonctionne pas pour moi. J'en ai trouvé un autre:

import 'package:flutter/services.dart';

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

Cela a résolu mon problème.

Andrey Turkovsky
la source
Appeler cela ne me cache pas le clavier. Devrait-il fonctionner à la fois sur Android et iOS?
Jardo
A travaillé pour moi sur iOS (12.1, iPhone 5s) et Android (Pixel 3)
Jannie Theunissen
Où mettez-vous cela? J'ai simplement essayé de l'ajouter comme premier morceau de code dans l'application et cela n'a rien fait.
Justin808
Que voulez-vous dire - "le premier bit de code"? Insérez-le dans la buildméthode par exemple.
Andrey Turkovsky
1
y a-t-il un équivalent pour cela pour le clavier numérique?
Daniel Maksimovich le
19

Pour Flutter 1.17.3 (canal stable à partir de juin 2020), utilisez

FocusManager.instance.primaryFocus.unfocus();
Suztomo
la source
12

Aucune des solutions ci-dessus ne fonctionne pour moi.

Flutter suggère ceci - Placez votre widget dans le nouveau GestureDetector () sur lequel tap masquera le clavier et onTap utilisera FocusScope.of (context) .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
la source
12

Le code suivant m'a aidé à masquer le clavier

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

essayez ceci sur le geste du robinet

Karan champaneri
la source
Merci ... a pris cette solution
Ajay Kumar
6

Comme dans Flutter, tout est un widget, j'ai décidé d'envelopper l' approche SystemChannels.textInput.invokeMethod('TextInput.hide');et l' FocusScope.of(context).requestFocus(FocusNode());approche dans un court module utilitaire avec un widget et un mixin dedans.

Avec le widget, vous pouvez envelopper n'importe quel widget (très pratique lorsque vous utilisez un bon support IDE) avec le 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(),
    );
  }
}

Avec le mixin, vous pouvez déclencher le masquage du clavier de n'importe quel état ou widget lors de toute interaction:

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

Créez simplement un keyboard_hider.dartfichier et le widget et le mixin sont prêts à être utilisés:

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
la source
4

Vous pouvez utiliser la unfocus()méthode de la FocusNodeclasse.

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.
la source
1
Salut! Il serait préférable que vous puissiez modifier votre réponse pour ajouter un peu plus de contexte à votre réponse.
grooveplex
1
La meilleure solution avec le moins de codage
Val
Oui, cela supprime le focus si vous appuyez sur un widget spécifique. Je ne peux pas l'ajouter à tous les widgets de mon application.
Dpedrinha
Taper sur un widget n'est qu'une façon d'appeler une unfocusméthode. Si vous ne voulez pas spammer cela sur votre application, vous pouvez utiliser une méthode différente, comme l' TextFormFieldévénement de changement ou un modèle réactif, cela dépend de l'architecture de votre application.
Evandro Ap. S.
4

On dirait différentes approches pour différentes versions. J'utilise Flutter v1.17.1 et ce qui suit fonctionne pour moi.

onTap: () {
    FocusScopeNode currentFocus = FocusScope.of(context);
    if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
       currentFocus.focusedChild.unfocus();
    }
}
dbyuvaraj
la source
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
la source
0

essayez d'utiliser un contrôleur d'édition de texte. au début,

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

et dans l'événement on presse,

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

cela supprimera le clavier.

CHANDUKA SAMARASINGHE.
la source