how can i create drowdownbutton with Riverpod Notifier? - flutter

I want to create DropDownButton with changenotifierProvider in Riverpod, but i can not write nicely my code. Please help me. I suppose, i just wrote 'watch' method, but i do not know how to read it. So, it should show the item which is chosen, and also it should be update with provider.Category.
My DropDownButton code is here:
Widget dropdownButton(BuildContext context,watch) {
String constantValue = "League Of Legends";
final postProvider = ChangeNotifierProvider<PostProvider>((ref) => PostProvider());
final provider = watch(postProvider);
return Consumer(
builder: (context, watch, _) {
return DropdownButton(
value: provider.postCategory ?? constantValue,
onChanged: (newValue) {
provider.postCategory = newValue;
},
items: <String>["League Of Legends", "Steam", "Csgo"]
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
onTap: () => value,
value: value ?? constantValue,
child: Text(value ?? constantValue),
);
}).toList());
},
);
}
Here my DropDownButton Image: ( when i choose any item of the list, it can not work properly. It always pick the first one (It picks "League of Legends").
I select steam but card categoty shows League of legends

final postProvider =
ChangeNotifierProvider<PostProvider>((ref) => PostProvider());
class PostProvider extends ChangeNotifier {
String _postCategory;
String get postCategory => _postCategory;
categoryOnChanged(String value) {
if (value.isEmpty) {
return _postCategory;
}
_postCategory = value;
print(_postCategory);
return notifyListeners();
}
}
class DropDownPage extends StatefulWidget {
#override
_DropDownPageState createState() => _DropDownPageState();
}
class _DropDownPageState extends State<DropDownPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Dropdown Riverpod issue"),
),
body: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: Center(
child: _DropDownWidgetConsumer(),
),
),
);
}
}
class _DropDownWidgetConsumer extends ConsumerWidget {
#override
Widget build(BuildContext context, ScopedReader watch) {
final category = watch(postProvider).postCategory;
return DropdownButton(
hint: Text("Choose category"),
value: category,
items: <String>["League Of Legends", "Steam", "Csgo"]
.map((e) => DropdownMenuItem<String>(
onTap: () => e,
value: e ?? category,
child: Text(e ?? "$category"),
))
.toList(),
onChanged: (value) {
context.read(postProvider).categoryOnChanged(value);
},
);
}
}

Related

Why is the value of the drop-down list (button) not assigned?

I have about 7 DropDownButton, so I created a class in which I just change the values. Here is my class -
class DropDown extends StatelessWidget {
late List<DropdownMenuItem<dynamic>> menuItem;
String? menuValue;
String? hintValue;
DropDown(this.menuItem, this.menuValue, this.hintValue);
#override
Widget build(BuildContext context) {
return StatefulBuilder(builder: (BuildContext context, StateSetter mystate){
return Container(
child: DropdownButton(
underline: Container(
height: 0.1,
color: Colors.transparent,
),
hint: Text('$hintValue'),
value: menuValue,
icon: const Icon(Icons.keyboard_arrow_down),
items: menuItem,
onChanged: (dynamic newValue) {
mystate(() {
menuValue = newValue!;
});
}
)
)
);
}) ;
}
}
Below is how I display these dropdowns -
DropDown(LoginClass.typeModemsDropDown, LoginClass.typeModemsValue, 'Выберите тип модема'),
const SizedBox(
height: 12,
),
DropDown(LoginClass.vendorCountersDropDown, LoginClass.vendorCountersValue, 'text'),
When you try to display in the console LoginClass.vendorCountersValue - the value of null. However, if at this point, I will output print(menuValue); -
mystate(() {
menuValue = newValue!;
print(menuValue);
});
Then, it displays the correct values ​​in the console for me
data - Here is how I am getting the data -
LoginClass.viewModemsDropDown .add(DropdownMenuItem<dynamic>(value: resp['data'][i]['id'].toString(), child: Text(resp['data'][i]['attributes'] ['view_name']))),
// LoginClass.viewModemsDropDown - ["blue": 1, "red": 2] !VALUE!
Tell me, how can I see the values of the selected item anywhere in the code?
Can you point out my mistake and tell me what I'm doing wrong?
You can use a callback method on your DropDown. Also use named constructor cases like this.
class DropDown extends StatelessWidget {
final Function(dynamic) callback;
final List<DropdownMenuItem<dynamic>> menuItem;
final String? menuValue;
final String? hintValue;
const DropDown({
Key? key,
required this.callback,
required this.menuItem,
required this.menuValue,
required this.hintValue,
}) : super(key: key);
#override
Widget build(BuildContext context) {
String? currentValue = menuValue;
return StatefulBuilder(
builder: (BuildContext context, StateSetter mystate) {
return Container(
child: DropdownButton(
underline: Container(
height: 0.1,
color: Colors.transparent,
),
hint: Text('$hintValue'),
value: menuValue,
icon: const Icon(Icons.keyboard_arrow_down),
items: menuItem,
onChanged: (dynamic newValue) {
mystate(() {
currentValue = newValue!;
});
callback(currentValue);
},
),
);
});
}
}
And use case
DropDown(
menuItem: ["a", "b"]
.map(
(e) => DropdownMenuItem(
child: Text(e),
value: e,
),
)
.toList(),
callback: (p0) {
print(p0);
},
hintValue: "Set",
menuValue: "a",
),

