单击外部TextField /屏幕上的任意位置后,如何在颤动中隐藏软输入键盘?

时间:2018-08-02 11:49:12

标签: dart flutter

目前,我知道通过任何小部件的onTap方法使用此代码隐藏软键盘的方法。

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

但是我想通过单击TextField外部或屏幕上的任何位置来隐藏软键盘。扑扑中有什么方法可以做到这一点?

19 个答案:

答案 0 :(得分:15)

GestureDetector中的整个屏幕换成

new Scaffold(

  body: new GestureDetector(
      onTap: () {
        // call this method here to hide soft keyboard
        FocusScope.of(context).requestFocus(new FocusNode());
      },
    child: new Container(
       -
       -
       -
        )
   )

答案 1 :(得分:9)

您的操作方式有误,只需尝试使用这种简单的方法来隐藏软键盘即可。您只需要用GestureDetector方法将整个屏幕包裹起来,然后onTap方法就可以编写此代码。

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

这是完整的示例:

new Scaffold(

body: new GestureDetector(
  onTap: () {

    FocusScope.of(context).requestFocus(new FocusNode());
  },
child: new Container(
   //rest of your code write here
    )
 )

答案 2 :(得分:5)

只是一个小注释:

如果您使用ListView,则它的keyboardDismissBehavior属性可能会引起关注:

ListView(
  keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
  children: [],
)

答案 3 :(得分:5)

如果您希望行为可以在应用程序的任何屏幕上访问,请用GestureDetector包装MaterialApp:

// main.dart
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        FocusScopeNode currentFocus = FocusScope.of(context);

        if (!currentFocus.hasPrimaryFocus) {
          currentFocus.unfocus();
        }
      },
      child: MaterialApp(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: MyHomePage(),
      ),
    );
  }
}

检查hasPrimaryFocus是必要的,以防止Flutter在试图使节点不集中在树的顶部时引发异常。

(最初由Flutter Igniter博客的James Dixon给出)

答案 4 :(得分:4)

我发现每个人都使用FocusScope.of(context).requestFocus(new FocusNode());来使文本字段失去焦点,这对我来说似乎是错误的。

IMO仅会创建一个新的无用的对象,该对象会一直挂着,直到用户点击带有“ real” FocusNode的文本字段为止。

如果您正在寻找一种“正确”的方式来实现以下目的:1)关闭键盘2)取消焦点文本字段-我可能已经找到了正确的方法:

FocusScope.of(context).detach();

Official docsdetach是安全的,即使没有焦点。


但是,如果您只想隐藏键盘而不丢失文本字段焦点(出于某种原因),则可以尝试以下操作:

import 'package:flutter/services.dart' show SystemChannels;

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

答案 5 :(得分:2)

如果焦点在 webview 内,从另一个屏幕或任何其他屏幕打开键盘,然后使用以下方式隐藏键盘

import 'package:flutter/services.dart';

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

这比添加 FocusScope.of(context).unfocus() 的解决方案更有效,因为该解决方案让我陷入了显示和隐藏键盘的循环

答案 6 :(得分:2)

最适合我。

我从 Material App 开始换行,因为全局外部接触

FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
  FocusManager.instance.primaryFocus.unfocus();
}

在下面解决,

我检查平台 iOS 只是因为 Android 可以关闭键盘后退按钮

Listener(
  onPointerUp: (_) {
    if (Platform.isIOS) {
      FocusScopeNode currentFocus = FocusScope.of(context);
      if (!currentFocus.hasPrimaryFocus &&
          currentFocus.focusedChild != null) {
        FocusManager.instance.primaryFocus.unfocus();
      }
    }
  },
  child: MaterialApp(
    debugShowCheckedModeBanner: true,
    home: MyHomePage(),
    ...
  ),
),

很高兴你的编码。

Flutter 版本

enter image description here

答案 7 :(得分:2)

这将在最新的flutter版本中工作。

GestureDetector(
  onTap: () {
    FocusScopeNode currentFocus = FocusScope.of(context);

    if (!currentFocus.hasPrimaryFocus &&
        currentFocus.focusedChild != null) {
      FocusManager.instance.primaryFocus.unfocus();
    }
  },
  child: MaterialApp(
    theme: ThemeData.dark().copyWith(
      primaryColor: Color(0xFF0A0E21),
      scaffoldBackgroundColor: Color(0xFF0A0E21),
    ),
    home: LoginUI(),
  ),
);

答案 8 :(得分:1)

我刚刚开发了一个小包装,可以为任何小部件提供您想要的行为:keyboard_dismisser on pub.dev。您可以用它包装整个页面,以便在点击任何不活动的小部件时键盘都不会被打开。

