如何解除屏幕上的键盘?

我正在用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());
}
266617 次浏览

这个答案已经过时了。有关Flutter的新版本,请参阅答案

你可以通过去掉TextFormField的焦点并将其交给一个未使用的FocusNode来解散键盘:

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

解决方案与FocusScope不适合我。 我找到了另一个:

import 'package:flutter/services.dart';


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

它解决了我的问题。

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

颤振提示这个- 把你的小部件放在新的GestureDetector ()里面,点击将隐藏键盘,在点击时使用FocusScope.of(上下文)。新FocusNode requestFocus (())

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;
}}

你可以使用FocusNode类中的unfocus()方法。

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());
}

在Flutter中,一切都是一个小部件,我决定将FocusScope.of(context).unfocus();方法包装在一个简短的实用程序小部件中。

只需创建KeyboardHider小部件:

import 'package:flutter/widgets.dart';


/// A widget that upon tap attempts to hide the keyboard.
class KeyboardHider extends StatelessWidget {
/// Creates a widget that on tap, hides the keyboard.
const KeyboardHider({
required this.child,
Key? key,
}) : super(key: key);


/// The widget below this widget in the tree.
final Widget child;


@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => FocusScope.of(context).unfocus(),
child: child,
);
}
}

现在,你可以用KeyboardHider小部件包装任何小部件(在使用好的IDE时非常方便),然后当你点击某个东西时,键盘会自动关闭。它与表单和其他可点击区域一起工作得很好。

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(),
);
}
}

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

   void initState() {
SystemChannels.textInput.invokeMethod('TextInput.hide');
super.initState();
}

对于Flutter版本2或最新版本:

由于Flutter 2具有零安全,这是最好的方法:

FocusManager.instance.primaryFocus?.unfocus();

注意:使用旧的方法会导致一些问题,如保持重建状态;


用于颤振版本<2 :

自Flutter v1.7.8+热修复。2、要走的路是:

FocusScope.of(context).unfocus();

关于PR的评论:

现在#31909 (be75fb3)已经着陆了,你应该使用 FocusScope.of(context).unfocus()代替 FocusScope.of(context).requestFocus(FocusNode()),因为__abc1是 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̶(̶)̶)̶;̶

阅读更多关于颤振文档中的FocusScope

_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>[/*...*/],
),
),
);
}
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'),
),
), })

试试这个动作

看起来不同的版本用不同的方法。我使用的是Flutter v1.17.1,下面的操作适合我。

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

尝试使用TextEditingController。 在开始时,

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

在新闻发布会上,

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

这将取消键盘。

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

FocusManager.instance.primaryFocus.unfocus();

总之,这是Flutter 1.17的工作解决方案:

像这样包装你的Widget:

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

取消键盘(1.7.8+热修复。2和以上)只需调用下面的方法:

FocusScope.of(context).unfocus();

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

你也可以为你的文本域声明一个focusNode,当你完成时,你可以在那个focusNode上调用unfocus方法 并且dispose它

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

对我来说,上面的App小部件监听器是我发现的最好的方法:

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

这可能会简化情况。下面的代码只在键盘打开时才会工作

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

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

如果你使用CustomScrollView,只要放,

keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,

你可以用“gesturedetector”来包装你的小部件,然后分配“FocusScope.of(context).unfocus()”。到其onTap功能

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

如果你的键盘仍然不会关闭,不要忘记添加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)),
),
);
}

我已经创建了这个函数到我的基本代码,到目前为止工作得很好!!

void hideKeyword(BuildContext context) {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
currentFocus.focusedChild.unfocus();
}
}

FocusScope.of(上下文).unfocus ();是行不通的。

这段代码为我工作在颤振2.2.3和零安全。

WidgetsBinding.instance?.focusManager.primaryFocus?.unfocus()

来源:https://github.com/flutter/flutter/issues/20227#issuecomment-512860882

例如,把这段代码放在MyAppState中,当整个应用程序触摸外部时应用隐藏键盘。

return GestureDetector(
onTap: () =>
WidgetsBinding.instance?.focusManager.primaryFocus?.unfocus(),
child: MaterialApp(
title: 'Flutter Demo',
theme: getTheme(),
home: _body(),
),
);

在需要时调用此函数

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

使用SystemChannels.textInput.invokeMethod('TextInput.hide');。当屏幕加载时,它将关闭/解除键盘。

void initState() {
super.initState();
SystemChannels.textInput.invokeMethod('TextInput.hide');
}

我们需要检查当前FocusNode是否有“主焦点”。如果没有,我们在当前节点上调用unfocus()来移除焦点并触发键盘解散。如果尝试unfocus()当前具有主焦点的节点,Flutter将抛出异常。

 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(),
),
);
< p >} } < / p >

======关闭键盘点击出TextField后 =======

 @override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),  //this will dismiss keyboard
child: Scaffold(
body: SafeArea(
.........

======关闭键盘当滚动屏幕时 =======

ListView(
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, //this will dismiss
children: [
..........

< >强SingleChildScrollView < / >强小部件也有这个属性。

你可以用这个。

  1. FocusScope.of(上下文).requestFocus (FocusNode ());

你可以使用这个手势侦测器的onTap或者像这样的InkWell。

  1. < p > GestureDetector (

                 onTap: () {`
    // THIS FOCUS SCOPE WILL CLOSE THE KEYBOARD
    FocusScope.of(context).requestFocus(FocusNode());
    forgotPasswordAPI(emailController.text);
    },``
    

在构建小部件中添加此代码

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