Is it possible in a dropdown button the displayed value to not be in the menu?

I tried to do it but I get an error. I was wondering if there is some kind of loophole.
Also, is there a way for the menu to open below the displayed value?
Here is the code:
import 'package:flutter/material.dart';
import './grile_view.dart';
class Grile extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return GrileState();
}
}
class GrileState extends State<Grile> {
var _bGrile = ['bgrila 1', 'bgrila 2'];
var _bio = 'bgrila 1';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.only(top: 15.0, left: 10.0, right: 10.0),
child: ListView(
children: <Widget>[
// DropdownButton
DropdownButton<String>(
items: _bGrile.map((String dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: Text(dropDownStringItem)
);
}).toList(),
onChanged: (value){
Navigator.push(context, MaterialPageRoute(builder: (context) =>
GView()));
},
value: _bio
),
// DropdownButton End
]
)
)
);
} // build
} // GrileState
I am new at programming so excuse anything dumb I wrote in the code.
The DropdownButton class contains a very handy hint property. According to the DropdownButton documentation:
If [value] is null and [hint] is non-null, the [hint] widget is
displayed as a placeholder for the dropdown button's value.
What does this mean for you?
All you have to do is add a hint widget to your DropdownButton and then remove the assignment from your dynamic value.
Here's a brief example of a DropdownButton with a hint property:
class DropDownPage extends StatefulWidget {
#override
_DropDownPageState createState() => _DropDownPageState();
}
class _DropDownPageState extends State<DropDownPage> {
int dropdownValue; // Notice how this isn't assigned a value.
#override
Widget build(BuildContext context) {
return Center(
child: DropdownButton(
// Here's the hint property. I used a Text widget,
// but you can use any widget you like
hint: Text("Pick a Widget"),
value: dropdownValue,
items: [
DropdownMenuItem(child: Text("FlatButton"), value: 0),
DropdownMenuItem(child: Text("Container"), value: 1),
DropdownMenuItem(child: Text("Scaffold"), value: 2),
DropdownMenuItem(child: Text("GestureDetector"), value: 3),
],
onChanged: (value) {
setState(() {
dropdownValue = value;
});
},
));
}
}
This is the result:
So in your code, here's what you have to do in your own code.
Edit this: var _bio = 'bgrila 1';
And change it to this: var _bio;
Then add a hint property to your DropdownButton:
DropdownButton<String>(
hint: Text("Pick a *****"), // Replace with your hint widget
items: _bGrile.map((String dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: Text(dropDownStringItem)
);
}).toList(),
onChanged: (value){
Navigator.push(context, MaterialPageRoute(builder: (context) =>
GView()));
},
value: _bio
),
So that your entire code looks like this:
class Grile extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return GrileState();
}
}
class GrileState extends State<Grile> {
var _bGrile = ['bgrila 1', 'bgrila 2'];
var _bio;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.only(top: 15.0, left: 10.0, right: 10.0),
child: ListView(
children: <Widget>[
// DropdownButton
DropdownButton<String>(
hint: Text("Pick a *******"),
items: _bGrile.map((String dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: Text(dropDownStringItem)
);
}).toList(),
onChanged: (value){
Navigator.push(context, MaterialPageRoute(builder: (context) =>
GView()));
},
value: _bio
),
// DropdownButton End
]
)
)
);
} // build
} // GrileState

How to resolve flutter dropdownButtonFormField dynamic selection checking for dropdownButton's value

