目前我知道使用此代码隐藏软键盘的onTap方法,通过任何小部件的方法.
FocusScope.of(context).requestFocus(new FocusNode());
Run Code Online (Sandbox Code Playgroud)
但我想通过单击TextField外部或屏幕上的任何位置来隐藏软键盘.有没有什么方法可以做到这一点?
Sam*_*ain 51
我找到了最简单的方法,现在您可以onTapOutside在 TextField 小部件中使用
TextField(
onTapOutside: (event) {
print('onTapOutside');
FocusManager.instance.primaryFocus?.unfocus();
},)
Run Code Online (Sandbox Code Playgroud)
当文本字段获得焦点时,在 [TextFieldTapRegion] 组之外发生的每次点击都会调用此方法。
小智 38
您以错误的方式进行操作,只需尝试使用此简单方法来隐藏软键盘即可。您只需要用方法将整个屏幕包裹起来,GestureDetector然后用onTap方法编写此代码。
FocusScope.of(context).requestFocus(new FocusNode());
Run Code Online (Sandbox Code Playgroud)
这是完整的示例:
new Scaffold(
body: new GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(new FocusNode());
},
child: new Container(
//rest of your code write here
)
)
Run Code Online (Sandbox Code Playgroud)
小智 16
总结整个屏幕GestureDetector作为
new Scaffold(
body: new GestureDetector(
onTap: () {
// call this method here to hide soft keyboard
FocusScope.of(context).requestFocus(new FocusNode());
},
child: new Container(
-
-
-
)
)
Run Code Online (Sandbox Code Playgroud)
mah*_*mnj 15
从 Flutters 最新版本 v1.7.8+hotfix.2 开始,你可以使用 unfocus() 而不是 requestfocus() 来隐藏键盘
FocusScope.of(context).unfocus()
Run Code Online (Sandbox Code Playgroud)
所以每当你点击身体部位键盘时就会被隐藏
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("Login"),
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: Container(...)
),
);
}
Run Code Online (Sandbox Code Playgroud)
pma*_*ias 14
如果您有复杂的屏幕,我建议改用Listener。我之前遇到过问题:
使用“HitTestBehavior.opaque”捕获“GestureDetector”上的事件时存在滞后/延迟?
文档说:
考虑使用 GestureDetector 监听更高级别的手势,而不是监听原始指针事件
GestureDetector聆听高层的手势。我认为它造成了一些延迟或滞后。
我的解决方法:
Listener(
behavior: HitTestBehavior.opaque,
onPointerDown: (_) {
FocusManager.instance.primaryFocus?.unfocus();
},
child: Scaffold()
Run Code Online (Sandbox Code Playgroud)
当您点击任意位置时,这将是捕获事件。
Geo*_*rge 12
从2019年5月上旬开始,FocusNode现在有unfocus方法:
取消任何未解决的焦点请求。
无论此节点是否曾经请求过焦点,都可以安全地调用此方法。
使用unfocus,如果你宣布一个FocusNode以编程方式集中文本字段:
final focusNode = FocusNode();
// ...
focusNode.unfocus();
Run Code Online (Sandbox Code Playgroud)
我的原始答案建议detach方法-仅在需要FocusNode完全摆脱使用时才使用。如果您打算将其保留-请unfocus改用。
如果您尚未FocusNode明确声明,请使用“常规”方法:
FocusScope.of(context).requestFocus(new FocusNode());
Run Code Online (Sandbox Code Playgroud)
我看到每个人都FocusScope.of(context).requestFocus(new FocusNode());习惯于使文本字段失去焦点,这对我来说似乎是错误的。
IMO仅会创建一个新的无用的对象,该对象会一直悬在用户使用'real'敲击文本字段之前FocusNode。
如果您正在寻找一种“正确”的方法来1)消除键盘2)取消焦点文本字段-我可能已经找到了正确的方法:
FocusScope.of(context).detach();
Run Code Online (Sandbox Code Playgroud)
官方文档说,detach即使没有焦点,也可以安全使用。
import 'package:flutter/services.dart' show SystemChannels;
SystemChannels.textInput.invokeMethod('TextInput.hide');
Run Code Online (Sandbox Code Playgroud)
omn*_*sia 12
正如一个小的旁注:
如果您使用ListView它的keyboardDismissBehavior属性可能会感兴趣:
ListView(
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
children: [],
)
Run Code Online (Sandbox Code Playgroud)
如果您希望在应用程序的任何屏幕上都可以访问该行为,请使用 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(),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
检查 hasPrimaryFocus 是必要的,以防止 Flutter 在尝试使树顶部的节点不聚焦时抛出异常。
(最初由 Flutter Igniter 博客的 James Dixon 提供)
我已经添加了这一行
behavior: HitTestBehavior.opaque,
Run Code Online (Sandbox Code Playgroud)
到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'),
),
)
);
}
Run Code Online (Sandbox Code Playgroud)
GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
behavior: HitTestBehavior.translucent,
child: rootWidget
)
Run Code Online (Sandbox Code Playgroud)
onPressed: () {
FocusScope.of(context).unfocus();
},
Run Code Online (Sandbox Code Playgroud)
这对我有用。
如果您想以“正确的方式”执行此操作,请使用 Listener 而不是 GestureDetector。
GestureDetector 仅适用于“单击”,这并不代表可以执行的所有可能的手势。
Listener(
onPointerDown: (_) {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.focusedChild.unfocus();
}
},
child: MaterialApp(...),
);
Run Code Online (Sandbox Code Playgroud)
这将适用于最新的颤振版本。
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(),
),
);
Run Code Online (Sandbox Code Playgroud)
child: Form(
child: Column(
children: [
TextFormField(
decoration: InputDecoration(
labelText: 'User Name', hintText: 'User Name'),
onTapOutside: (PointerDownEvent event) {
FocusScope.of(context).requestFocus(_unUsedFocusNode);
},
),
],
),
),
Run Code Online (Sandbox Code Playgroud)
定义焦点节点
FocusNode _unUsedFocusNode = FocusNode();
Run Code Online (Sandbox Code Playgroud)
重写 TextFromField 中的 onTapOutside 方法
onTapOutside: (PointerDownEvent event) {
FocusScope.of(context).requestFocus(_unUsedFocusNode);
},
Run Code Online (Sandbox Code Playgroud)
编辑:
Note: it will work in sdk Flutter 3.6.0-0.1.pre Dart SDK 2.19.0-374.1.beta
Run Code Online (Sandbox Code Playgroud)