使用按下的键盘键检测点击

Detect tap with pressed keyboard key

我正在尝试为桌面应用程序实现一个 ListView,它能够包含多个select 项目。在桌面上,我们通过单击一个项目或单击并按住控制键来执行此操作。要 select 一个项目,您只需添加一个 Inkwell 或 GestureRecognizer,但我如何检测点击时是否也按下了控制键?我找不到任何建议

你可以玩这个小部件。确保 运行 为桌面模式。

  • 我们需要监听键盘事件。为此,我正在使用 RawKeyboardListener.

  • 跟踪ctrl事件

  • 通过清除之前选择的项目在正常点击时发生单选,但是 _isCTRLPressed 不清除选择的项目

onTap: () {
  if (!_isCTRLPressed) _selectedIndex.clear();
  _onTap(index);
}
演示小部件
class ItemSelection extends StatefulWidget {
  const ItemSelection({Key? key}) : super(key: key);

  @override
  State<ItemSelection> createState() => _ItemSelectionState();
}

class _ItemSelectionState extends State<ItemSelection> {
  List<int> _selectedIndex = [];

  void _onTap(index) {
    if (_selectedIndex.contains(index)) {
      _selectedIndex.remove(index);
    } else {
      _selectedIndex.add(index);
    }
    setState(() {});
  }

  final fc = FocusNode();
  // you can use list for multi-purpose
  bool _isCTRLPressed = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: RawKeyboardListener(
        focusNode: fc,
        autofocus: true,
        onKey: (event) {
          if (event.isKeyPressed(LogicalKeyboardKey.controlLeft)) {
            if (event is RawKeyDownEvent) {
              _isCTRLPressed = true;
            }
          } else {
            _isCTRLPressed = false;
          }
        },
        child: GridView.count(
          crossAxisCount: 6,
          mainAxisSpacing: 2,
          crossAxisSpacing: 2,
          children: List.generate(
            55,
            (index) => GestureDetector(
              onTap: () {
                if (!_isCTRLPressed) _selectedIndex.clear();
                _onTap(index);

                debugPrint("ctrlPressed $_isCTRLPressed");
              },
              child: Container(
                color: _selectedIndex.contains(index)
                    ? Colors.cyanAccent
                    : Colors.grey,
                alignment: Alignment.center,
                child: Text(index.toString()),
              ),
            ),
          ),
        ),
      ),
    );
  }
}