画面キーボードを閉じるにはどうすればよいですか?


137

ユーザー入力をaで収集しています。TextFormFieldユーザーがa FloatingActionButtonを押すと、それらが完了したことを示し、画面キーボードを閉じます。

キーボードを自動的に消すにはどうすればよいですか?

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

コリン、@ Pascalからの2番目の回答は、更新された修正済みの回答です。
Jack

回答:


223

Flutter v1.7.8 + hotfix.2以降、進む方法は次のとおりです。

FocusScope.of(context).unfocus()

それに関するPRについてコメントしてください:

#31909(be75fb3)が到着したので、の FocusScope.of(context).unfocus()代わりにを 使用してください 。FocusScope.of(context).requestFocus(FocusNode())FocusNodeChangeNotifiers

- > しないでください使用̶r̶e̶q̶u̶e̶s̶t̶F̶o̶c̶u̶s̶(̶F̶o̶c̶u̶s̶N̶o̶d̶e̶(̶)̶もう。

 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
hotfix v1.7.8 + hotfix.4
Rajesh Jr.

2
私のために働く、この答えは正しいものとしてマスクされなければならない
user3087360

@kineは詳しく説明してもらえますか?ドキュメントごとに、これはその方法です(api.flutter.dev/flutter/widgets/FocusNode/unfocus.htmlを参照)
Pascal

@Pascalはい私はドキュメントを読んだので、これが私の望ましい解決策でしたが、私のアプリでは常に機能するわけではありません(複数TextFieldのやその他の編集ウィジェットを含む非常に複雑なフォーム)。理由はわかりunfocusませんが、効果がない場合があります。承認済みのソリューション(他の変更なし)で置き換えると、問題が修正されます。多分それunfocusはから呼び出される場所に関連しています。たとえばCheckBoxListTile.onChanged、ユーザーがチェックボックスウィジェットを操作するときにキーボードを閉じるため、および他の同様の場所から呼び出す必要があります。問題の正確な場所を覚えていません。
キネ

@kine説明ありがとうございます。Flutterチームに例を提供するのはすばらしいことです;-)
Pascal

206

注:この回答は古くなっています。Flutterの新しいバージョンの回答をご覧ください

のフォーカスを奪いTextFormField、未使用のものに渡すことで、キーボードを閉じることができますFocusNode

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

このコードはどこに実装しますか?TextFormField; 多分onChanged:あなたのカスタムボタンの後でまたはアクションで?
Charles Jr 2017

@CharlesJr私は私のボタンのアクションでそれを行います。
ダンカンジョーンズ

あなたが望むなら私のパッケージを使うことができます:) pub.dartlang.org/packages/keyboard_actions
diegoveloper

17
回答を参照してください-これは、フラッタv1.7.8の前にあるstackoverflow.com/a/56946311/8696915与えますFocusScope.of(context).unfocus()
リチャード・ジョンソン

1
.unfocus()にアクセスできる場合は、これを行わないでください。メモリリークが発生します。その新しいFocusNode()はクリーンアップされません。.unfocus()に関するコメントを参照
Michael Peterson

70

FocusScopeを使用した解決策が機能しません。私は別のものを見つけました:

import 'package:flutter/services.dart';

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

それは私の問題を解決しました。


これを呼び出しても、キーボードは非表示になりません。AndroidとiOSの両方で動作しますか?
Jardo 2018

iOS(12.1、iPhone 5s)とAndroid(Pixel 3)で動作しました
Jannie Theunissen

これはどこに置くの?アプリの最初のコードとして追加しただけで、何も起こりませんでした。
Justin808

「コードの最初のビット」とはどういう意味ですか?buildたとえばメソッドに挿入します。
Andrey Turkovsky

1
これに相当する数字キーボードはありますか?
ダニエル・マクシモビッチ

19

Flutter 1.17.3(2020年6月の時点で安定したチャネル)の場合は、

FocusManager.instance.primaryFocus.unfocus();

12

上記の解決策はどれも私にはうまくいきません。

Flutterがこれを提案します-ウィジェットを新しいGestureDetector()内に配置し、タップするとキーボードが非表示になり、onTapで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;
}}

12

次のコードは、キーボードを非表示にするのに役立ちました

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

タップジェスチャーでこれを試してください


ありがとう...この解決策
Ajay Kumar

6

Flutterと同様に、すべてがウィジェットなので、SystemChannels.textInput.invokeMethod('TextInput.hide');FocusScope.of(context).requestFocus(FocusNode());、ウィジェットとミックスインを含む短いユーティリティモジュールにアプローチました。

ウィジェットを使用すると、ウィジェットで任意のウィジェットをラップできます(優れたIDEサポートを使用する場合に非常に便利です)KeyboardHider

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

ミックスインを使用すると、インタラクション時にキーボードを任意の状態またはウィジェットから非表示にすることができます。

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

keyboard_hider.dartファイルを作成するだけで、ウィジェットとミックスインを使用する準備が整います。

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

クラスのunfocus()メソッドを使用できますFocusNode

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
こんにちは!回答を編集して、回答にもう少しコンテキストを追加することができれば最適です。
-GroovePlex

1
最小限のコーディングで最高のソリューション
Val

はい、特定のウィジェットをタップするとフォーカスが削除されます。アプリのすべてのウィジェットに追加できません。
Dpedrinha

ウィジェットをタップすることは、unfocusメソッドを呼び出す1つの方法にすぎません。アプリでこれをスパムしたくない場合は、TextFormField変更イベントやリアクティブパターンなどの別の方法を使用できます。これはアプリのアーキテクチャによって異なります。
Evandro Ap。S.

4

バージョンごとに異なるアプローチのように見えます。Flutter v1.17.1を使用していますが、以下でうまくいきます。

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

テキスト編集コントローラーを使用してみてください。初めに、

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

オンプレスイベントでは

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

これにより、キーボードが閉じます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.