代码之家  ›  专栏  ›  技术社区  ›  Jaswant Singh

在颤振[duplicate]中点击文本字段外部(屏幕上的任何位置)时隐藏屏幕键盘

  •  1
  • Jaswant Singh  · 技术社区  · 8 年前

    我正在使用 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());
    }
    
    0 回复  |  直到 9 年前
        1
  •  502
  •   Pedro Massango    6 年前

    从Flatterv1.7.8+修补程序2开始,要做的是:

    FocusScope.of(context).unfocus()
    

    Comment

    既然#31909(be75fb3)已经着陆,您应该使用 FocusScope.of(context).unfocus() 而不是 FocusScope.of(context).requestFocus(FocusNode()) 自从 FocusNode s是 ChangeNotifiers ,并应妥善处理。

    不要 ̶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̶(̶)̶)̶;̶
    
        2
  •  293
  •   cubuspl42    6 年前

    注: 这个答案已经过时了。 See the answer for newer versions of Flutter .

    TextFormField 把它送给一个没用过的人 FocusNode :

    FocusScope.of(context).requestFocus(FocusNode());
    
        3
  •  108
  •   Andrii Turkovskyi    8 年前

    使用聚焦镜的解决方案对我不起作用。 我发现了另一个:

    import 'package:flutter/services.dart';
    
    SystemChannels.textInput.invokeMethod('TextInput.hide');
    

    它解决了我的问题。

        4
  •  87
  •   suztomo    6 年前

    对于颤振1.17.3(截至2020年6月的稳定通道),使用

    FocusManager.instance.primaryFocus.unfocus();
    
        5
  •  28
  •   poonam    7 年前

    下面的代码帮助我隐藏键盘

       void initState() {
       SystemChannels.textInput.invokeMethod('TextInput.hide');
       super.initState();
       }
    
        6
  •  26
  •   Cassio Seffrin    5 年前

    FocusScope.of(context).unfocus();
    

    (上下文)的焦点范围 FocusScope.of(context).hasPrimaryFocus

        7
  •  23
  •   TomáÅ¡ Silný    6 年前

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

    FocusScope.of(context).unfocus();
    

    你可以在

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

    多亏了索普

        8
  •  21
  •   dbyuvaraj    6 年前

    对于不同的版本,看起来有不同的方法。我使用的是颤振v1.17.1,下面的内容对我很有用。

    onTap: () {
        FocusScopeNode currentFocus = FocusScope.of(context);
        if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
           currentFocus.focusedChild.unfocus();
        }
    }
    
        9
  •  20
  •   Karan Champaneri    6 年前
    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'),
        ),
      ), })
    

        10
  •  18
  •   aamitarya    7 年前

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

    弗利特暗示了这一点- 把你的小部件放进去 新的手势检测器() 哪个点击将隐藏键盘和onTap的使用 FocusScope.of(上下文).requestFocus(新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;
    }}
    
        11
  •  18
  •   Ilya Iksent    5 年前

    对我来说,上面的Listener应用程序小部件是我找到的最好的方法:

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

    这可以简化情况。只有当键盘打开时,下面的代码才能工作

    if(FocusScope.of(context).isFirstFocus) {
     FocusScope.of(context).requestFocus(new FocusNode());
    }
    
        13
  •  11
  •   Vince Varga    7 年前

    因为在Flutter中,一切都是一个小部件,所以我决定将 SystemChannels.textInput.invokeMethod('TextInput.hide'); FocusScope.of(context).requestFocus(FocusNode());

    有了这个小部件,您可以用 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 文件、小部件和mixin已准备好使用:

    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,
        );
      }
    }
    
        14
  •  9
  •   Evandro Ap. S.    7 年前

    你可以用 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());
    }
    
        15
  •  6
  •   Valentin Seehausen    6 年前

    总之,这是颤振1.17的有效解决方案:

    像这样包装您的小部件:

    GestureDetector(
            onTap: FocusScope.of(context).unfocus,
            child: YourWidget(),
    );
    
        16
  •  4
  •   9Dragons    5 年前

    如果使用CustomScrollView,只需将,

    keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
    
        17
  •  4
  •   Aykut Acikgoz    5 年前

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

    GestureDetector(
     onTap: () => FocusScope.of(context).unfocus(),
     child: child,
    );
    
        18
  •  3
  •   Amit Prajapati    7 年前
    _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>[/*...*/],
        ),
        ),
     );
    }
    
        19
  •  3
  •   Klesley Gonçalves    5 年前

    只需使用:

    Focus.of(context).unfocus();
    

    关于颤振中的所有焦点-> enter link description here

        20
  •  1
  •   Gagan Yadav    5 年前

    还可以为textfield声明一个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'),
            ),
          ),
        );
      }
    }
    
        21
  •  0
  •   AH Developer    5 年前

    FocusScope.of(context).unfocus()在与筛选的listView一起使用时有一个缺点。 除了如此多的细节和简洁,使用键盘解释器包 https://pub.dev/packages/keyboard_dismisser 将解决所有问题。

        22
  •  0
  •   Yasin Ege    4 年前

    如果您的键盘仍然无法关闭,请不要忘记将focusNode添加到TextField。上面的信息很有用,但是忘记添加focusNode让我有点困扰。这里有一个例子。

    TextField(
              focusNode: FocusNode(),
              textController: _controller,
              autoFocus: false,
              textStyle: TextStyle(fontSize: 14),
              onFieldSubmitted: (text) {},
              onChanged: (text) {},
              hint: 'Enter the code',
              hintColor: CustomColors.mediumGray,
              suffixAsset: _voucherController.text.length == 7
                  ? Assets.ic_approved_voucher
                  : null,
              isIcon: false,
              isObscure: false,
              maxLength: 7,
            )
    

    closeKeyboard(BuildContext context) {
        var currentFocus = FocusScope.of(context);
        if (!currentFocus.hasPrimaryFocus) {
          currentFocus.unfocus();
        }
      }
    
        @override
      Widget build(BuildContext context) {
        _keyboardVisible = MediaQuery.of(context).viewInsets.bottom != 0;
        size = MediaQuery.of(context).size;
        return GestureDetector(
          onTap: () {
            closeKeyboard(context);
          },
          child: Scaffold(
            backgroundColor: Colors.white,
            body: Container(
                width: double.maxFinite,
                height: double.maxFinite,
                child: _buildUI(vm)),
          ),
        );
      }
        23
  •  -1
  •   Chetan Goyal    4 年前

    尝试使用TextEditingController。 一开始,

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

    在新闻发布会上,

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