Atoms
Checkboxes
How to use
Let's say I want to create Buttons from array of string.
const List<String> continents = [
'Africa',
'Antarctica',
'Asia',
'Australia',
'Europe',
'North America',
'South America',
];
ButtonCheckBox<String>(
items: continents.map((e) => CheckboxItem(text: e, data: e)).toList(),
onChanged: (_) {},
),
Let's say I want to create checkbox Buttons for X
type. Type for which all buttons will be created, where value of all individual checkbox will be of that type.
Now let's assume We have type Language so here you can see example for that.
// Model/ Custom Type
class Language {
final String language;
final Difficulty difficulty;
const Language({
required this.language,
required this.difficulty,
});
}
enum Difficulty {
easy,
moderate,
hard,
}
// Array of that Model/ Custom Type
const List<Language> items = [
Language(
language: 'c / c++',
difficulty: Difficulty.easy,
),
Language(
language: 'python',
difficulty: Difficulty.easy,
),
Language(
language: 'dart',
difficulty: Difficulty.easy,
),
Language(
language: 'other',
difficulty: Difficulty.easy,
),
];
// Passing Model/ Custom Type in ButtonCheckBox
ButtonCheckBox<Language>(
items: items.map((e) => CheckboxItem(text: e.language, data: e)).toList(),
onChanged: (_) {},
),
In CheckboxItem you can pass initialValue
as true/ false for it's default value.
Other properties of ButtonCheckBox
- padding
- Pass padding to change padding around individual buttons
Source code
import 'package:flutter/material.dart';
import '../../helpers/constants.dart';
class CheckboxItem<T> {
final String text;
final bool initialValue;
final T data;
const CheckboxItem({
required this.text,
this.initialValue = false,
required this.data,
});
}
class ButtonCheckBox<T> extends StatefulWidget {
final List<CheckboxItem<T>> items;
final void Function(List<T>) onChanged;
final EdgeInsets? padding;
const ButtonCheckBox({
Key? key,
required this.items,
required this.onChanged,
this.padding,
}) : super(key: key);
@override
State<ButtonCheckBox<T>> createState() => _ButtonCheckBoxState<T>();
}
class _ButtonCheckBoxState<T> extends State<ButtonCheckBox<T>> {
final List<bool> _values = [];
final List<T> _selectedValues = [];
@override
void initState() {
assert(widget.items.isNotEmpty);
for (final item in widget.items) {
_values.add(item.initialValue);
if (item.initialValue) {
_selectedValues.add(item.data);
}
}
super.initState();
}
@override
Widget build(BuildContext context) {
return Wrap(
children: [
for (int index = 0; index < widget.items.length; index++)
Padding(
padding: widget.padding ?? rightPadding8 + bottomPadding8,
child: InkWell(
onTap: () {
setState(() {
_values[index] = !_values[index];
});
updateSelectedValues(index);
widget.onChanged(_selectedValues);
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Checkbox(
value: _values[index],
onChanged: (value) {
if (value == null) return;
setState(() {
_values[index] = value;
});
updateSelectedValues(index);
widget.onChanged(_selectedValues);
},
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
visualDensity: const VisualDensity(
horizontal: VisualDensity.minimumDensity,
vertical: VisualDensity.minimumDensity,
),
),
Flexible(
child: Text(widget.items[index].text),
),
],
),
),
),
],
);
}
void updateSelectedValues(int index) {
if (_values[index]) {
_selectedValues.add(widget.items[index].data);
} else {
_selectedValues.remove(widget.items[index].data);
}
}
}