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,
),
);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.