How to select multiple checkboxes in flutter in checkboxlisttile

Issue

Can anyone please tell me how do I select multiple options in checkboxlisttile.
Here I am able to click only one option. I want to set the status column in note table in database as completed when i check the particular item.
(Actually I want to select the item as completed and display it under another tab called completed. checkboxlisttile is created dynamically i.e from database. When a new note is added it is displayed in this listview.)

note_info.dart //this is the screen where notes are displayed i.e listview

import 'dart:io';
import 'package:vers2cts/models/note_model.dart';
import 'package:vers2cts/models/customer_model.dart';
import 'package:vers2cts/services/db_service.dart';
import 'package:vers2cts/utils/db_helper.dart';
import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';

import 'new_note.dart';


class Note_Info extends StatefulWidget{
  final String appBarTitle;
  final CustomerModel customer;

  //Note_Info();
  Note_Info(this. customer, this.appBarTitle);

  @override
  State<StatefulWidget> createState() {
    //return Note_InfoState();
   return Note_InfoState(this. customer,this.appBarTitle);
  }

}

class Note_InfoState extends State<Note_Info> {
  DBService dbService = DBService();
  List<NoteModel> noteList;
  int count = 0;

  static final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>();
  NoteModel note=NoteModel();
  String appBarTitle;
  CustomerModel customer=new CustomerModel();
  Note_InfoState(this.customer, this.appBarTitle);
 

  bool rememberMe = false;
  DateTime _date = DateTime.now();
  TextEditingController custfNameController = TextEditingController();

  @override
  void initState() {
    super.initState();
  }


