How to handle multiple checkboxes from a Listview.builder?

Issue

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]),
          );
        },
      ),
    );
  }
}

Answered By – bluenile

Answer Checked By – Pedro (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *