Detect tap with pressed keyboard key

1.9k Views Asked by At

I am trying to implement a ListView for Desktop applications, which is able to multiselect the items. On Desktop we do this by either clicking an item, or clicking and holding the control key. To select an item, you simply can add an Inkwell or GestureRecognizer, but how do I detect on click that there is also the control key pressed? I couldn't find any suggestions

1

There are 1 best solutions below

1
On BEST ANSWER

You can play with this widget. Make sure to run as desktop mode.

  • we need to listen keyboard event. For that I am using RawKeyboardListener.

  • keep track ctrl event

  • single selection happen on normal tap by clearing previous selected item, but while _isCTRLPressed don't clear the selected items

onTap: () {
  if (!_isCTRLPressed) _selectedIndex.clear();
  _onTap(index);
}
Demo widget
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()),
              ),
            ),
          ),
        ),
      ),
    );
  }
}