Flutter - how to implement checkboxes with Bloc - flutter

I am trying to create a list with checkboxes with a Select All option at the top.
The current code works fine with the SelectAll/De-selectAll.
The problem is, even the individual checkboxes are working as a SelectAll checkbox. Meaning, any checkbox when selected/de-selected, selects/de-selects all other checkboxes.
HomePage:
import 'dart:convert';
import 'dart:io';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:http/http.dart' as http;
import 'package:boost/resources/toast_display.dart';
import 'package:flutter/material.dart';
import 'package:internet_connection_checker/internet_connection_checker.dart';
import '../models/meetings.dart';
import '../models/test.dart';
import '../resources/app_strings.dart';
import '../utils/accesss_token_manager.dart';
import '../utils/app_urls.dart';
import '../utils/constants.dart';
import '../utils/routes.dart';
import '../widgets/cubit/notification_cubit.dart';
class NewHomeScreen extends StatefulWidget {
const NewHomeScreen({Key? key}) : super(key: key);
#override
State<NewHomeScreen> createState() => _NewHomeScreenState();
}
class _NewHomeScreenState extends State<NewHomeScreen> {
Meeting meeting = Meeting();
List<WeeklyMeeting> weeklyMeetingsList = [];
bool isSelectAll = false;
bool isMeetingSelected = false;
final allowNotifications = NotificationSetting(title: 'Allow Notifications');
final notifications = [
NotificationSetting(title: 'Show Message'),
NotificationSetting(title: 'Show Group'),
NotificationSetting(title: 'Show Calling'),
];
#override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Test'),
),
body: ListView(
children: [
buildToggleCheckbox(allowNotifications),
const Divider(),
...notifications.map(buildSingleCheckbox).toList(),
],
),
);
Widget buildToggleCheckbox(NotificationSetting notification) => buildCheckbox(
notification: notification,
onClicked: () {
BlocProvider.of<NotificationSelectionCubit>(context)
.toggleAllowNotificationSelection();
});
Widget buildSingleCheckbox(NotificationSetting notification) => buildCheckbox(
notification: notification,
onClicked: () {
BlocProvider.of<NotificationSelectionCubit>(context)
.toggleIndividualNotificationSelection();
},
);
Widget buildCheckbox({
required NotificationSetting notification,
required VoidCallback onClicked,
}) {
return BlocBuilder<NotificationSelectionCubit, NotificationState>(
builder: (context, state) {
return ListTile(
onTap: onClicked,
/// stack is used only to give the checkboxes a radio button look, when a checkbox
is selected it will look like a checked radio button, and when de-selected, it will
look like an unselected radio button.
leading: Stack(children: [
Visibility(
visible: state.value,
child: Checkbox(
shape: const CircleBorder(),
value: !state.value,
onChanged: (val) {
onClicked();
}),
),
Visibility(
visible: !state.value,
child: IconButton(
onPressed: () {
onClicked();
},
icon: const Icon(Icons.radio_button_checked),
),
)
]),
title: Text(
notification.title,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
);
},
);
}
}
NotificationSelectionCubit class
class NotificationSelectionCubit extends Cubit<NotificationState> {
NotificationSelectionCubit()
: super(NotificationState(value: false, allowNotification: false));
final allowNotifications = NotificationSetting(title: 'Allow Notifications');
final notifications = [
NotificationSetting(title: 'Show Message'),
NotificationSetting(title: 'Show Group'),
NotificationSetting(title: 'Show Calling'),
];
void toggleIndividualNotificationSelection() {
for (var notification in notifications) {
return emit(NotificationState(
value: !state.value, allowNotification: state.allowNotification));
}
}
void toggleAllowNotificationSelection() => emit(NotificationState(
value: state.allowNotification,
allowNotification: !state.allowNotification));
}
And
class NotificationState {
bool value;
bool allowNotification;
NotificationState({required this.value, required this.allowNotification});
}

