2

I am building a row of toggle buttons (on/off selectors) which is basically a row of containers and each container is a category and is clickable.

Q: How to make it so in a way when one category is selected all the others get deselected?

This is the categories widget I've build:

Widget header(){
  return Column(
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
      Container(
        padding: EdgeInsets.only(top: 4.0, left: 0.0, right: 0.0, bottom: 6.0),
        child: Container(
          child: Center(
            child: Column(
              children: <Widget>[
                SizedBox(height: 4.0,),
                Container(
                  margin: EdgeInsets.only(left: 10.0, right: 10.0),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: <Widget>[
                      InkWell(
                        splashColor: Colors.blue[100],
                        onTap: (){},
                        child: Container(
                          padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
                          decoration: BoxDecoration(
                            color: Colors.blueAccent[100],
                            borderRadius: BorderRadius.all(Radius.circular(48.0)),
                          ),
                          child: Text('All',
                          style: TextStyle(color: Colors.white, fontSize: 10.0, fontWeight: FontWeight.w500),),
                        ),
                      ),
                      SizedBox(width: 2.0,),
                      InkWell(
                        splashColor: Colors.blue[100],
                        onTap: (){},                        
                        child: Container(
                          padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
                          decoration: BoxDecoration(
                            color: Colors.grey[300],
                            borderRadius: BorderRadius.all(Radius.circular(48.0)),
                          ),
                          child: Text('category 1',
                          style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
                        ),
                      ),
                      SizedBox(width: 2.0,),
                      InkWell(
                        splashColor: Colors.blue[100],
                        onTap: (){},                        
                        child: Container(
                          padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
                          decoration: BoxDecoration(
                            color: Colors.grey[300],
                            borderRadius: BorderRadius.all(Radius.circular(48.0)),
                          ),
                          child: Text('category 2',
                          style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
                        ),
                      ),
                      SizedBox(width: 2.0,),
                      InkWell(
                        splashColor: Colors.blue[100],
                        onTap: (){},                        
                        child: Container(
                          padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
                          decoration: BoxDecoration(
                            color: Colors.grey[300],
                            borderRadius: BorderRadius.all(Radius.circular(48.0)),
                          ),
                          child: Text('category 3',
                          style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
                        ),
                      ),
                      SizedBox(width: 2.0,),
                      InkWell(
                        splashColor: Colors.blue[100],
                        onTap: (){},                        
                        child: Container(
                          padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
                          decoration: BoxDecoration(
                            color: Colors.grey[300],
                            borderRadius: BorderRadius.all(Radius.circular(48.0)),
                          ),
                          child: Text('category 4',
                          style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
                        ),
                      ),
                    ],
                  ),
                ),
                SizedBox(height: 6.0,)
              ],
            ),
          ),
        ),
      ),
    ],
  );
}`
2

2 Answers 2

8

The best way would be to use ListView.builder to build your items and save the selected indexes but you can also modify your existing code to save selected items in a list and check to see if the item is in the list and if it is then add selection format and refresh the page. You can implement that as shown below,

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  List<String> selectedCategory = new List<String>();
  String all = 'All';
  String category1 = 'category 1';
  String category2 = 'category 2';
  String category3 = 'category 3';
  String category4 = 'category 4';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(
              title: Text('Test'),
            ),
            body: Container(
                padding: const EdgeInsets.all(20.0),
                child: header()
            )));
  }

  Widget header(){
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        Container(
          padding: EdgeInsets.only(top: 4.0, left: 0.0, right: 0.0, bottom: 6.0),
          child: Container(
            child: Center(
              child: Column(
                children: <Widget>[
                  SizedBox(height: 4.0,),
                  Container(
                    margin: EdgeInsets.only(left: 10.0, right: 10.0),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: <Widget>[
                        InkWell(
                          splashColor: Colors.blue[100],
                          onTap: (){
                            selectedCategory.add(all);
                            selectedCategory.add(category1);
                            selectedCategory.add(category2);
                            selectedCategory.add(category3);
                            selectedCategory.add(category4);
                            setState(() {});
                          },
                          child: Container(
                            padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
                            decoration: BoxDecoration(
                              color: selectedCategory.contains(all) ? Colors.blueAccent[100] : Colors.grey[500],
                              borderRadius: BorderRadius.all(Radius.circular(48.0)),
                            ),
                            child: Text('All',
                              style: TextStyle(color: Colors.white, fontSize: 10.0, fontWeight: FontWeight.w500),),
                          ),
                        ),
                        SizedBox(width: 2.0,),
                        InkWell(
                          splashColor: Colors.blue[100],
                          onTap: (){
                            selectedCategory = new List<String>();
                            selectedCategory.add(category1);
                            setState(() {});
                          },
                          child: Container(
                            padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
                            decoration: BoxDecoration(
                              color: selectedCategory.contains(category1) ? Colors.blue[100] : Colors.grey[300],
                              borderRadius: BorderRadius.all(Radius.circular(48.0)),
                            ),
                            child: Text('category 1',
                              style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
                          ),
                        ),
                        SizedBox(width: 2.0,),
                        InkWell(
                          splashColor: Colors.blue[100],
                          onTap: (){
                            selectedCategory = new List<String>();
                            selectedCategory.add(category2);
                            setState(() {});
                          },
                          child: Container(
                            padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
                            decoration: BoxDecoration(
                              color: selectedCategory.contains(category2) ? Colors.blue[100] : Colors.grey[300],
                              borderRadius: BorderRadius.all(Radius.circular(48.0)),
                            ),
                            child: Text('category 2',
                              style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
                          ),
                        ),
                        SizedBox(width: 2.0,),
                        InkWell(
                          splashColor: Colors.blue[100],
                          onTap: (){
                            selectedCategory = new List<String>();
                            selectedCategory.add(category3);
                            setState(() {});
                          },
                          child: Container(
                            padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
                            decoration: BoxDecoration(
                              color: selectedCategory.contains(category3) ? Colors.blue[100] : Colors.grey[300],
                              borderRadius: BorderRadius.all(Radius.circular(48.0)),
                            ),
                            child: Text('category 3',
                              style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
                          ),
                        ),
                        SizedBox(width: 2.0,),
                        InkWell(
                          splashColor: Colors.blue[100],
                          onTap: (){
                            selectedCategory = new List<String>();
                            selectedCategory.add(category4);
                            setState(() {});
                          },
                          child: Container(
                            padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
                            decoration: BoxDecoration(
                              color: selectedCategory.contains(category4) ? Colors.blue[100] : Colors.grey[300],
                              borderRadius: BorderRadius.all(Radius.circular(48.0)),
                            ),
                            child: Text('category 4',
                              style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
                          ),
                        ),
                      ],
                    ),
                  ),
                  SizedBox(height: 6.0,)
                ],
              ),
            ),
          ),
        ),
      ],
    );
  }
}

demo

Hope this helps.

Sign up to request clarification or add additional context in comments.

2 Comments

this looks good and satisfies my requirements, but is it considered as best practice? I think there's room for improvements and optimization.
That was just an example to give you an idea on how you can achieve what you want based on your existing code but a best approach would be to save the selection state in database so that it's preserved for later but really depends on your goal.
1

Well, this piece of code can be optimized, but so far this worked just fine:

class Header extends StatefulWidget {
  @override
  _HeaderState createState() => _HeaderState();
}

class _HeaderState extends State<Header> {

  List<bool> isSelected;

  @override
    void initState() {
        isSelected = [true, false, false, false, false];
        super.initState();
    }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: <Widget>[
        ToggleButtons(
          borderColor: Colors.transparent,
          fillColor: Colors.transparent,
          borderWidth: null,
          selectedBorderColor: Colors.transparent,
          selectedColor: Colors.transparent,   
          splashColor: Colors.transparent,       
          children: <Widget>[
            !isSelected[0] ?
            Container(            
              padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
              margin: EdgeInsets.only(right: 3.0),
              decoration: BoxDecoration(
                color: Colors.grey[300],
                borderRadius: BorderRadius.all(Radius.circular(48.0)),
              ),
              child: Text('cat 1',
              style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
            )
            :Container(     
              margin: EdgeInsets.only(right: 3.0),       
              padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
              decoration: BoxDecoration(
                color: Colors.blueAccent[100],
                borderRadius: BorderRadius.all(Radius.circular(48.0)),
              ),
              child: Text('cat 1',
              style: TextStyle(color: Colors.white, fontSize: 10.0, fontWeight: FontWeight.w700),),
            ),
            !isSelected[1] ?
            Container(
              margin: EdgeInsets.only(right: 3.0),
              padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
              decoration: BoxDecoration(
                color: Colors.grey[300],
                borderRadius: BorderRadius.all(Radius.circular(48.0)),
              ),
              child: Text('cat 2',
                style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
            )
            :Container(  
              margin: EdgeInsets.only(right: 3.0),          
              padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
              decoration: BoxDecoration(
                color: Colors.blueAccent[100],
                borderRadius: BorderRadius.all(Radius.circular(48.0)),
              ),
              child: Text('cat 2',
              style: TextStyle(color: Colors.white, fontSize: 10.0, fontWeight: FontWeight.w700),),
            ),
            !isSelected[2] ?
            Container(
              margin: EdgeInsets.only(right: 3.0),
              padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
              decoration: BoxDecoration(
                color: Colors.grey[300],
                borderRadius: BorderRadius.all(Radius.circular(48.0)),
              ),
              child: Text('cat 3',
                style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
            )
            :Container(  
              margin: EdgeInsets.only(right: 3.0),          
              padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
              decoration: BoxDecoration(
                color: Colors.blueAccent[100],
                borderRadius: BorderRadius.all(Radius.circular(48.0)),
              ),
              child: Text('cat 3',
              style: TextStyle(color: Colors.white, fontSize: 10.0, fontWeight: FontWeight.w700),),
            ),
            !isSelected[3] ?
            Container(
              margin: EdgeInsets.only(right: 3.0),
              padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
              decoration: BoxDecoration(
                color: Colors.grey[300],
                borderRadius: BorderRadius.all(Radius.circular(48.0)),
              ),
              child: Text('cat 4',
                style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
            )
            :Container(  
              margin: EdgeInsets.only(right: 3.0),          
              padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
              decoration: BoxDecoration(
                color: Colors.blueAccent[100],
                borderRadius: BorderRadius.all(Radius.circular(48.0)),
              ),
              child: Text('cat 4',
              style: TextStyle(color: Colors.white, fontSize: 10.0, fontWeight: FontWeight.w700),),
            ),
            !isSelected[4] ?
            Container(
              padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
              decoration: BoxDecoration(
                color: Colors.grey[300],
                borderRadius: BorderRadius.all(Radius.circular(48.0)),
              ),
              child: Text('cat 5',
                style: TextStyle(color: Colors.grey[900], fontSize: 10.0, fontWeight: FontWeight.w500),),
            )
            :Container(            
              padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
              decoration: BoxDecoration(
                color: Colors.blueAccent[100],
                borderRadius: BorderRadius.all(Radius.circular(48.0)),
              ),
              child: Text('cat 5',
              style: TextStyle(color: Colors.white, fontSize: 10.0, fontWeight: FontWeight.w700),),
            ),
          ],
          onPressed: (int index) {
            setState(() {
              for (int i = 0; i < isSelected.length; i++) {
                isSelected[i] = i == index;
              }
            });
          },
          isSelected: isSelected,
        ),
      ],
    );
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.