Search code examples
flutterdartcheckboxflutter-listview

How to handle multiple checkboxes from a Listview.builder?


I have a ListView.builder which returns a checkbox and its label. This listview will return a list of checkboxes and labels which will be displayed on the screen. Currently, I'm just creating a global variable isChecked and changing the value of the checkbox with onChanged callback and this value. But it changes the values of all the checkboxes present on the screen.

I need a way to handle each checkbox individually without modifying other checkbox values. And also keep a count of the ticked checkboxes. I'm using a checkboxtile widget for this.


Solution

  • You can change your isChecked bool to be a List of bool's as follows :

    List<bool> isChecked = List.generate(_len, (index) => false);
    

    You can count the number of checked Checkbox's as follows :

    isChecked.where((check) => check == true).length
    

    You can count the number of unchecked Checkbox's as follows :

    isChecked.where((check) => check == false).length
    

    Please see the code below in which sets the checkbox checked / unchecked counts in the the title of the app.

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key}) : super(key: key);
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      static int _len = 10;
      List<bool> isChecked = List.generate(_len, (index) => false);
      String _getTitle() =>
          "Checkbox Demo : Checked = ${isChecked.where((check) => check == true).length}, Unchecked = ${isChecked.where((check) => check == false).length}";
      String _title = "Checkbox Demo";
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('$_title'),
          ),
          body: ListView.builder(
            itemCount: _len,
            itemBuilder: (context, index) {
              return ListTile(
                title: Text("Item $index"),
                trailing: Checkbox(
                    onChanged: (checked) {
                      setState(
                        () {
                          isChecked[index] = checked;
                          _title = _getTitle();
                        },
                      );
                    },
                    value: isChecked[index]),
              );
            },
          ),
        );
      }
    }