如何解除屏幕键盘?

时间:2017-07-09 00:44:06

标签: dart flutter

我正在使用TextFormField收集用户输入,当用户按下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());
}

25 个答案:

答案 0 :(得分:69)

你可以通过取消TextFormField的焦点并将其交给未使用的FocusNode来解雇键盘:

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

答案 1 :(得分:45)

对于Flutter 1.17.3(自2020年6月起稳定的渠道),请使用

FocusManager.instance.primaryFocus.unfocus();

答案 2 :(得分:24)

使用FocusScope解决方案对我不起作用。 我发现了另一个:

import 'package:flutter/services.dart';

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

它解决了我的问题。

答案 3 :(得分:11)

要关闭键盘(1.7.8 + hotfix.2及更高版本),只需调用以下方法:

FocusScope.of(context).unfocus();

一旦 FocusScope.of(context).unfocus()方法在关闭键盘之前已经检查是否有焦点,则不需要检查它。但如果您需要它,只需调用另一个上下文方法:FocusScope.of(context).hasPrimaryFocus

答案 4 :(得分:7)

从Flutter v1.7.8 + hotfix.2开始,方法是:

FocusScope.of(context).unfocus()

Comment关于PR的问题:

  

现在#31909(be75fb3)已着陆,您应该使用   FocusScope.of(context).unfocus()而不是   FocusScope.of(context).requestFocus(FocusNode()),因为FocusNodes是   ChangeNotifiers,应正确处理。

答案 5 :(得分:6)

在所有窗口小部件的顶部放置一个GestureDetector,并在其中onTap()的{​​{1}}中调用

gestureDetector

答案 6 :(得分:6)

对于不同的版本,似乎使用了不同的方法。我正在使用Flutter v1.17.1,以下对我有用。

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

答案 7 :(得分:5)

对于我来说,“应用程序”小部件上方的监听器是我发现的最佳方法:

Listener(
  onPointerUp: (_) {
    FocusScopeNode currentFocus = FocusScope.of(context);
    if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
      currentFocus.focusedChild.unfocus();
    }
  },
  child: MaterialApp(
    title: 'Flutter Test App',
    theme: theme,
    ...
  ),
)

答案 8 :(得分:4)

.unfocus()在滚动列表时自动隐藏键盘的示例实现

FocusScope.of(context).unfocus();

您可以找到

https://github.com/flutter/flutter/issues/36869#issuecomment-518118441

感谢szotp

答案 9 :(得分:3)

以上所有解决方案都不适合我。

Flutter建议这样做- 将您的窗口小部件放在 new GestureDetector()内,点击该按钮可隐藏键盘,然后使用 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;
}}

答案 10 :(得分:2)

如果您使用 CustomScrollView,只需输入,

keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,

答案 11 :(得分:2)

可以使用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());
}

答案 12 :(得分:2)

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

轻按手势尝试一下

答案 13 :(得分:1)

在Flutter中,一切都是小部件,因此我决定将Rectangle { id: windowBox state [ ... ] ... Component.onCompleted: { windowBox.state = ORINET } } SystemChannels.textInput.invokeMethod('TextInput.hide');方法包装在一个带有小部件和混合器的简短实用程序模块中。

使用该小部件,您可以使用FocusScope.of(context).requestFocus(FocusNode());小部件来包装任何小部件(在使用良好的IDE支持时非常方便):

KeyboardHider

使用mixin,您可以在任何交互时触发从任何状态或小部件隐藏键盘:

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, ... }, ); } } 文件,即可使用该小部件和mixin:

keyboard_hider.dart

答案 14 :(得分: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>[/*...*/],
    ),
    ),
 );
}

答案 15 :(得分:1)

总而言之,这是Flutter 1.17的可行解决方案:

这样包装您的小部件:

GestureDetector(
        onTap: FocusScope.of(context).unfocus,
        child: YourWidget(),
);

答案 16 :(得分:1)

以下代码帮助我隐藏了键盘

S

答案 17 :(得分:1)

这可以简化情况。下面的代码仅在键盘打开的情况下有效

if(FocusScope.of(context).isFirstFocus) {
 FocusScope.of(context).requestFocus(new FocusNode());
}

答案 18 :(得分:0)

尝试使用文本编辑控制器。 一开始,

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

在新闻发布活动中,

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

这将关闭键盘。

答案 19 :(得分:0)

您还可以为您的文本字段声明一个focusNode,完成后您可以在该focusNode上调用unfocus方法 并处理掉它

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

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

/// declare focus
  final FocusNode _titleFocus = FocusNode();

  @override
  void dispose() {
    _titleFocus.dispose();
  }

  @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

            _titleFocus.unfocus();
            _controller.clear();
          });
        },
      ),
      body: new Container(
        alignment: FractionalOffset.center,
        padding: new EdgeInsets.all(20.0),
        child: new TextFormField(
          controller: _controller,
          focusNode: _titleFocus,
          decoration: new InputDecoration(labelText: 'Example Text'),
        ),
      ),
    );
  }
}

答案 20 :(得分:0)

FocusScope.of(context).unfocus() 与过滤的 listView 一起使用时有一个缺点。 除了这么多细节和简洁,使用https://pub.dev/packages/keyboard_dismisser中的keyboard_dismisser包将解决所有问题。

答案 21 :(得分:0)

只需使用:

LockButton.setOnClickListener {
             if (i == 1) {
                 Toast.makeText(this@MainActivity, "Unlocked!", Toast.LENGTH_LONG).show()
                 GlobalScope.launch {
                     val url = URL(ipcomm2)
                     val con: HttpURLConnection = url.openConnection() as HttpURLConnection
                        try {
                          val `in`: InputStream = BufferedInputStream(con.inputStream)
                          `in`.read()
                        } finally {
                          con.disconnect()
                        }
                 }
                     i = 0
             }
                 else if (i == 0) {
                     Toast.makeText(this@MainActivity, "Locked!", Toast.LENGTH_LONG).show()
                     GlobalScope.launch {
                         val url2 = URL(ipcomm2)
                         val con2: HttpURLConnection = url2.openConnection() as HttpURLConnection
                             try {
                                 val inp: InputStream = BufferedInputStream(con2.inputStream)
                                 inp.read()
                             } finally {
                                 con2.disconnect()
                             }

                     }
                     i = 1
                 }
             }

关于 Flutter 中的焦点的所有信息 -> enter link description here

答案 22 :(得分:0)

这对我有用:

import 'package:flutter/services.dart';

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

答案 23 :(得分:-1)

您可以使用“GestureDetector”包装您的小部件,然后将“FocusScope.of(context).unfocus()”分配给它的 onTap 函数

GestureDetector(
 onTap: () => FocusScope.of(context).unfocus(),
 child: child,
);

答案 24 :(得分:-1)

另一种方法是使用TextFormField并设置textInputAction

TextFormField(
  textInputAction: TextInputAction.done,
  controller: textEditingController
)

键盘不会自动关闭,但用户可以使用输入操作手动关闭。