33

Using flutter, I am trying to build a list of values with some text and a customized checkbox next to it. Tapping anywhere on the text or checkbox should show the enabled state and tapping again should disable it. I am unsure how to handle the state of each checkbox separately. I tried using CheckBoxListTile too but I am not sure how I can achieve what I want. Can someone provide any examples?

Anonk
  • 1,473
  • 4
  • 13
  • 15

10 Answers10

45

Here's some sample code for CheckboxListTile. You can find more examples in the gallery.

screenshot

import 'package:flutter/material.dart';

class Demo extends StatefulWidget {
  @override
  DemoState createState() => new DemoState();
}

class DemoState extends State<Demo> {
  Map<String, bool> values = {
    'foo': true,
    'bar': false,
  };

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text('CheckboxListTile demo')),
      body: new ListView(
        children: values.keys.map((String key) {
          return new CheckboxListTile(
            title: new Text(key),
            value: values[key],
            onChanged: (bool value) {
              setState(() {
                values[key] = value;
              });
            },
          );
        }).toList(),
      ),
    );
  }
}

void main() {
  runApp(new MaterialApp(home: new Demo(), debugShowCheckedModeBanner: false));
}
Collin Jackson
  • 110,240
  • 31
  • 221
  • 152
  • 1
    When you create a map you are hardcoding it (making it not to be dynamic). For example, imagine creating a list of tasks (it can be 1 up to 50 tasks to do). Could you improve your answer please? – pedro_bb7 Apr 15 '20 at 19:37
  • 2
    @pedro_bb7 - that is not a reasonable request. This answer perfectly illustrates the pertinent details - using a collection of values that are easily changed. Showing code that demonstrates how to query that (eg from a DB) would complicate the answer without adding benefit. – Chris Rogers Aug 20 '21 at 06:19
23

I think it will work as you want. It also stores all selected checkbox value(s) into a List variable. so you please simply put this code in main.dart file and execute to check how it works.

