如何在Flutter中点击TextField/屏幕其他位置后隐藏软键盘?

204

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

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

我想通过在TextField之外的任何地方点击或屏幕上的任何位置来隐藏软键盘。 在Flutter中是否有任何方法可以实现这一点?


但是,我希望通过在TextField之外的任何地方点击或屏幕上的任何位置来隐藏软键盘。 Flutter中是否有任何方法可以实现这一点?

3
您可以将整个屏幕用https://docs.flutter.io/flutter/widgets/GestureDetector-class.html包裹起来,然后在“onTap: () => FocusScope.of(context).requestFocus(new FocusNode());”中调用上面的代码。 - Günter Zöchbauer
1
感谢 @GünterZöchbauer。是否有触摸事件方法,因为轻按不会解决我的问题。键盘在 onTap 方法中隐藏。我需要经常隐藏键盘,因为我触摸屏幕。 - Ammy Kang
我正在使用TabBar,并在每个选项卡屏幕上拥有搜索视图框。当我从一个选项卡滑动到另一个选项卡时,如果屏幕上有键盘或者SearchView的TextField中有文本,则不会滑动到另一个选项卡,而是返回到相同的选项卡。主要是在键盘弹出时存在选项卡滑动问题,否则选项卡滑动正常。 - Ammy Kang
我该如何添加“Listener”小部件,你能给个例子吗? - Ammy Kang
2
MaterialApp( builder: (context, child) => GestureDetector( onTap: (){ FocusManager.instance.primaryFocus?.unfocus(); }, child: child, )) - Avnish Nishad
显示剩余6条评论
29个回答

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

7
这将在最新的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(),
  ),
);

5
child: Form(
    child: Column(
        children: [
            TextFormField(
                decoration: InputDecoration(
                        labelText: 'User Name', hintText: 'User Name'),
                onTapOutside: (PointerDownEvent event) {
                    FocusScope.of(context).requestFocus(_unUsedFocusNode);
                },
            ),
        ],
    ),
),

定义焦点节点。

FocusNode _unUsedFocusNode = FocusNode();

在TextFromField中重写onTapOutside方法

onTapOutside: (PointerDownEvent event) {
  FocusScope.of(context).requestFocus(_unUsedFocusNode);
},

编辑:

Note: it will work in sdk Flutter 3.6.0-0.1.pre Dart SDK 2.19.0-374.1.beta

5
如果你想以“正确的方式”实现这个功能,应该使用Listener而不是GestureDetector。
GestureDetector只对“单击”有效,这并不能代表所有可能执行的手势。
Listener(
  onPointerDown: (_) {
    FocusScopeNode currentFocus = FocusScope.of(context);
    if (!currentFocus.hasPrimaryFocus) {
      currentFocus.focusedChild.unfocus();
    }
  },
  child: MaterialApp(...),
);

4

最适合我的。

我选择使用 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 版本

在这里输入图片描述


是的,在一年之后,它在iOS上运行得非常好... - alperefesahin
它在我的iOS设备上运行良好,正如你所说的,Android有返回按钮。(Flutter版本3.0.5) - huzeyfetas

3

在Flutter 2.5中,GestureDetector.OnTap没有起作用。

只有以下方法可以使用:

return GestureDetector(
      //keyboard pop-down
      onTapDown: (_) => FocusManager.instance.primaryFocus?.unfocus(),
      behavior: HitTestBehavior.translucent,
      child: Scaffold(

一样的。只有这个对我有效。谢谢。 - eqrakhattak
这个有效,谢谢!但是当用户按下返回按钮时,我们该如何使其正常工作? - Usman Sabuwala

3
我刚开发了一个小包,能够为任何小部件提供你所需要的行为方式: keyboard_dismisser on pub.dev。你可以用它来包装整个页面,这样当点击任何非活动小部件时,键盘就会消失。

3

现在您可以使用onTapOutside了。

TextField(
    onTapOutside: (b) {
        FocusManager.instance.primaryFocus?.unfocus();
    }, 
),

2

以下是适合初学者的简单解决方案,当用户点击屏幕上的任何区域时,您需要隐藏键盘。希望这能对您有所帮助。

步骤1:您需要在全局类中创建此方法,

此方法将主要小部件包装到GestureDetector中,因此当用户在文本字段之外点击时,它将自动隐藏键盘。

Widget hideKeyboardWhileTapOnScreen(BuildContext context, {MaterialApp child}){

  return GestureDetector(
    onTap: () {
      if (Platform.isIOS) { //For iOS platform specific condition you can use as per requirement
        SystemChannels.textInput.invokeMethod('TextInput.hide');
        print("Keyboard Hide");
      }      
    },
    child: child,
  );
}

这个方法将您的主widget包装成Listener,所以当用户触摸并向上滚动时,它会自动隐藏键盘。

Widget hideKeyboardWhileTapOnScreen(BuildContext context, {MaterialApp child}){
  return Listener(
    onPointerUp: (_) {
      if (Platform.isIOS) {
        FocusScopeNode currentFocus = FocusScope.of(context);
        if (!currentFocus.hasPrimaryFocus &&
            currentFocus.focusedChild != null) {
          FocusManager.instance.primaryFocus.unfocus();
          print("Call keyboard listner  call");
        }
      }
    },
    child: child,
  );
}

步骤二:使用全局方法的方法如下

@override
Widget build(BuildContext context) {
 
  return hideKeyboardWhileTapOnScreen(context,
    child: MaterialApp(
        debugShowCheckedModeBanner: false, home: Scaffold(body: setAppbar())),
  );
}

Widget setAppbar2() {
  return MaterialApp(
    debugShowCheckedModeBanner: false,
    theme: ThemeData(primarySwatch: Colors.orange),
    home: Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar(),
    ),
  );
}

2

最简单的方法 - 只需在您的MaterialAppbuilder方法中编写一些代码:

void main() {
  runApp(const MyApp());
}

Widget build(BuildContext context) {
  return MaterialApp(
    home: const MyHomePage(),
    builder: (context, child) {
      // this is the key
      return GestureDetector(
        onTap: () => FocusManager.instance.primaryFocus?.unfocus(),
        child: child,
      );
    },
 );
}

然后在所有页面中都可以使用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接