I am trying to ask the user to select the type of item in the first dropdown and then select from its corresponding available colours in the second dropdown. However, when after I have selected a colour (i.e. white) and now want to switch to another item that does not have this colour, an error is thrown:
"There should be exactly one item with [DropdownButton]'s value: white. \nEither zero or 2 or more
[DropdownMenuItem]s were detected with the same value"
Please help, I have already tried to setState at various places to update the values but this error still occurs.
The following is my code snippet:
StreamBuilder<QuerySnapshot>(
stream: mainItemsSnapshots,
builder: (context, snapshot) {
if (snapshot.hasError) return Text("Error");
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
default:
{
List<DropdownMenuItem> dropdownMenuItems =
snapshot.data.documents
.map((DocumentSnapshot mainItem) {
return new DropdownMenuItem<String>(
value: mainItem.documentID,
child: Text(mainItem.documentID),
);
}).toList();
return DropdownButtonFormField<String>(
items: dropdownMenuItems,
onChanged: (String value) {
if (value != tempMainItemType) {
setState(() {
tempMainItemType = value;
tempItemColorsList.clear();
tempItemColorsList = [];
tempMainItemColor = null;
});
}
if (tempItemColorsList.isEmpty && value != null) {
tempItemColorsList = snapshot.data.documents
.where((element) => element.documentID == value)
.first
.data["colors"]
.keys
.map((color) => color.toString())
.toList()
.cast<String>();
}
setState((){});
},
onSaved: (String value) {
_order.mainItemType = value;
},
value: tempMainItemType,
);
}
}
},
),
// Main color
if (tempItemColorsList?.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: spacingGeneral),
child: textFieldLabel(context, "Main color"),
),
if (tempItemColorsList?.isNotEmpty)
DropdownButtonFormField(
items: tempItemColorsList.map((String color) {
return new DropdownMenuItem<String>(
value: color,
child: Text(color),
);
}).toList(),
onSaved: (String value) {
_order.mainColor = value;
},
value: tempMainItemColor,
onChanged: (String value) {
setState(() {
tempMainItemColor = value;
});
},
),
This maybe too late, but you can create a Map<String, List<String>> where the keys are the items of the first dropdown list, and the value will be the items of second dropdown list.
Here, I created a state that stores the selected item of the first dropdown list. Then I used it to map the items of the second dropdown list.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SampleDD(),
);
}
}
class SampleDD extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: DoubleDropdown(
items: <String, List<String>>{
'dark colors': ['black', 'gray', 'brown'],
'light colors': ['white', 'yellow', 'green'],
},
onChangedFirst: (val) => print('Selected first: $val'),
onChangedSecond: (val) => print('Selected second: $val'),
),
),
);
}
}
class DoubleDropdown extends StatefulWidget {
DoubleDropdown({
#required this.items,
#required this.onChangedFirst,
#required this.onChangedSecond,
});
final Map<String, List<String>> items;
final ValueChanged<String> onChangedFirst;
final ValueChanged<String> onChangedSecond;
#override
_DoubleDropdownState createState() => _DoubleDropdownState();
}
class _DoubleDropdownState extends State<DoubleDropdown> {
String selectedKey;
#override
void initState() {
super.initState();
selectedKey = widget.items.keys.first;
}
#override
Widget build(BuildContext context) {
return Column(
children: [
_buildFirstDropdown(),
_buildSecondDowndown(),
],
);
}
Widget _buildFirstDropdown() => DropdownButtonFormField<String>(
items: widget.items.keys.map((e) {
return DropdownMenuItem<String>(
child: Text(e),
value: e,
);
}).toList(),
onChanged: (val) {
setState(() => selectedKey = val);
widget.onChangedFirst(val);
},
value: selectedKey,
);
Widget _buildSecondDowndown() => DropdownButtonFormField<String>(
items: widget.items[selectedKey].map((e) {
return DropdownMenuItem<String>(
child: Text(e),
value: e,
);
}).toList(),
onChanged: widget.onChangedSecond,
value: widget.items[selectedKey].first,
);
}

Is there an equivalent widget in flutter to the "select multiple" element in HTML

