0

I am struggling trying to figure out how to simultaneously implement animation while using a state management solution (GetX). With this code in the UI:

     class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
      late AnimationController animController;
      late Animation topPlayerCard1;
      late Animation leftPlayerCard1;

     @override
      void initState() {
        super.initState();
        animController = AnimationController(
            vsync: this, duration: Duration(milliseconds: 1000));
        topPlayerCard1 = Tween<double>(begin: -1, end: 0.95).animate(
            CurvedAnimation(
                parent: animController,
                curve: Interval(0.0, 0.30, curve: Curves.decelerate)));
        leftPlayerCard1 = Tween<double>(begin: 1, end: -0.2).animate(
            CurvedAnimation(
                parent: animController,
                curve: Interval(0.0, 0.30, curve: Curves.decelerate)));
        animController.addListener(() {
          setState(() {});
        });
        animController.forward();
      }

  @override
  Widget build(BuildContext context) {
    DeckController deckController = DeckController(); //GetX Controller
    deckController.makeDeck();

    return Scaffold(
      appBar: AppBar(),
      body: Container(
        child: Column(
          children: [
            Align(
              alignment: Alignment(
                leftPlayerCard1.value,
                topPlayerCard1.value,
              ),
              child: Obx(
                () => buildCard(deckController.playerCard1.value),
              ),
            ),
            TextButton(
              child: Text('Next Cards'),
              onPressed: () {
                deckController.playerCard1.value = deckController.getNextCard();
                //Make the cards move
                animController.reset();
                animController.forward();
              },
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    animController.dispose();
    super.dispose();
  }
}

the playing card image slides across the screen and will do so each time the button's clicked. However, because setState is called repeatedly (I think), the cardsDealt variable in the GetXController continually resets to 0 as the controller is continually reinitiated (so getNextCard() always returns the same value from the deck list):

   class DeckController extends GetxController {
  var deck = <PlayingCard>[].obs;
  var cardsDealt = 0;
  var playerCard1 = PlayingCard(suit: CardSuit.S, value: CardValue.ace).obs;
  var playerCard2 = PlayingCard(suit: CardSuit.S, value: CardValue.ace).obs;
  var dealerCard = PlayingCard(suit: CardSuit.S, value: CardValue.ace).obs;

  void makeDeck() {
    // make standard 52 card deck
    final _deck = RxList<PlayingCard>();
    CardSuit.values.forEach((suit) {
      CardValue.values.forEach((type) {
        _deck.add(PlayingCard(
          value: type,
          suit: suit,
        ));
      });
    });
    deck = _deck;
  }

  void shuffleNewDeck() {
    makeDeck();
    deck.shuffle();
    cardsDealt = 0;
  }

  PlayingCard getNextCard() {
    PlayingCard _card;
    if (cardsDealt <= 51) {
      _card = deck[cardsDealt];
      cardsDealt++;
    } else
      _card = deck[0];
    return _card;
  }

In addition, having the stateful UI seems opposite to what state management is supposed to be about. How do I write this code so that the card image slides across the screen AND the PlayingCard object returned by getNextCard() changes each time the UI button is tapped?

Al C
  • 5,175
  • 6
  • 44
  • 74
  • make `DeckController deckController` a field in your `State` class, not a local variable inside `build` method? i never used `getx` but this is the first thing i would start with – pskink Aug 13 '21 at 16:28
  • @pskink Yes, of course. I feel like an idiot :-) Your point is excellent. – Al C Aug 13 '21 at 17:20

0 Answers0