0

I am creating a card deck where I'd like the user to touch on the deck of cards to select a card, but then move their thumb (pointer) left/right to adjust the selection. enter image description here For example the user touched down on 2 of clubs, but as they move thumb horizontally to the right and onto 3 of clubs, that will then be selected.

I am experimenting with flutter and I tried to achieve this using the GestureDetector class. But I expected GestureDetector.onHorizontalDragUpdate to be called on 3 of Clubs when I move onto the card, but it seems to call it to the widget where I touched down (2 of clubs).

Here's my sample code:

class Deck extends StatefulWidget {
  Deck({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _DeckState createState() => new _DeckState();
}

class _DeckState extends State<Deck> {
  List<String> _cards = ['s7', 's8', 's10', 'sk', 'h10', 'hq', 'c2', 'c3', 'd6', 'dj', 'dq', 'dk', 'da'];

  String _selectedCard;

  void _onButtonPressed() {
  }


  void _selectCard(String card){
    print(card);

    setState(() {
      if(_selectedCard == card)
        return;

      _selectedCard = card;   
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Stack(
        children: _cards
          .asMap()
          .map<int, Positioned>((i, c){
            var positioned = Positioned(
                left: i * 25.0, 
                top: c == _selectedCard ? 10.0 : 30.0, 
                width: 71.0,
                height: 96.0,
                child: GestureDetector(
                  behavior: HitTestBehavior.opaque,
                  onHorizontalDragDown: (e) => _selectCard(c),
                  onHorizontalDragUpdate: (e) => _selectCard(c),
                  child: Image(
                    image: new AssetImage('assets/$c.gif'),
                  ),
                ),
              );
            return MapEntry(i, positioned);
          })
          .values
          .map((c) => c)
          .toList()
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _onButtonPressed,
        tooltip: 'Increment',
        child: new Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

Is GestureDetector not the right class for this? How can I achieve this? Please note that I've tried Listener.PointerMoveEvent, but it seem to behave the same way, sending the move event to the widget where touch-down occurred, instead of to the new widget.

Kayes
  • 502
  • 7
  • 18
  • 1
    You can wrap the whole Stack with GestureDetector or Listener. After that you have to check absolute tap position and find card on this position. It's a bit of complicate way, but I don't see another – Andrii Turkovskyi Oct 09 '18 at 07:57
  • 1
    You can take a look into https://stackoverflow.com/questions/50639652/how-to-swipe-drag-2-or-more-buttons-in-a-grid-of-buttons-using-flutter/52625182#52625182 – Rémi Rousselet Oct 09 '18 at 07:59
  • @AndreyTurkovsky Thanks. Hoping I didn't have to do that :( I'll give it a try. – Kayes Oct 19 '18 at 00:11

1 Answers1

1

I had a problem that looked like yours...Instead of Gesture Detector I wrapped my widgets with an Listener and gave the same Global Key for them. Something like:

final GlobalKey _key = GlobalKey();
Listener(
    key: _key,
    behavior: HitTestBehavior.opaque,
    onPointerSomething: (PointerSomeEvent){...},
    child: widget1,
)
Listener(
    key: _key,
    behavior: HitTestBehavior.opaque,
    onPointerSomething: (PointerSomeEvent){...},
    child: widget2,
)

Worked for me, hope it work for you too...Anyway if you want to track a pointer through multiple widgets I guess Listener will be better than Gesture Detector