GetX and ListView issues
Because your controller instance initializes only once.
To solve your problem, you need to make a List
that has the status of the cards in the Controller
.
Or don't use the State management tool, but separately place the _isExpanded
value in the _CustomCardState
class. And use the setState()
function.
EDIT
There is another way by using the tag
argument when creating the controller like Get.create(someController, tag: TAG_NAME);
krumpli
Updated on January 04, 2023Comments
-
krumpli over 1 year
I have quite the problem wrapping my head around the whole state management of GetX so naturally I'm facing some issues.
I'm getting a collection from firebase which I put into a listview populated with Card widgets (
CustomCard()
), each document into a Card widget. In this Card widget I have a boolean that controls whether the card should be expanded (simply by Adding a Row()) or not if Card is tapped. The issue I'm facing is that if use GetX for this boolean, all the cards will trigger and not each individual card. In a way this seems logical because I only have one controller that manages this boolean.So to clarify,
bool isCardExpanded
seem to be global for all Card widgets meaning that if I tap one card, ALL cards will expand, which is not what I want. I need them to act individually. Do I need one separate controller for every Card in the list view or is this solvable in another way?Controller
class Controller extends GetxController { RxBool isCardExpanded = false.obs; void changeExpanded() { isCardExpanded.value = !isCardExpanded.value; update(); } }
ListView:
class CustomScreen extends State<CustomScreen> implements ItemScreenInterface { Controller ctrl = Get.find(); @override Widget build(BuildContext context) { return StreamBuilder( stream: FirebaseFirestore.instance .collection(someCol) .doc(SomeDoc) .collection(anotherCol).snapshots(), builder: (BuildContext context, AsyncSnapshot snapshot) { return Column( children: [ Expanded( child: ListView.builder( shrinkWrap: true, itemCount: snapshot.data.docs.length, itemBuilder: (_, i) { return CustomCard( // <------------ Card widget document: snapshot.data.docs[i]); }), ) ], ); }, ); }
Card class
class CustomCard extends StatefulWidget { CustomCard({required this.doc}); var doc; @override _CustomCardState createState() => _CustomCardState(); } class _CustomCardState extends State<CustomCard> { Controller ctrl = Get.find(); RxBool _isCardExpanded = false.obs; @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return Card( child: GestureDetector( onTap: () { ctrl.changeExpanded(); // <-- change bool }, child: Padding( padding: EdgeInsets.all(2), child: Column( children: <Widget>[ Row( children: <Widget>[ Text('Top Part') ]), if (_isCardExpanded.value) Divider(thickness: 2), if (_isCardExpanded.value) // Controlled by _isCardExpanded. Add Row if true Row( children: <Widget>[ Text('EXPANDED'), ], ), ], ), ), ), ); } }
Desired outcome:
Actual outcome:
-
krumpli about 2 yearsThank you, this is what I suspected. I was wondering what the upside was with GetX compared to just setState() in the Card class, which i was using.