wierdo
wierdo

Reputation: 285

How to change a property of other elements' of a list when one of them tapped in Flutter

What I'm trying to do

I have Choice class which includes a list like below.

class Choice {
  Choice({this.title, this.selected});

  final String title;
  final IconData icon;

  bool selected;
}

List<Choice> categoryChoices = <Choice>[
  Choice(title: 'Highlights', selected: true),
  Choice(title: 'Coming Up', selected: false),
  Choice(title: 'England', selected: false),
  Choice(title: 'Germany', selected: false),
  Choice(title: 'Italy', selected: false),
  Choice(title: 'Spain', selected: false),
  Choice(title: 'France', selected: false),
  Choice(title: 'Turkey', selected: false),
];

Also I have a ChoiceButton class which generates GestureDetectors based on the choice list above.

class ChoiceButton extends StatefulWidget {
  ChoiceButton({this.choice, this.onPressed});

  final Choice choice;
  final Function onPressed;

  @override
  _ChoiceButtonState createState() => _ChoiceButtonState();
}

class _ChoiceButtonState extends State<ChoiceButton> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Container(
        alignment: Alignment.center,
        child: Text(
          widget.choice.title,
          style: kTextStyleButtonPrimary.copyWith(
              fontSize: 16.0, fontWeight: FontWeight.normal),
        ),
        decoration: BoxDecoration(
          color: widget.choice.selected ? Colors.blue : Colors.white,
          borderRadius: BorderRadius.circular(10.0),
          border: Border.all(
            color: Colors.blue,
          ),
        ),
        height: 40.0,
        width: 120.0,
      ),
      onTap: widget.onPressed,
    );
  }
}

What is the problem

In my home screen, I put these gesture detectors in a scrollable row. When a gesture detector tapped, I'm changing the color. No problem, my code does all of these. The problem is, there shoulde be only one tapped GestureDetector at the moment. When user taps another, I should set all of others selected property as false. I'm using a map, but I can't find a way to reach other elements of the map to set their selected properties as false. What is the best way to do that kind of thing?

            Padding(
              padding: EdgeInsets.only(
                  left: 12.0, right: 12.0, top: 8.0, bottom: 2.0),
              child: SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: categoryChoices.map((Choice choice) {
                    print(choice);
                    return Padding(
                      padding: EdgeInsets.only(
                          left: 4.0, right: 4.0, top: 2.0, bottom: 2.0),
                      child: ChoiceButton(
                        choice: choice,
                        onPressed: () {
                          //var index = categoryChoices.indexOf(choice);
                          setState(() {
                            choice.selected = true;
                          });
                        },
                      ),
                    );
                  }).toList(),

Upvotes: 1

Views: 951

Answers (1)

Midhun MP
Midhun MP

Reputation: 107231

You can do that by modifying your ChoiceButton implementation. You need to add an unique field in your Choice model (an integer id or something like that), here I'm assuming your title field as unique.

class ChoiceButton extends StatefulWidget {
  ChoiceButton({this.choice, this.onPressed, this.selectedChoice});

  final String selectedChoice; // Add this field to keep track of current selected choice value
  final Choice choice;
  final Function onPressed;

  @override
  _ChoiceButtonState createState() => _ChoiceButtonState();
}

class _ChoiceButtonState extends State<ChoiceButton> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Container(
        alignment: Alignment.center,
        child: Text(
          widget.choice.title,
          style: TextStyle(
              fontSize: 16.0, fontWeight: FontWeight.normal),
        ),
        decoration: BoxDecoration(
          // The selection is made based on currently selected value
          color: widget.selectedChoice == widget.choice.title ? Colors.blue : Colors.white,
          borderRadius: BorderRadius.circular(10.0),
          border: Border.all(
            color: Colors.blue,
          ),
        ),
        height: 40.0,
        width: 120.0,
      ),
      onTap: widget.onPressed,
    );
  }
}

And in your file (where you are going to use the choice button) declare a variable to keep track of selected value)

String selectedValue;

And now change your ChoiceButton initialising code to:

ChoiceButton(
   choice: choice,
   selectedChoice: selectedValue,
   onPressed: () {
      setState(() {
         selectedValue = choice.title;
      });
   },
),

Upvotes: 1

Related Questions