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?