Flutter:如何在按键按下时阻止默认行为?

8
我正在尝试拦截用户按音量按钮以执行特定操作并防止默认行为(更改音量)。
以下是我目前的代码:
RawKeyboard.instance.addListener(_keyboardListener);

void _keyboardListener(RawKeyEvent e) {
  if(e.runtimeType == RawKeyUpEvent) {
    RawKeyEventDataAndroid eA = e.data;
    if(eA.keyCode == 24) { //volume up key
      _goNextPage();
    }
    if(eA.keyCode == 25) { //volume down key
      _goPrevPage();
    }
  }
}

我该如何防止音量改变(并停止音量滑块出现在顶部)?
类似于Javascript的方法是在键盘事件上调用event.preventDefault()
这似乎是一个非常琐碎的问题,但我在文档中没有找到任何答案。
谢谢。

你找到解决方案了吗? - splangi
很遗憾,不行。 - joseph
3个回答

4

我曾经遇到过类似的问题,想分享一下我是如何解决它的。

为了停止传播,我们必须从焦点节点树中的onKey方法返回true。为了实现这一点,我已经包装了我的应用程序主体,使用了以下的FocusScopeFocus小部件:

MaterialApp(
      home: Scaffold(
          body: FocusScope(
              autofocus: true,
              child: Focus(
                  autofocus: true,
                  canRequestFocus: true,
                  onKey: (data, event) {
                    if (event.isKeyPressed(LogicalKeyboardKey.audioVolumeUp)) {
                      print("Volume up");
                      return true;
                    }
                    if (event
                        .isKeyPressed(LogicalKeyboardKey.audioVolumeDown)) {
                      print("Volume down");
                      return true;
                    }
                    return false;
                  },
                  child: Text(text: "Hallochen")))))

1
感谢Sergey的答案,我也成功解决了问题。在我的情况下,我想创建一个ListView,并使用下拉刷新(RefreshIndicator)来适用于移动设备和Web。
我尝试实现一个刷新指示器,当用户点击F5刷新网页时会出现,但我必须防止浏览器真正刷新页面。
以下是我的实现示例,它可以防止用户在单击F5时进行刷新。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';


class ExamplePage extends StatefulWidget {
  @override
  _ExamplePageState createState() => _ExamplePageState();
}

class _ExamplePageState extends State<ExamplePage> {
  final GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
  final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = new GlobalKey<RefreshIndicatorState>();
  
  List items = [];

  Future<void> _pullRefresh() async {
    await Future.delayed(Duration(milliseconds: 1000));
  }
  
  @override
  Widget build(BuildContext context) {
    return FocusScope(
      autofocus: true,
      child: Focus(
        autofocus: true,
        canRequestFocus: true,
        onKey: (data, event) {
          if (event
              .isKeyPressed(LogicalKeyboardKey.f5)) {
            _refreshIndicatorKey.currentState!.show();
            return KeyEventResult.handled;
          }
          return KeyEventResult.ignored;
        },
        child: Container(
            padding: EdgeInsets.all(15.0),
            child: RefreshIndicator(
              key: _refreshIndicatorKey,
              onRefresh: _pullRefresh,
              child: AnimatedList(
                key: listKey,
                initialItemCount: items.length,
                itemBuilder: (context, index, animation) {
                  return _buildItem(context, index, animation);
                },
              ),
            ),
        ),
      ),
    );
  }
  
    Widget _buildItem(
      BuildContext context, int index, Animation<double> animation) {
    return Text("Example");
    }
}

0

这里的所有解决方案都是针对 Focus 小部件的,它们给了我灵感,但对我来说并不完全适用,因为我正在使用 RawKeyboardListener,而且不想改用其他东西。

以下是对我有效的方法:

final node = FocusNode();
final fnode = FocusScopeNode();

@override
Widget build(BuildContext context) {
  return FocusScope(
    node: fnode,
    child: RawKeyboardListener(
      focusNode: node,
      ...
    ),
  );
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接