I am searching for a widget in flutter that is equal to
<select multiple=""></select>
in flutter.
An example implementation (for the web) is MaterializeCSS Select Multiple
As seen above I should be able to provide a list of items (with some of them preselected) and at the end retrieve a list of selected items or a map or something else.
An example implementation or a link to a documentation is very appreciated.
I don't think that a widget like that currently exists in Flutter, but you can build one yourself.
On mobile phones with limited screen space it would probably make sense to display a dialog with a submit button, like this native Android dialog.
Here is a rough sketch how to implement such a dialog in less than 100 lines of code:
class MultiSelectDialogItem<V> {
const MultiSelectDialogItem(this.value, this.label);
final V value;
final String label;
}
class MultiSelectDialog<V> extends StatefulWidget {
MultiSelectDialog({Key key, this.items, this.initialSelectedValues}) : super(key: key);
final List<MultiSelectDialogItem<V>> items;
final Set<V> initialSelectedValues;
#override
State<StatefulWidget> createState() => _MultiSelectDialogState<V>();
}
class _MultiSelectDialogState<V> extends State<MultiSelectDialog<V>> {
final _selectedValues = Set<V>();
void initState() {
super.initState();
if (widget.initialSelectedValues != null) {
_selectedValues.addAll(widget.initialSelectedValues);
}
}
void _onItemCheckedChange(V itemValue, bool checked) {
setState(() {
if (checked) {
_selectedValues.add(itemValue);
} else {
_selectedValues.remove(itemValue);
}
});
}
void _onCancelTap() {
Navigator.pop(context);
}
void _onSubmitTap() {
Navigator.pop(context, _selectedValues);
}
#override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('Select animals'),
contentPadding: EdgeInsets.only(top: 12.0),
content: SingleChildScrollView(
child: ListTileTheme(
contentPadding: EdgeInsets.fromLTRB(14.0, 0.0, 24.0, 0.0),
child: ListBody(
children: widget.items.map(_buildItem).toList(),
),
),
),
actions: <Widget>[
FlatButton(
child: Text('CANCEL'),
onPressed: _onCancelTap,
),
FlatButton(
child: Text('OK'),
onPressed: _onSubmitTap,
)
],
);
}
Widget _buildItem(MultiSelectDialogItem<V> item) {
final checked = _selectedValues.contains(item.value);
return CheckboxListTile(
value: checked,
title: Text(item.label),
controlAffinity: ListTileControlAffinity.leading,
onChanged: (checked) => _onItemCheckedChange(item.value, checked),
);
}
}
You can use it like this:
void _showMultiSelect(BuildContext context) async {
final items = <MultiSelectDialogItem<int>>[
MultiSelectDialogItem(1, 'Dog'),
MultiSelectDialogItem(2, 'Cat'),
MultiSelectDialogItem(3, 'Mouse'),
];
final selectedValues = await showDialog<Set<int>>(
context: context,
builder: (BuildContext context) {
return MultiSelectDialog(
items: items,
initialSelectedValues: [1, 3].toSet(),
);
},
);
print(selectedValues);
}
Is this what you want?
In case you need a short and ready to use code, follow this article
import 'package:flutter/material.dart';
import 'package:multiple_selection_dialogue_app/widgets/multi_select_dialog.dart';
/// A demo page that displays an [ElevatedButton]
class DemoPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
/// Stores the selected flavours
List<String> flavours = [];
return ElevatedButton(
child: Text('Flavours'),
onPressed: () async {
flavours = await showDialog<List<String>>(
context: context,
builder: (_) => MultiSelectDialog(
question: Text('Select Your Flavours'),
answers: [
'Chocolate',
'Caramel',
'Vanilla',
'Peanut Butter'
])) ??
[];
print(flavours);
// Logic to save selected flavours in the database
});
}
}
import 'package:flutter/material.dart';
/// A Custom Dialog that displays a single question & list of answers.
class MultiSelectDialog extends StatelessWidget {
/// List to display the answer.
final List<String> answers;
/// Widget to display the question.
final Widget question;
/// List to hold the selected answer
/// i.e. ['a'] or ['a','b'] or ['a','b','c'] etc.
final List<String> selectedItems = [];
/// Map that holds selected option with a boolean value
/// i.e. { 'a' : false}.
static Map<String, bool> mappedItem;
MultiSelectDialog({this.answers, this.question});
/// Function that converts the list answer to a map.
Map<String, bool> initMap() {
return mappedItem = Map.fromIterable(answers,
key: (k) => k.toString(),
value: (v) {
if (v != true && v != false)
return false;
else
return v as bool;
});
}
#override
Widget build(BuildContext context) {
if (mappedItem == null) {
initMap();
}
return SimpleDialog(
title: question,
children: [
...mappedItem.keys.map((String key) {
return StatefulBuilder(
builder: (_, StateSetter setState) => CheckboxListTile(
title: Text(key), // Displays the option
value: mappedItem[key], // Displays checked or unchecked value
controlAffinity: ListTileControlAffinity.platform,
onChanged: (value) => setState(() => mappedItem[key] = value)),
);
}).toList(),
Align(
alignment: Alignment.center,
child: ElevatedButton(
style: ButtonStyle(visualDensity: VisualDensity.comfortable),
child: Text('Submit'),
onPressed: () {
// Clear the list
selectedItems.clear();
// Traverse each map entry
mappedItem.forEach((key, value) {
if (value == true) {
selectedItems.add(key);
}
});
// Close the Dialog & return selectedItems
Navigator.pop(context, selectedItems);
}))
],
);
}
}
import 'package:flutter/material.dart';
import 'package:multiple_selection_dialogue_app/pages/demo_page.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: DemoPage(),
),
),
);
}
}

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,
],
);
},
);
});