我想要实现的是在查看此小部件时,当RawKeyboardListener
未选中/未对准焦点时,TextField
开始立即收听。它运行HandleKey function
来处理我想对keyCode
进行的操作。
我遇到的问题是第一次运行应用程序时,handleKey function
似乎正在运行两次。因此,在下面的示例中,当我仅输入1键时,它将打印why does this run twice $_keyCode
两次。我认为它监听keyUp和keyDown。我想要的结果是它只能运行一次...
但是,当我选择TextField并使用模拟器键盘进行常规提交时,代码也可以正常工作。
我正在努力理解为什么它仅在与TextField交互后才有问题。我觉得它需要在某个地方放置Future
或await
吗?但我不知道。
请帮助。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:async';
class KeyboardListener extends StatefulWidget {
KeyboardListener();
@override
_RawKeyboardListenerState createState() => new _RawKeyboardListenerState();
}
class _RawKeyboardListenerState extends State<KeyboardListener> {
TextEditingController _controller = new TextEditingController();
FocusNode _textNode = new FocusNode();
@override
initState() {
super.initState();
}
//Handle when submitting
void _handleSubmitted(String finalinput) {
setState(() {
SystemChannels.textInput.invokeMethod('TextInput.hide'); //hide keyboard again
_controller.clear();
});
}
handleKey(RawKeyEventDataAndroid key) {
String _keyCode;
_keyCode = key.keyCode.toString(); //keycode of key event (66 is return)
print("why does this run twice $_keyCode");
}
_buildTextComposer() {
TextField _textField = new TextField(
controller: _controller,
onSubmitted: _handleSubmitted,
);
FocusScope.of(context).requestFocus(_textNode);
return new RawKeyboardListener(
focusNode: _textNode,
onKey: (key) => handleKey(key.data),
child: _textField
);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text("Search Item")),
body: _buildTextComposer(),
);
}
}
答案 0 :(得分:4)
使用以下类的实例会同时为keydown和keyup事件调用您的回调:
您可以将整个对象传递给handleKey,并根据对象的运行时类型进行过滤。例如
handleKey(RawKeyEvent key) {
print("Event runtimeType is ${key.runtimeType}");
if(key.runtimeType.toString() == 'RawKeyDownEvent'){
RawKeyEventDataAndroid data = key.data as RawKeyEventDataAndroid;
String _keyCode;
_keyCode = data.keyCode.toString(); //keycode of key event (66 is return)
print("why does this run twice $_keyCode");
}
}
_buildTextComposer() {
TextField _textField = new TextField(
controller: _controller,
onSubmitted: _handleSubmitted,
);
FocusScope.of(context).requestFocus(_textNode);
return new RawKeyboardListener(
focusNode: _textNode,
onKey: handleKey,
child: _textField
);
}
如果仍然不能解决问题,请检查从handleKey方法记录的实际runtimeType,并按其进行过滤。
答案 1 :(得分:1)
你是对的。 RawKeyboardListener
监听原始键盘事件。这意味着它上下返回(或触摸屏上的命名约定如何)。知道您可以简单地创建一个if语句并只需完成一次事件:
bool _tempKeyPressedOnce = false;
if (!_tempKeyPressedOnce) {
// do stuff
_tempKeyPressedOnce = true;
}
答案 2 :(得分:0)
这是使其工作的方式:
RawKeyboardListener(
focusNode: FocusNode(),
onKey: (event) {
// Only taking key down event into consideration
if (event.runtimeType == RawKeyDownEvent) {
bool shiftPressed = event.isShiftPressed; // true: if shift key is pressed
}
},
child: TextField(),
)
答案 3 :(得分:0)
我更喜欢使用 is
而不是访问运行时类型:
onKey: (RawKeyEvent event) {
if (event is RawKeyDownEvent) {
// handle key down
} else if (event is RawKeyUpEvent) {
// handle key up
}
},