首页 > 解决方案 > Flutter 键盘侦听器在每次刷新时复合构建

问题描述

颤振新手。我有一个键盘监听器包裹我的 Scaffold 主体以检测 Enter 和退格键。

但是我注意到:在每次页面刷新时,都会有额外的侦听器导致事件的双重触发。即在侦听器内触发的增量函数将加倍

我必须关闭浏览器并重新打开页面才能返回初始状态

这里发生了什么事?有什么最好的方法来解决这个问题?

我的代码(选定的相关部分):

class MyHomePageState extends State<MyHomePage> {
  static int counter = 0;

  void _incrementCounter() {
    setState(() {
      counter++;
    });
  }

  void _decrementCounter() {
    setState(() {
      if (counter > 0) {
        counter--;
     }
    });
  }

. . .

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomSheet: Container(
        padding: EdgeInsets.all(5.0),
        child: Text(
          'Some text',
          style: const TextStyle(
            fontSize: 12.0,
          ),
      textAlign: TextAlign.center,
    ),
  ),
  body: RawKeyboardListener(
    focusNode: FocusNode(),
    onKey: (RawKeyEvent event) {
      if (event.isKeyPressed(LogicalKeyboardKey.enter) ||
          event.isKeyPressed(LogicalKeyboardKey.numpadEnter)) {
        _incrementCounter();
      }

      if (event.isKeyPressed(LogicalKeyboardKey.backspace)) {
        _decrementCounter();
      }
    },
    autofocus: true,
    child: Stack(
      alignment: Alignment.center,
      children: <Widget>[
        Container(
          decoration: const BoxDecoration(.......

提前致谢!

标签: flutterkeylistener

解决方案


不是最漂亮的解决方案,但我设法通过分离一个按钮并处理监听器来解决这个问题

_buildDefectButton() {
    // ElevatedButton _button =
    FocusScope.of(context).requestFocus(_focusNode);
    return RawKeyboardListener(
      focusNode: _focusNode,
      autofocus: true,
      onKey: (RawKeyEvent event) => {
        if (event is RawKeyDownEvent)
          {
            _handleKeyPressed(_focusNode, event),
          }
      },
      child: ElevatedButton.icon(
        style: ButtonStyle(
          padding:
              MaterialStateProperty.all<EdgeInsets>(const EdgeInsets.all(20)),
        ),
        label: const Text(
          'Button pressed!',
          style: TextStyle(
            fontSize: 20.0,
          ),
        ),
        onPressed: _incrementCounter,
        icon: const Icon(Icons.sentiment_very_dissatisfied),
      ),
    );
  }


//Handle when keyPressed
  _handleKeyPressed(FocusNode _focusNode, RawKeyEvent event) {
    if (event is RawKeyDownEvent) {
      if (event.isKeyPressed(LogicalKeyboardKey.enter) ||
          event.isKeyPressed(LogicalKeyboardKey.numpadEnter)) {
        _incrementCounter();
        // return KeyEventResult.handled;
      }

      if (event.isKeyPressed(LogicalKeyboardKey.backspace)) {
        _decrementCounter();
        // return KeyEventResult.handled;
      }
    }
    // return KeyEventResult.ignored;
  }

并添加

final FocusNode _focusNode = FocusNode();

@override
  void initState() {
    super.initState();
}

@override
  void dispose() {
    // The attachment will automatically be detached in dispose().
    _focusNode.dispose();
    super.dispose();
  }

如果我在return KeyEventResult.handled按下键盘按钮时会导致重复计数,我确实遇到了一些令人困惑的情况,但是只是处理键盘按下而不返回结果并在最后处理键节点解决了我的问题,即每次刷新时侦听器都会复合。希望这对将来可能面临类似困惑的任何人有所帮助。


推荐阅读