Flutter RawKeyboardListener收听了两次?

时间:2018-06-22 09:51:05

标签: android dart flutter

我想要实现的是在查看此小部件时,当RawKeyboardListener未选中/未对准焦点时,TextField开始立即收听。它运行HandleKey function来处理我想对keyCode进行的操作。

我遇到的问题是第一次运行应用程序时,handleKey function似乎正在运行两次。因此,在下面的示例中,当我仅输入1键时,它将打印why does this run twice $_keyCode两次。我认为它监听keyUp和keyDown。我想要的结果是它只能运行一次...

但是,当我选择TextField并使用模拟器键盘进行常规提交时,代码也可以正常工作。

我正在努力理解为什么它仅在与TextField交互后才有问题。我觉得它需要在某个地方放置Futureawait吗?但我不知道。

请帮助。

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

4 个答案:

答案 0 :(得分:4)

使用以下类的实例会同时为keydown和keyup事件调用您的回调:

  • RawKeyDownEvent
  • RawKeyUpEvent

您可以将整个对象传递给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
  }
},