import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Multi-Select & Unselect Checkbox in Flutter'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List _selecteCategorys = List();

  Map<String, dynamic> _categories = {
    "responseCode": "1",
    "responseText": "List categories.",
    "responseBody": [
      {"category_id": "5", "category_name": "Barber"},
      {"category_id": "3", "category_name": "Carpanter"},
      {"category_id": "7", "category_name": "Cook"}
    ],
    "responseTotalResult":
        3 // Total result is 3 here becasue we have 3 categories in responseBody.
  };

  void _onCategorySelected(bool selected, category_id) {
    if (selected == true) {
      setState(() {
        _selecteCategorys.add(category_id);
      });
    } else {
      setState(() {
        _selecteCategorys.remove(category_id);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: ListView.builder(
          itemCount: _categories['responseTotalResult'],
          itemBuilder: (BuildContext context, int index) {
            return CheckboxListTile(
              value: _selecteCategorys
                  .contains(_categories['responseBody'][index]['category_id']),
              onChanged: (bool selected) {
                _onCategorySelected(selected,
                    _categories['responseBody'][index]['category_id']);
              },
              title: Text(_categories['responseBody'][index]['category_name']),
            );
          }),  
    );
  }
}
Manoj Kumar
  • 808
  • 9
  • 15
9

use List contains returns bool.

here is example

List<int> selectedList = [];
List<Widget> mList; //you can't add equal
createMenuWidget(Course courses) {
  for (int b = 0; b < courses.length; b++) {
    Map cmap = courses[b];
    mList.add(CheckboxListTile(
      onChanged: (bool value){
        setState(() {
          if(value){
            selectedList.add(cmap[course_id]);
          }else{
            selectedList.remove(cmap[course_id]);
          }
        });
      },
      value: selectedList.contains(cmap[course_id]),
      title: new Text(cmap[course_name]),
    ));
  }
}
Rutvik Gumasana
  • 1,458
  • 11
  • 42
  • 66
force-guidance
  • 103
  • 1
  • 4
6

The simple Way to Do this with Dynamic List of Data with CheckBox.

List<String>data= ["Mathew","Deon","Sara","Yeu"];
List<String> userChecked = [];

ListView.builder(
    itemCount: data.length,
    itemBuilder: (context, i) {
      return ListTile(
        title: Text(
            data[i])
        trailing:Checkbox(
                value: userChecked.contains(data[i]),
                onChanged: (val) {
                  _onSelected(val, data[i]);
                },
              )
            //you can use checkboxlistTile too
      );
    })
// now we write the functionality to check and uncheck it!!

void _onSelected(bool selected, String dataName) {
    if (selected == true) {
      setState(() {
        userChecked.add(dataName);
      });
    } else {
      setState(() {
        userChecked.remove(dataName);
      });
    }
  }

And Its Done !!... Enjoy Fluttering... Give a thumbs up as it will work for you !! :P

Ravindra S. Patil
  • 11,757
  • 3
  • 13
  • 40
neon97
  • 552
  • 6
  • 8
5

Please use package grouped_buttons.
It support both checkbox and radio.
https://pub.dartlang.org/packages/grouped_buttons

CheckboxGroup(
      labels: <String>[
        "Sunday",
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday",
      ],
      disabled: [
        "Wednesday",
        "Friday"
      ],
      onChange: (bool isChecked, String label, int index) => print("isChecked: $isChecked   label: $label  index: $index"),
      onSelected: (List<String> checked) => print("checked: ${checked.toString()}"),
    ),

enter image description here

and full example of usage in here https://github.com/akshathjain/grouped_buttons/blob/master/example/lib/main.dart

and author's logic to implement https://github.com/akshathjain/grouped_buttons/blob/master/lib/src/checkbox_group.dart

Basically, author use two List of Strings to control selected and unselect

void onChanged(bool isChecked, int i){
  bool isAlreadyContained = _selected.contains(widget.labels.elementAt(i));

  if(mounted){
   setState(() {
    if(!isChecked && isAlreadyContained){
      _selected.remove(widget.labels.elementAt(i));
    }else if(isChecked && !isAlreadyContained){
      _selected.add(widget.labels.elementAt(i));
    }

    if(widget.onChange != null) widget.onChange(isChecked, widget.labels.elementAt(i), i);
    if(widget.onSelected != null) widget.onSelected(_selected);
   });
 }
}
chunhunghan
  • 51,087
  • 5
  • 102
  • 120
5

Screenshot (Null safe)

enter image description here


Code:

class _MyPageState extends State<MyPage> {
  final Map<String, bool> _map = {};
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () => setState(() => _map.addEntries([MapEntry('Checkbox #${++_count}', false)])),
      ),
      body: ListView(
        children: _map.keys
            .map(
              (key) => CheckboxListTile(
                value: _map[key],
                onChanged: (value) => setState(() => _map[key] = value!),
                subtitle: Text(key),
              ),
            )
            .toList(),
      ),
    );
  }
}
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
4

Use chekboxListTile

Here is the sample code

    @override
    Widget build(BuildContext context) {
      return Center(
        child: CheckboxListTile(
          title: Text('Check me'),
  );
    }

By the way, You can also add checkbox in ListView in Flutter. Apps sample is given below-

Main.dart

import 'package:flutter/material.dart';
import 'checkbox_in_listview_task-7.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: CheckBoxInListview(),
    );
  }
}

checkbox_in_listview_task.dart

import 'package:flutter/material.dart';

class CheckBoxInListview extends StatefulWidget {
  @override
  _CheckBoxInListviewState createState() => _CheckBoxInListviewState();
}

class _CheckBoxInListviewState extends State<CheckBoxInListview> {
  bool _isChecked = true;

  List<String> _texts = [
    "InduceSmile.com," "Flutter.io",
    "google.com",
    "youtube.com",
    "yahoo.com",
    "gmail.com"
  ];
  @override
  Widget build(BuildContext context) {
return Scaffold(
      appBar: AppBar(
        title: Text("CheckBox in ListView Example"),
      ),
      body: ListView(
        padding: EdgeInsets.all(8.0),
        children: _texts.map((text) => CheckboxListTile(
          title: Text(text),
           value: _isChecked,
              onChanged: (val) {
              setState(() {
               _isChecked = val;

            });
          },
        )).toList(),
      ),
    );
  }
}

And here is the output

CheckBox in LisView in Flutter app

Abir Ahsan
  • 2,649
  • 29
  • 51
2

here how you can do it

import 'package:flutter/material.dart';

class RegisterFragments extends StatefulWidget {
  RegisterFragments({Key key, this.step}) : super(key: key);
  final int step;