You can do it like this:
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CheckBoxCubit(),
child: MaterialApp(
home: Scaffold(
body: BlocBuilder<CheckBoxCubit, CheckBoxState>(
builder: (context, state) {
return Center(
child: ListView.builder(
itemCount: state.checkBoxes.length,
itemBuilder: (context, index) {
return CheckboxListTile(
title: Text(state.checkBoxes[index]['name']),
value: state.checkBoxes[index]['isChecked'],
onChanged: (newValue) => context.read<CheckBoxCubit>().toggleNotification(index, newValue),
);
},
),
);
},
),
),
),
);
}
}
State file is as follows:
class CheckBoxState {
List<Map> checkBoxes;
CheckBoxState({
required this.checkBoxes,
});
CheckBoxState copyWith({
final List<Map>? checkBoxes,
}) {
return CheckBoxState(
checkBoxes: checkBoxes ?? this.checkBoxes,
);
}
}
Cubit file is as follow:
class CheckBoxCubit extends Cubit<CheckBoxState> {
CheckBoxCubit()
: super(CheckBoxState(
checkBoxes: [
{
"name": "Foobball",
"isChecked": false,
},
{
"name": "Baseball",
"isChecked": false,
},
],
));
void toggleNotification(int index, bool? newValue) => emit(
state.copyWith(
checkBoxes: List.from(state.checkBoxes)..[index]['isChecked'] = newValue,
),
);
}

Related

How to block the repeated item in flutter?

