Flutter RawKeyboardListener 听两次?

Jay*_*den 13 android dart flutter

我想要实现的是在查看此小部件时,RawKeyboardListenerTextField未选择/聚焦时立即开始收听。它运行HandleKey function来处理我想用keyCode.

我遇到的问题是第一次运行应用程序时,handleKey function似乎运行了两次。所以在下面的例子中,why does this run twice $_keyCode当我只输入 1 个键时,它会打印TWICE。我认为它会听 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(),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

Gan*_*pat 26

使用以下类的实例为 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
      );
  }
Run Code Online (Sandbox Code Playgroud)

如果这仍然没有帮助,请检查从 handleKey 方法记录的实际运行时类型,并按这些进行过滤。

  • 我宁愿使用实例类型运算符:键是 RawKeyDownEvent (3认同)
  • 请注意,这在生产版本中不起作用,其中runtimeType将被优化,即不可用。 (2认同)

Sur*_*gch 15

按键按下按键按下onKey事件都会触发回调。这就是为什么按一次键似乎会调用两次。

在处理事件时,我更喜欢使用is而不是访问运行时类型:

onKey: (RawKeyEvent event) {
  if (event is RawKeyDownEvent) {
    // handle key down
  } else if (event is RawKeyUpEvent) {
    // handle key up
  }
},
Run Code Online (Sandbox Code Playgroud)


ASA*_*EED 5

使用isKeyPressed对我有用。

我的工作代码

RawKeyboardListener(
                  focusNode: _focusNodeKeyboard,
                  onKey: (event) {
                    if (event.isKeyPressed(LogicalKeyboardKey.backspace)) {
                      print('Backspace Pressed'); // Printed Once
                    }
                  },
                )
Run Code Online (Sandbox Code Playgroud)

旧版本

RawKeyboardListener(
                  focusNode: _focusNodeKeyboard,
                  onKey: (event) {
                    if (event.logicalKey == LogicalKeyboardKey.backspace) {
                     print('Backspace Pressed'); // Printed Twice
                    }
                  },
                )
Run Code Online (Sandbox Code Playgroud)