答案 9 :(得分:1)

FocusScopeNode currentFocus = FocusScope.of(context);

    if (!currentFocus.hasPrimaryFocus) {
      currentFocus.unfocus();
    }

您应该在这里https://flutterigniter.com/dismiss-keyboard-form-lose-focus/

答案 10 :(得分:1)

如果在堆栈上,请尝试

body: GestureDetector(
              onTap: () {
                FocusScope.of(context).requestFocus(new FocusNode());
              },
              child: Container(
                height: double.infinity,
                width: double.infinity,
                color: Colors.transparent,
                child: Stack(children: [
                  _CustomBody(_),
                  Positioned(
                      bottom: 15, right: 20, left: 20, child: _BotonNewList()),
                ]),
              ),
            ),

答案 11 :(得分:1)

如果您想“以正确的方式”执行此操作,请使用Listener而不是GestureDetector。

GestureDetector仅适用于“单次点击”,不能代表所有可以执行的手势。

Listener(
  onPointerDown: (_) {
    FocusScopeNode currentFocus = FocusScope.of(context);
    if (!currentFocus.hasPrimaryFocus) {
      currentFocus.focusedChild.unfocus();
    }
  },
  child: MaterialApp(...),
);

答案 12 :(得分:1)

这会起作用

 Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return GestureDetector(
  onTap: () {
    FocusScopeNode focus = FocusScope.of(context);
    if (!focus.hasPrimaryFocus && focus.focusedChild != null) {
      focus.focusedChild.unfocus();
    }
  },
  child: MaterialApp(
    title: 'Flutter Demo',

答案 13 :(得分:1)

我已经添加了这一行

behavior: HitTestBehavior.opaque,

到GestureDetector,它现在似乎正在按预期运行。

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(AppLocalizations.of(context).calculatorAdvancedStageTitle),
      ),
      body: GestureDetector(
        behavior: HitTestBehavior.opaque,
        onTap: () {
          FocusScope.of(context).requestFocus(new FocusNode());
        },
        child: Padding(
          padding: const EdgeInsets.only(
            left: 14,
            top: 8,
            right: 14,
            bottom: 8,
          ),
          child: Text('Work'),
        ),
      )
    );
  }

答案 14 :(得分:0)

maheshmnj从v1.7.8 + hotfix.2版本开始说的是正确的,您可以使用unfocus()而不是requestfocus()隐藏键盘。

FocusScope.of(context).unfocus()

但是在我的情况下,我仍然遇到很多布局错误,因为导航到的屏幕无法处理布局。

════════ Exception Caught By rendering library ═════════════════════════════════
The following JsonUnsupportedObjectError was thrown during paint():
Converting object to an encodable object failed: Infinity
When the exception was thrown, this was the stack
#0      _JsonStringifier.writeObject  (dart:convert/json.dart:647:7)
#1      _JsonStringifier.writeMap  (dart:convert/json.dart:728:7)
#2      _JsonStringifier.writeJsonValue  (dart:convert/json.dart:683:21)
#3      _JsonStringifier.writeObject  (dart:convert/json.dart:638:9)
#4      _JsonStringifier.writeList  (dart:convert/json.dart:698:9)

这是通过在接收屏幕Scaffold()

中插入“ resizeToAvoidBottomInset:false ”来解决的。
@override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,   // HERE
      appBar: AppBar(
        centerTitle: true,
        title: Text("Receiving Screen "),
      ),
      body: Container(...)
      ),
    );
  }

答案 15 :(得分:0)

onPressed: () {
    FocusScope.of(context).unfocus();
},

这对我有用。

答案 16 :(得分:0)

从Flutters最新版本v1.7.8 + hotfix.2开始,您可以使用unfocus()而不是requestfocus()隐藏键盘

FocusScope.of(context).unfocus()

因此,只要您在身体部位点击,键盘就会被隐藏

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text("Login"),
      ),
      body: GestureDetector(
        onTap: () {
          FocusScope.of(context).unfocus();
        },
        child: Container(...)
      ),
    );
  }

答案 17 :(得分:0)

这是最好的

Scaffold(
body: GestureDetector(
  onTap: () {
   if (messageFocusNode.hasFocus) {
     messageFocusNode.unfocus();
 }
},
child: new Container(
   //rest of your code write here
    )
 )

答案 18 :(得分:0)

GestureDetector(
  onTap: () {
        FocusScope.of(context).requestFocus(FocusNode());
  },
  behavior: HitTestBehavior.translucent,
  child: rootWidget
)