I saw this code in KindaCode. This is link ( https://www.kindacode.com/article/flutter-hive-database/#single__comments ) . I want the added item not to be added again. How can I do that? This code, we just add items and delete and olsa upgrade. We just write the name and quantity and adding the item. But if i write the same name as the other one, adds again.
// main.dart
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Hive.initFlutter();
await Hive.openBox('shopping_box'); //verileri icerisinde barındırıcak kutuyu olusturma
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'KindaCode.com',
theme: ThemeData(
primarySwatch: Colors.green,
),
home: const HomePage(),
);
}
}
// Home Page
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<Map<String, dynamic>> _items = [];
final _shoppingBox = Hive.box('shopping_box');
#override
void initState() {
super.initState();
_refreshItems(); // Load data when app starts
}
// Get all items from the database
void _refreshItems() {
final data = _shoppingBox.keys.map((key) {
final value = _shoppingBox.get(key);
return {"key": key, "name": value["name".toLowerCase()], "quantity": value['quantity']};
}).toList(); //verileri listede gosterme
setState(() {
_items = data.reversed.toList(); //en sondan en eskiye dogru siralamak icin reversed
// we use "reversed" to sort items in order from the latest to the oldest
});
}
// Create new item
Future<void> _createItem(Map<String, dynamic> newItem) async {
await _shoppingBox.add(newItem); //yeni veri olusturma
_refreshItems(); // update the UI
}
// Retrieve a single item from the database by using its key
// Our app won't use this function but I put it here for your reference
// Update a single item
Future<void> _updateItem(int itemKey, Map<String, dynamic> item) async {
await _shoppingBox.put(itemKey, item); //tablo icerisine veriyi koyma
_refreshItems(); // Update the UI
}
// Delete a single item
Future<void> _deleteItem(int itemKey) async {
await _shoppingBox.delete(itemKey);
_refreshItems(); // update the UI
// Display a snackbar
ScaffoldMessenger.of(context).showSnackBar( //ekranin alt kisminda itemin silindigini belirtme
const SnackBar(content: Text('An item has been deleted')));
}
// TextFields' controllers
final TextEditingController _nameController = TextEditingController();
final TextEditingController _quantityController = TextEditingController();
void _showForm(BuildContext ctx, int? itemKey) async { //yeni item eklerken ve butona basildiginda tetiklenen flotingbutton
// itemKey == null -> create new item
// itemKey != null -> update an existing item
if (itemKey != null) { //itemi guncelleme
final existingItem =
_items.firstWhere((element) => element['key'] == itemKey);
_nameController.text = existingItem['name'];
_quantityController.text = existingItem['quantity'];
}
showModalBottomSheet(
context: ctx,
elevation: 5,
isScrollControlled: true,
builder: (_) => Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(ctx).viewInsets.bottom,
top: 15,
left: 15,
right: 15),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
TextField(
controller: _nameController,
decoration: const InputDecoration(hintText: 'Name'),
),
const SizedBox(
height: 10,
),
TextField(
controller: _quantityController,
keyboardType: TextInputType.number,
decoration: const InputDecoration(hintText: 'Quantity'),
),
const SizedBox(
height: 20,
),
ElevatedButton( //here the create or upgrade the item
onPressed: () async {
// Save new item
if (itemKey == null) { //yeni item
if() {
_createItem({
"name": _nameController.text,
"quantity": _quantityController.text
});
}
}
// update an existing item
if (itemKey != null) {
_updateItem(itemKey, {
'name': _nameController.text.trim(),
'quantity': _quantityController.text.trim()
});
}
// Clear the text fields
_nameController.text = '';
_quantityController.text = '';
Navigator.of(context).pop(); // Close the bottom sheet
},
child: Text(itemKey == null ? 'Create New' : 'Update'),
),
const SizedBox(
height: 15,
)
],
),
));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('KindaCode.com'),
),
body: _items.isEmpty
? const Center(
child: Text(
'No Data',
style: TextStyle(fontSize: 30),
),
)
: ListView.builder(
// the list of items
itemCount: _items.length,
itemBuilder: (_, index) {
final currentItem = _items[index];
return Card(
color: Colors.orange.shade100,
margin: const EdgeInsets.all(10),
elevation: 3,
child: ListTile(
title: Text(currentItem['name']),
subtitle: Text(currentItem['quantity'].toString()),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
// Edit button
IconButton(
icon: const Icon(Icons.edit), //düzenleme butonu
onPressed: () =>
_showForm(context, currentItem['key'])),
// Delete button
IconButton(
icon: const Icon(Icons.delete),
onPressed: () => _deleteItem(currentItem['key']),
),
],
)),
);
}),
// Add new item button
floatingActionButton: FloatingActionButton( //ekranin alt kosesinde bulunan ekleme butonu
onPressed: () => _showForm(context, null),
child: const Icon(Icons.add),
),
);
}
} ```

How to Display selected data to another page in flutter

Hi i am new to flutter i have used sample database to get data of 10 users. this data is displayed in list tile with leading item is checkbox (to select / deselect). Now i need help in displaying the selected data on to the other page once i press cart button in the appbar..
here's my main
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_application_http_get/example.dart';
import 'package:flutter_application_http_get/screen.dart';
import 'package:flutter_application_http_get/selected.dart';
import 'package:flutter_application_http_get/sunday_state.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Sunday(),
);
}
}
class Sunday extends StatefulWidget {
const Sunday({Key? key}) : super(key: key);
#override
_SundayState createState() => _SundayState();
}
API Called Here
class _SundayState extends State<Sunday> {
var users = [];
Future getUserData() async {
var res =
await http.get(Uri.https("jsonplaceholder.typicode.com", "users"));
var jsonData = jsonDecode(res.body) as List;
setState(() {
users = jsonData;
});
}
#override
void initState() {
super.initState();
getUserData();
}
final notification = [SundayCheckBoxState()];
late final post;
data from post if checked printed..
getCheckboxItems() {
users.forEach((post) {
if (post['checked'] == true) {
print(post);
}
});
}
here in when onpressed i need to display the checked data on to the other page
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("User Data"),
actions: [
IconButton(
onPressed: getCheckboxItems,
icon: Icon(Icons.shopping_cart))
],
),
body: Container(
child: Card(
margin: EdgeInsets.all(20.0),
child: ListView.builder(
itemCount: users.length,
itemBuilder: (context, i) {
final post = users[i];
return Card(
elevation: 5,
child: Padding(
padding: const EdgeInsets.all(12.0),
child: ListView(shrinkWrap: true, children: [
ListTile(
leading: Checkbox(
value: post['checked'] ?? false,
onChanged: (value) {
setState(() {
post['checked'] = value;
});
}),
title: Text("${post['id']}" + "${post['name']}"),
),
])
));
}),
),
),
);
}
You can try this logic it worked for me :
var _isSelectedCheckBoxArr = [];
var _addSelectedValueArr = [];
Checkbox(
value: _isSelectedCheckBoxArr[i],
materialTapTargetSize:
MaterialTapTargetSize
.shrinkWrap,
onChanged: (s) {
setState(() {
_isSelectedCheckBoxArr[i] =
!_isSelectedCheckBoxArr[i];
});
print(
"$_tag onChanged: (s): $s");
if (s) {
setState(() {
_addSelectedValueArr.add(
"${users[i]}");
});
} else if (!s) {
setState(() {
_addSelectedValueArr
.remove(
users[i]);
});
}
}),
Then on the click of cart button pass the _addSelectedValueArr array in the constructor of the screen you want to display.

Save Multi Select Choice Chips selected/unselected state in an alert-dialog

I am filtering results in my application based off of the multichoice chips that are selected. I have it filtering results properly, however when I select the done button in the alert dialog it does not save the selected state of the choice chips. It also does not clear the selected states of the choice chips when I hit the clear button. Any recommendations?
MultiFilterChoiceChips Class:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class MultiFilterChips extends StatefulWidget {
final List<String> filterList;
final Function(List<String>) onSelectionChanged;
MultiFilterChips(this.filterList, {this.onSelectionChanged});
#override
_MultiFilterChipsState createState() => _MultiFilterChipsState();
}
class _MultiFilterChipsState extends State<MultiFilterChips> {
List<String> selectedFilters = List();
_buildFilterList() {
List<Widget> filters = List();
widget.filterList..forEach((item){
filters.add(Container(
padding: const EdgeInsets.all(2.0),
child: ChoiceChip(
label: Text('$item'),
selected: selectedFilters.contains(item),
onSelected: (selected) {
setState(() {
selectedFilters.contains(item)
? selectedFilters.remove(item)
: selectedFilters.add(item);
widget.onSelectionChanged(selectedFilters);
});
},
),
));
});
return filters;
}
#override
Widget build(BuildContext context) {
return Wrap(
children: _buildFilterList(),
);
}
}
Filter Pressed (App Bar Icon) Alert Dialog:
_filterPressed() {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
scrollable: true,
title: Text('Filter Scouts'),
content: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Rank:'),
_multiFilterRankChipState(),
Padding(padding: EdgeInsets.all(5)),
Text('Patrol:'),
_multiFilterPatrolChipState(),
],
)),
actions: <Widget>[
FlatButton(
child: Text("Clear"),
onPressed: () {
filter = ""; //ranks filter string to send to the sqlite database
pfilter = ""; //patrol filter string to send to the sqlite database
setState(() {
selectedRanks.clear(); //List<String> that holds the selected ranks
selectedPatrols.clear(); //List<String> that holds the selected patrols
//sends the query to the database and resets the future list builder state
// back to initial state without filters
_searchResults(searchText);
});
},
),
FlatButton(
child: Text("Done"),
onPressed: () {
Navigator.of(context).pop();
})
],
);
});
}
Rank MultiFilter Call:
_multiFilterRankChipState() {
return MultiFilterChips(ranks, onSelectionChanged: (selectedList) {
setState(() {
//selectedList = selectedRanks;
selectedRanks = selectedList;
debugPrint("SELECTED LIST ${selectedRanks.toString()}");
_RanksFilterSet();
});
});
}
For getting the list of Patrols I am getting the distinct list from the sqlite database as the list patrols change overtime thus using a future builder to get the list of strings:
Patrol MultiFilter Call:
_multiFilterPatrolChipState() {
return Container(
child: FutureBuilder<List<String>>(
future: patrols(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return MultiFilterChips(snapshot.data,
onSelectionChanged: (selectedList) {
setState(() {
selectedPatrols = selectedList;
_PatrolFilterSet();
});
});
}
return Container(
alignment: AlignmentDirectional.center,
child: new CircularProgressIndicator(
strokeWidth: 7,
));
},
),
);
}
Let me know if you need more code! Thanks!
You can store the selected items in a Map. In this sample, multi-select mode will start on long press of an item. Multi-select mode will stop when there's no selected items left.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var selectMode = false;
Map<String, bool> listItemSelected = {
'List 1': false,
'List 2': false,
'List 3': false,
'List 4': false,
'List 5': false,
'List 6': false,
'List 7': false,
'List 8': false,
'List 9': false,
};
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: ListView(
children: listItemSelected.keys.map((key) {
return Card(
child: GestureDetector(
onTap: () {
// if multi-select mode is true, tap should select List item
if (selectMode && listItemSelected.containsValue(true)) {
debugPrint('onTap on $key');
setState(() {
listItemSelected[key] = !listItemSelected[key];
});
} else {
// Stop multi-select mode when there's no more selected List item
debugPrint('selectMode STOP');
selectMode = false;
}
},
// Start List multi-select mode on long press
onLongPress: () {
debugPrint('onLongPress on $key');
if (!selectMode) {
debugPrint('selectMode START');
selectMode = true;
}
setState(() {
listItemSelected[key] = !listItemSelected[key];
});
},
child: Container(
// Change List item color if selected
color: (listItemSelected[key])
? Colors.lightBlueAccent
: Colors.white,
padding: EdgeInsets.all(16.0),
child: Text(key),
),
),
);
}).toList(),
),
),
);
}
}
Demo

Dynamic list of check box tile in alert dialog not working

There is no clear answer on how to implement a checkbox tile in a dialog and set the state to work.
A print statement is working in setting the state of the checkbox is not changing, but other statements are working. Where can I find the answer?
I am using a dialog with multiple check boxes for multi select. Is there another of implementing multiselect in Flutter?
child: TextFormField(
decoration: InputDecoration(
labelText: 'Team Leader',
labelStyle: TextStyle(color: Colors.black)),
controller: teamLeaderController,
enabled: false,
style: TextStyle(color: Colors.black),
),
onTap: () {
showDialog(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return CheckBoxDialog(context, teamLeader,
"Choose Team Leader", teamLeaderController, onSubmit);
});
}),
class CheckBoxState extends State<CheckBoxDialog> {
BuildContext context;
List<String> places;
String title;
TextEditingController con;
bool state;
CheckBoxState(this.context, this.places, this.title, this.con);
#override
void initState() {
super.initState();
state = false;
}
#override
Widget build(BuildContext context) {
return new AlertDialog(
title: new Text(title),
content:
Column(children: getMultiSelectOption(context, places, con, state)),
actions: <Widget>[
FlatButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
}),
FlatButton(
child: Text('Ok'),
onPressed: () {
widget.onSubmit("");
Navigator.of(context).pop();
})
],
);
}
List<Widget> getMultiSelectOption(BuildContext context, List<String> places,
TextEditingController con, bool state) {
List<Widget> options = [];
List<String> selectedList = [];
for (int i = 0; i < places.length; i++) {
options.add(CheckboxListTile(
title: Text(places[i]),
value: selectedList.contains(places[i]),
onChanged: (bool value) {
print("on change: $value title: ${places[i]}");
setState(() {
if (value) {
selectedList.add(places[i]);
} else {
selectedList.remove(places[i]);
}
print("contains: ${selectedList.contains(places[i])}");
print("status: $value");
});
}));
}
return options;
}
}
Suppose you have a Dialog with some Widgets such as RadioListTile, DropdowButton… or anything that might need to be updated WHILE the dialog remains visible, how to do it?
Look at this example here.
https://www.didierboelens.com/2018/05/hint-5-how-to-refresh-the-content-of-a-dialog-via-setstate/
Suppose you have a Dialog with some Widgets such as RadioListTile, DropdowButton… or anything that might need to be updated WHILE the dialog remains visible, how to do it?
Difficulty: Beginner
Background
Lately I had to display a Dialog to let the user select an item from a list and I wanted to display a list of RadioListTile.
I had no problem to show the Dialog and display the list, via the following source code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
class Sample extends StatefulWidget {
#override
_SampleState createState() => new _SampleState();
}
class _SampleState extends State<Sample> {
List<String> countries = <String>['Belgium','France','Italy','Germany','Spain','Portugal'];
int _selectedCountryIndex = 0;
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_){_showDialog();});
}
_buildList(){
if (countries.length == 0){
return new Container();
}
return new Column(
children: new List<RadioListTile<int>>.generate(
countries.length,
(int index){
return new RadioListTile<int>(
value: index,
groupValue: _selectedCountryIndex,
title: new Text(countries[index]),
onChanged: (int value) {
setState((){
_selectedCountryIndex = value;
});
},
);
}
)
);
}
_showDialog() async{
await showDialog<String>(
context: context,
builder: (BuildContext context){
return new CupertinoAlertDialog(
title: new Text('Please select'),
actions: <Widget>[
new CupertinoDialogAction(
isDestructiveAction: true,
onPressed: (){Navigator.of(context).pop('Cancel');},
child: new Text('Cancel'),
),
new CupertinoDialogAction(
isDestructiveAction: true,
onPressed: (){Navigator.of(context).pop('Accept');},
child: new Text('Accept'),
),
],
content: new SingleChildScrollView(
child: new Material(
child: _buildList(),
),
),
);
},
barrierDismissible: false,
);
}
#override
Widget build(BuildContext context) {
return new Container();
}
}
I was surprised to see that despite the setState in lines #34-36, the selected RadioListTile was not refreshed when the user tapped one of the items.
Explanation
After some investigation, I realized that the setState() refers to the stateful widget in which the setState is invoked. In this example, any call to the setState() rebuilds the view of the Sample Widget, and not the one of the content of the dialog. Therefore, how to do?
Solution
A very simple solution is to create another stateful widget that renders the content of the dialog. Then, any invocation of the setState will rebuild the content of the dialog.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
class Sample extends StatefulWidget {
#override
_SampleState createState() => new _SampleState();
}
class _SampleState extends State<Sample> {
List<String> countries = <String>['Belgium','France','Italy','Germany','Spain','Portugal'];
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_){_showDialog();});
}
_showDialog() async{
await showDialog<String>(
context: context,
builder: (BuildContext context){
return new CupertinoAlertDialog(
title: new Text('Please select'),
actions: <Widget>[
new CupertinoDialogAction(
isDestructiveAction: true,
onPressed: (){Navigator.of(context).pop('Cancel');},
child: new Text('Cancel'),
),
new CupertinoDialogAction(
isDestructiveAction: true,
onPressed: (){Navigator.of(context).pop('Accept');},
child: new Text('Accept'),
),
],
content: new SingleChildScrollView(
child: new Material(
child: new MyDialogContent(countries: countries),
),
),
);
},
barrierDismissible: false,
);
}
#override
Widget build(BuildContext context) {
return new Container();
}
}
class MyDialogContent extends StatefulWidget {
MyDialogContent({
Key key,
this.countries,
}): super(key: key);
final List<String> countries;
#override
_MyDialogContentState createState() => new _MyDialogContentState();
}
class _MyDialogContentState extends State<MyDialogContent> {
int _selectedIndex = 0;
#override
void initState(){
super.initState();
}
_getContent(){
if (widget.countries.length == 0){
return new Container();
}
return new Column(
children: new List<RadioListTile<int>>.generate(
widget.countries.length,
(int index){
return new RadioListTile<int>(
value: index,
groupValue: _selectedIndex,
title: new Text(widget.countries[index]),
onChanged: (int value) {
setState((){
_selectedIndex = value;
});
},
);
}
)
);
}
#override
Widget build(BuildContext context) {
return _getContent();
}
}

How can I handle a list of checkboxes dynamically created in flutter?

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?
Here's some sample code for CheckboxListTile. You can find more examples in the gallery.
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));
}
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']),
);
}),
);
}
}
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]),
));
}
}
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
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()}"),
),
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);
});
}
}
Screenshot (Null safe)
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(),
),
);
}
}
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
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,
);
}
}
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,
],
);
},
);
});