  @override
  Widget build(BuildContext context) {
  updateListView();
    if (noteList == null) {
      noteList = List<NoteModel>();
      updateListView();
    }

    TextStyle titleStyle = Theme.of(context).textTheme.subhead;
    var height = MediaQuery.of(context).size.height;
    var name=customer.first_name+" "+customer.last_name;
    custfNameController.text = name;

    return DefaultTabController(
        length: 4,
        child: Scaffold(
            appBar: AppBar(
              actions: [
                IconButton(
                  icon: Icon(
                    Icons.add,

                  ),
                  onPressed: () {
                    Navigator.of(context).push(MaterialPageRoute(
                        builder: (BuildContext context) => NewNote(customer,note)));
                  },
                )
              ],
            ),
            body: Container(
              child: Column(
                  children: <Widget>[
                    TextField(controller: custfNameController,
                        style: TextStyle(
                            fontSize: 20.0, fontWeight: FontWeight.bold),

                        textAlign: TextAlign.center),
                    Padding(
                      padding: const EdgeInsets.all(15.0),
                      child: Row(children: [
                        ImageProfile(customer.cust_photo),
                        Padding(
                          padding: const EdgeInsets.only(left: 30.0),
                          child: IconButton(
                            icon: Icon(
                              Icons.call,
                              color: Colors.green,
                              size: 45,
                            ),
                            onPressed: () {

                            },
                          ),
                        ),

                      ],),
                    ),

                    SizedBox(
                      height: 50,
                      child: AppBar(
                        bottom: TabBar(
                          tabs: [
                            Tab(
                              text: "All",
                              
                            ),
                            Tab(
                              text: "Pending",
                             
                            ),
                            Tab(
                              text: "Cancelled",
                              
                            ),
                            Tab(
                              text: "Completed",
                              
                            ),
                          ],
                        ),
                      ),
                    ),

                    // create widgets for each tab bar here
                    Expanded(
                      child: TabBarView(
                        children: [
                          // first tab bar view widget
                          Container(
                              child: getNotecheckList()
                          ),

                          // second tab bar view widget
                          Container(

                          ),


                          Container(
                            child: Center(
                              child: Text(
                                'Cancelled',
                              ),
                            ),
                          ),
                          Container(

                            child: Center(
                              child: Text(
                                'Completed',
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Container(
                        height: 55.0,
                        width: 200,
                        child: RaisedButton(
                          elevation: 2,

                          shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(20)),
                          color: Theme
                              .of(context)
                              .primaryColorDark,
                          textColor: Colors.white,
                          child: Text('Save', textScaleFactor: 1.5,),
                          onPressed: () {
                            setState(() {
                              //_reset();
                            });
                          },
                        ),
                      ),
                    ),
                  ]
              ),
            )
        ));
  }

  Widget ImageProfile(String fileName) {
    return Center(
      child: CircleAvatar(
          radius: 80.0,
          backgroundImage:  fileName == null
              ?AssetImage('images/person_icon.jpg')
              :FileImage(File(customer.cust_photo))),

    );

  }
  Future<void> updateListView() {
    final Future<Database> dbFuture = DB.init();
    dbFuture.then((database) {
      int cid=customer.cust_id;

      Future<List<NoteModel>> noteListFuture = dbService.getCustomerNotes(cid);
      noteListFuture.then((noteList) {

        setState(() {
          this.noteList = noteList;
          this.count = noteList.length;
        });
      });
    });
  }
  int _isChecked=-1;

  ListView getNotecheckList() {

    return ListView.builder(
        itemCount: count,
        itemBuilder: (BuildContext context, int position) {



        return Card(
          color: Colors.white,
          elevation: 2.0,
          child: CheckboxListTile(
            title: Text(this.noteList[position].note),
            subtitle: Text(this.noteList[position].actn_on),
            //secondary: const Icon(Icons.web),
            
            value: position== _isChecked,
            onChanged: (bool value) {
              setState(() {
               _isChecked = value?position:-1;

              });
            },

            controlAffinity: ListTileControlAffinity.leading,
                ),
            );
          },
         );
        }
  }

new_note.dart //this is where new note is added.

import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:smooth_star_rating/smooth_star_rating.dart';
import 'package:intl/intl.dart';
import 'package:vers2cts/models/customer_model.dart';
import 'package:vers2cts/models/note_model.dart';
import 'package:vers2cts/services/db_service.dart';
import 'package:vers2cts/utils/form_helper.dart';

class NewNote extends StatefulWidget{
  final NoteModel note;
  final CustomerModel customer;

  NewNote(this.customer,this. note);
//Dropdown
/*
 final String label;
   final Function(Color) onChanged;
  final double height;
  final double width;

  NewNote.fordropdwn({
    Key key,
    this.onChanged,
    this.height = 25,
    this.width = 150,
    this.label,
  }) : super(key: key);*/
  @override
  State<StatefulWidget> createState() {
    //return New_NoteState(this.customer);
    return New_NoteState(this.customer,this.note);
  }

}
class New_NoteState extends State<NewNote> with SingleTickerProviderStateMixin{
  New_NoteState(this.customer,this.note);
  NoteModel note=new NoteModel();
  CustomerModel customer=new CustomerModel();
  TextEditingController NoteController=TextEditingController();
  TextEditingController custfNameController = TextEditingController();
  DateTime _reminderDate = DateTime.now();
  DBService dbService=new DBService();

  SpeedDial _speedDial(){
    return SpeedDial(
      // child: Icon(Icons.add),
      animatedIcon: AnimatedIcons.add_event,

      animatedIconTheme: IconThemeData(size: 24.0),
      backgroundColor: Colors.yellow,
      curve: Curves.easeInCirc,
      children: [
        SpeedDialChild(
          child: Icon(Icons.location_on,color: Colors.yellow,),
          //backgroundColor: Theme.of(context).primaryColor,
          label: 'Add Location',
          //labelBackgroundColor:Theme.of(context).primaryColor,

        ),
        SpeedDialChild(
          child: Icon(Icons.keyboard_voice),
          //backgroundColor: Colors.yellow,
          label: 'Add voice',
          //labelBackgroundColor: Colors.yellow

        ),
        SpeedDialChild(
          child: Icon(Icons.attachment_outlined,color :Colors.redAccent),
          //backgroundColor:Theme.of(context).primaryColorLight,
          label: 'Add File',
          // labelBackgroundColor: Theme.of(context).primaryColorLight

        ),
        SpeedDialChild(
          child: Icon(Icons.image,color: Colors.lightBlue,),
          //backgroundColor: Colors.yellow,
          label: 'Add Image',
          // labelBackgroundColor: Colors.yellow,

        ),
      ],
    );
  }

  //for DropDownMenu
  Color value=Colors.red;
  final List<Color> colors = [
    Colors.red,
    Colors.blue,
    Colors.green,
    Colors.yellow,
    Colors.pink,
    Colors.purple,
    Colors.brown,
  ];

  //for Switch
  bool isSwitched = false;
  var textValue = 'Switch is OFF';

  void toggleSwitch(bool value) {

    if(isSwitched == false)
    {
      setState(() {
        isSwitched = true;
        note.rmnd_ind=1;
        //this.note.remindOn = _reminderDate.toString();

      });
    }
    else
    {
      setState(() {
        isSwitched = false;
        note.rmnd_ind=0;
      });
    }
  }
  @override
  Widget build(BuildContext context) {
    var height = MediaQuery.of(context).size.height;
    var width = MediaQuery.of(context).size.width;
    var name=customer.first_name+customer.last_name;
    custfNameController.text = name;

    return WillPopScope(

        onWillPop: () {
          // Write some code to control things, when user press Back navigation button in device navigationBar
          moveToLastScreen();
        },
        child: Scaffold(
          appBar:AppBar(),
          body:ListView(
            children: <Widget>[
              SizedBox(
                height: 2.0,
              ),
              TextField(controller: custfNameController,
                  style: TextStyle(
                      fontSize: 20.0, fontWeight: FontWeight.bold),

                  textAlign: TextAlign.center),
              Align(
                alignment: Alignment.centerLeft,
                child: Text("Add New",textAlign: TextAlign.left,
                  style: TextStyle(fontSize: 22,fontWeight: FontWeight.bold),),
              ),

              SizedBox(
                height: 2.0,
              ),
              Divider(),
              SizedBox(
                height: 2.0,
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: TextField(
                  controller: NoteController,
                  decoration: InputDecoration(
                      border: OutlineInputBorder(
                        borderSide: const BorderSide(width: 2.0),)),
                  keyboardType: TextInputType.multiline,
                  minLines: 5,//Normal textInputField will be displayed
                  maxLines: 5, // when user presses enter it will adapt to it
                  onChanged: (value) {
                    this.note.note = value;
                  },

                ),
              ),
              TableCalendar(
                selectedDayPredicate: (day) {
                  return isSameDay(_reminderDate, day);
                },
                onDaySelected: (selectedDay, focusedDay) {
                  setState(() {
                    String _reminderDate = DateFormat('dd-MM-yyyy').format(selectedDay);
                    note.actn_on=_reminderDate.toString();

                  });
                },// Set initial date

                focusedDay: DateTime.now(),
                firstDay: DateTime.utc(2010, 10, 16),
                lastDay: DateTime.utc(2030, 3, 14),),

              SizedBox(
                height: height*0.03,
              ),
              Padding(
                padding: const EdgeInsets.all(10.0),
                child: Row(//mainAxisAlignment: MainAxisAlignment.start,
                  children: <Widget>[
                    Text("Remind me",style: TextStyle(fontSize: 20),),

                    Padding(
                      padding: const EdgeInsets.only(left:80.0),
                      child: Container(
                        child: Switch(
                          onChanged: toggleSwitch,
                          value: isSwitched,

                          //activeColor: Colors.blue,
                          //activeTrackColor: Colors.yellow,
                          //inactiveThumbColor: Colors.redAccent,
                          //inactiveTrackColor: Colors.orange,
                        ),
                      ),
                    ),

                  ],),
              ),
              Padding(
                padding: const EdgeInsets.all(10.0),
                child: Row(mainAxisAlignment: MainAxisAlignment.start,
                    children:<Widget>[
                      Text("Priority",style: TextStyle(fontSize: 20.0),),
                      Padding(
                        padding: const EdgeInsets.only(left:20.0),
                        child: Container(
                          child: SmoothStarRating(
                            size: height=50.0,
                            allowHalfRating: false,
                            onRated: (value) {
                              this.note.prty=value;
                              print("rating value -> $value");

                            },
                          ),
                        ),
                      )]),
              ),

              Padding(
                padding: const EdgeInsets.all(10.0),
                child: Row(mainAxisAlignment: MainAxisAlignment.start,
                  children: <Widget>[

                    Text("Color",style: TextStyle(fontSize: 20),),
                    Padding(
                      padding: const EdgeInsets.only(left:80.0),
                      child: Container(
                        child: DropdownButton<Color>(
                          value: value,
                          //hint: Text(widget.label ?? ''),
                          onChanged: (color) {
                            setState(() => value = color);
                            //widget.onChanged(color);
                          },
                          items: colors.map((e) => DropdownMenuItem(
                            value: e,
                            child: Container(
                              // width: 60.0,
                              //height: 10.0,
                              width: 60.0,
                              // height: widget.height,
                              color: e,
                            ),
                          ),
                          )
                              .toList(),
                        ),
                      ),
                    ),

                  ],),
              ),

              SizedBox(
                height: height*0.08,
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Container(
                  height: 55.0,
                  width: 200,
                  child: RaisedButton(
                    elevation: 2,

                    shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(20)),
                    color: Theme.of(context).primaryColorDark,
                    textColor: Colors.white,
                    child: Text('Save',textScaleFactor: 1.5,),
                    onPressed: (){
                      setState(() {
                        _save();
                      });
                    },
                  ),
                ),
              ),



            ],



          ),
          floatingActionButton:_speedDial(),
          
        ));

  }
  void moveToLastScreen() {
    Navigator.pop(context, true);
  }

  void _save() async {
    moveToLastScreen();
    note.cust_id=customer.cust_id;
    print(customer.cust_id);
    print(note.cust_id);
  
    int result;
    if (note.note_id != null) {  // Case 1: Update operation
      result = await dbService.updateNote(note);
    } else { // Case 2: Insert Operation
      result = await dbService.insertNote(note);
    }

    if (result != 0) {  // Success
      FormHelper.showAlertDialog(context,'Status', 'Note Saved Successfully');
    } else {  // Failure
      FormHelper.showAlertDialog(context,'Status', 'Problem Saving Note');
    }

  }
}

db_service.dart

import 'package:vers2cts/models/customer_model.dart';
import 'package:vers2cts/models/languages_model.dart';
import 'package:vers2cts/models/note_model.dart';
import 'package:vers2cts/models/user_model.dart';
import 'package:vers2cts/utils/db_helper.dart';

class DBService {
  Future<int> insertNote(NoteModel note) async {
    await DB.init();
    var result = await DB.insert(NoteModel.table, note);
    return result;
  }
  Future<List<NoteModel>> getCustomerNotes(int customer) async {
    await DB.init();
    var res = await DB.rawQuery("note WHERE cust_id = '$customer'");
    int count = res.length;
    List<NoteModel> notelist = List<NoteModel>();
    // For loop to create a 'Note List' from a 'Map List'
    for (int i = 0; i < count; i++) {
      notelist.add(NoteModel.fromMap(res[i]));
    }
    return notelist;
  }
}

note_model.dart

import 'model.dart';

class NoteModel extends Model {
  static String table = 'note';
  bool isSelected=false;
  int note_id;
  int cust_id;
  String note;
  String actn_on;
  int rmnd_ind;
  double prty;
  String colr;
  String sts;

  int id;
  String cre_date;
  String cre_by;
  String mod_date;
  String mod_by;
  int txn_id;
  int delete_ind;

  NoteModel({
    this.note_id,
    this.cust_id,
    this.note,
    this.actn_on,
    this.rmnd_ind,
    this.prty,
    this.colr,
    this.sts,

    this.id,
    this.cre_date,
    this.cre_by,
    this.mod_date,
    this.mod_by,
    this.txn_id,
    this.delete_ind
  });

  static NoteModel fromMap(Map<String, dynamic> map) {
    return NoteModel(
      note_id: map["note_id"],
      cust_id: map['cust_id'],
      note: map['note'].toString(),
      actn_on: map['actn_on'].toString(),
      rmnd_ind: map['rmnd_ind'],
      prty: map['prty'],
      colr: map['colr'].toString(),
      sts: map['sts'].toString(),


      id: map['id'],
      cre_date: map['cre_date'].toString(),
      cre_by: map['cre_by'].toString(),
      mod_date: map['mod_date'].toString(),
      mod_by: map['mod_by'].toString(),
      txn_id: map['txn_id'],
      delete_ind: map['delete_ind'],
    );
  }

  Map<String, dynamic> toMap() {
    Map<String, dynamic> map = {
      'note_id': note_id,
      'cust_id': cust_id,
      'note':note,
      'actn_on': actn_on,
      'rmnd_ind': rmnd_ind,
      'prty': prty,
      'colr': colr,
      'sts':sts,


      'id': id,
      'cre_date': cre_date,
      'cre_by': cre_by,
      'mod_date':mod_date,
      'mod_by':mod_by,
      'txn_id':txn_id,
      'delete_ind': delete_ind

    };

    if (note_id != null) {
      map['note_id'] = note_id;
    }
    return map;
  }
}

db_helper.dart

import 'dart:async';
import 'package:vers2cts/models/model.dart';
import 'package:path/path.dart' as p;
import 'package:sqflite/sqflite.dart';

abstract class DB {
  static Database _db;

  static int get _version => 1;

  static Future<Database> init() async {
    if (_db != null) {
      return _db;
    }

    try {
      var databasesPath = await getDatabasesPath();
      String _path = p.join(databasesPath, 'CTS.db');
      _db = await openDatabase(_path, version: _version, onCreate: onCreate);
      print('db location:'+_path);

    } catch (ex) {
      print(ex);
    }
  }

  static void onCreate(Database db, int version) async {

    await db.execute(
        'CREATE TABLE note (note_id INTEGER PRIMARY KEY,cust_id INTEGER, '
            'note TEXT, '
            'actn_on TEXT, rmnd_ind INTEGER, prty REAL, colr TEXT,'
            'sts TEXT,'
            'id INTEGER, cre_date TEXT,cre_by TEXT, mod_date TEXT,mod_by TEXT, txn_id INTEGER, delete_ind INTEGER)');

  }

  static Future<List<Map<String, dynamic>>> query(String table) async =>
      _db.query(table);

  static Future<int> insert(String table, Model model) async =>
      await _db.insert(table, model.toMap());
  static Future<Batch> batch() async => _db.batch();
  static Future<List<Map<String, dynamic>>> rawQuery(String table) async =>
      _db.query(table);
}

Solution

You need to store what all values are selected from user and then play with it.
For example –

var selectedIndexes = [];

  ListView getNotecheckList() {
    return ListView.builder(
        itemCount: count,
        itemBuilder: (_, int index) {
        return Card(
          color: Colors.white,
          elevation: 2.0,
          child: CheckboxListTile(
            title: Text(this.noteList[position].note),
            subtitle: Text(this.noteList[position].actn_on),            
            value: selectedIndexes.contains(index),
            onChanged: (_) {
             if (selectedIndexes.contains(index)) {
              selectedIndexes.remove(index);   // unselect
             } else {
              selectedIndexes.add(index);  // select
              }
            },
            controlAffinity: ListTileControlAffinity.leading,
          ),
        );
      },
    );
  }

Answered By – Pushpendra

Answer Checked By – Dawn Plyler (FlutterFixes Volunteer)

Leave a Reply

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