  _RegisterFragmentsState createState() => _RegisterFragmentsState();
}

class _RegisterFragmentsState extends State<RegisterFragments> {
  Map<String, bool> values = {"abc": false, "def": true, "ghi": false};
  List<String> _do = ['One', 'Two', 'Free', 'Four'];
  String _dropdownValue = 'One';

  @override
  Widget build(BuildContext context) {
    switch (widget.step) {
      case 0:
        return buildDo();
        break;
      case 1:
        return Container(
          child: ListView.builder(
            shrinkWrap: true,
            itemCount: values.length,
            itemBuilder: (BuildContext context, int index) {
              switch (widget.step) {
                case 0:
                  return buildDo();
                  break;
                case 1:
                  return buildService(context, index);
                  break;
                default:
                  return Container();
                  break;
              }
            },
          ),
        );
        break;
      default:
        return Container();
        break;
    }
  }

  Widget buildService(BuildContext context, int index) {
    String _key = values.keys.elementAt(index);

    return Container(
      child: Card(
        child: CheckboxListTile(
          title: Text(_key),
          onChanged: (bool value) {
            setState(() {
              values[_key] = value;
            });
          },
          value: values[_key],
        ),
      ),
    );
  }

  Widget buildDo() {
    return DropdownButton<String>(
      isExpanded: true,
      hint: Text("Service"),
      items: _do.map<DropdownMenuItem<String>>((String value) {
        return DropdownMenuItem<String>(
          value: value,
          child: Text(value),
        );
      }).toList(),
      onChanged: (String newValue) {
        setState(() {
          this._dropdownValue = newValue;
        });
      },
      value: _dropdownValue,
    );
  }
}
Rashid Iqbal
  • 1,123
  • 13
  • 13
  • 1
    Some comments and explanations alongside code is always more instructing poster and readers of your answers. – Léa Gris Aug 16 '19 at 00:17
0

In case you are using the CheckBoxGroup or anything similar AND are inside a slider, do not forget to put it in a StatefulBuilder:

    return StatefulBuilder(// StatefulBuilder
    builder: (context, setState) {
  return CheckboxGroup(
    orientation: GroupedButtonsOrientation.HORIZONTAL,
    margin: const EdgeInsets.only(left: 12.0),
    onSelected: (List selected) => setState(() {
      _checked = selected;
    }),
    labels: teamWorkoutDays,
    checked: _checked,
    itemBuilder: (Checkbox cb, Text txt, int i) {
      return Column(
        children: <Widget>[
          Icon(Icons.polymer),
          cb,
          txt,
        ],
      );
    },
  );
});
stan
  • 229
  • 3
  • 10
0

To create a list of values with text and customized checkboxes that toggle their enabled state when tapped, you can use the ListView.builder along with a custom widget that encapsulates the checkbox and text. Here's a step-by-step breakdown:

  1. Create a Model Class:
class ItemModel {
  final String text;
  bool isChecked;

  ItemModel(this.text, this.isChecked);
}

Build the Screen:

import 'package:flutter/material.dart';

class CustomCheckBoxListItem extends StatelessWidget {
  final ListItemModel item;
  final Function(bool) onCheckboxChanged;

  CustomCheckBoxListItem({required this.item, required this.onCheckboxChanged});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        onCheckboxChanged(!item.isChecked);
      },
      child: Row(
        children: [
          Checkbox(
            value: item.isChecked,
            onChanged: onCheckboxChanged,
          ),
          Text(item.text),
        ],
      ),
    );
  }
}

Build the List:

import 'package:flutter/material.dart';

class CheckboxListExample extends StatefulWidget {
  @override
  _CheckboxListExampleState createState() => _CheckboxListExampleState();
}

class _CheckboxListExampleState extends State<CheckboxListExample> {
  List<ListItemModel> items = [
    ListItemModel('Item 1', false),
    ListItemModel('Item 2', false),
    // ... add more items
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Checkbox List Example')),
      body: ListView.builder(
        itemCount: items.length,
        itemBuilder: (context, index) {
          return CustomCheckBoxListItem(
            item: items[index],
            onCheckboxChanged: (isChecked) {
              setState(() {
                items[index].isChecked = isChecked;
              });
            },
          );
        },
      ),
    );
  }
}