Home > database >  GetX and ListView issues
GetX and ListView issues

Time:04-14

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:

enter image description here

Actual outcome:

enter image description here

CodePudding user response:

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.

  • Related