Reputation: 1301
Guys please tell me how to solve the problem. I'm using DropdownButton
with Checkboxlisttile
and ran into a problem that when selecting items, the selected item is not shown in the DropdownButto in the button itself, not in the list (I attached a screenshot below), am I doing something wrong and understand what needs to be fixed to show the selected item?
I use packs for style: [getwidget][1] and [dropdown_button2][2]
code
class DropdownWidget extends StatefulWidget {
List<String> items;
SvgPicture? icon;
double width;
DropdownWidget({
Key? key,
required this.items,
required this.icon,
required this.width,
}) : super(key: key);
@override
State<DropdownWidget> createState() => _DropdownWidgetState();
}
class _DropdownWidgetState extends State<DropdownWidget> {
String? selectedValue;
bool selected = false;
final List _selectedTitles = [];
final List _selectedTitlesIndex = [];
final GFCheckboxType type = GFCheckboxType.basic;
@override
void initState() {
super.initState();
if (widget.items.isNotEmpty) {
_selectedTitles.add(widget.items[3]);
}
}
void _onItemSelect(bool selected, int index) {
if (selected == true) {
setState(() {
_selectedTitles.add(widget.items[index]);
_selectedTitlesIndex.add(index);
});
} else {
setState(() {
_selectedTitles.remove(widget.items[index]);
_selectedTitlesIndex.remove(index);
});
}
}
@override
Widget build(BuildContext context) {
return SizedBox(
width: widget.width,
child: DropdownButtonHideUnderline(
child: DropdownButton2(
items: List.generate(
widget.items.length,
(index) => DropdownMenuItem<String>(
value: widget.items[index],
child: Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: constants.Colors.white.withOpacity(0.1),
width: 1,
),
),
),
child: StatefulBuilder(
builder: (context, setStateSB) => GFCheckboxListTile(
value: _selectedTitles.contains(widget.items[index]),
onChanged: (bool selected) {
_onItemSelect(selected, index);
setStateSB(() {});
},
selected: selected,
title: Text(
widget.items[index],
style: constants.Styles.smallTextStyleWhite,
),
padding: const EdgeInsets.only(top: 14, bottom: 13),
margin: const EdgeInsets.only(right: 12, left: 2),
size: 22,
activeBgColor: constants.Colors.greyCheckbox,
activeBorderColor: constants.Colors.greyCheckbox,
inactiveBgColor: constants.Colors.greyCheckbox,
activeIcon: SvgPicture.asset(constants.Assets.checkboxIcon),
inactiveBorderColor: constants.Colors.greyXMiddle,
type: type,
),
),
),
),
),
value: selectedValue,
onChanged: (value) {
setState(() {
selectedValue = value as String;
});
},
icon: SvgPicture.asset(constants.Assets.arrowDropdown),
iconSize: 21,
buttonHeight: 27,
itemHeight: 66,
dropdownMaxHeight: 191,
dropdownWidth: 140,
dropdownDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: constants.Colors.purpleMain,
),
color: constants.Colors.greyDark,
),
selectedItemBuilder: (context) {
return _selectedTitles.map(
(item) {
return Row(
children: [
widget.icon ?? const SizedBox(),
const SizedBox(width: 8),
Text(
item,
style: constants.Styles.bigBookTextStyleWhite,
),
],
);
},
).toList();
},
),
),
);
}
}
list
final List<String> carList = const [
"All EV's",
'Main EV',
'<EV2>',
];
Upvotes: 0
Views: 90
Reputation: 1783
as you are using a Dropdown widget as a workaround, I prepared a real solution for you that achieves exactly what you are looking for:
return Container(
width: 150,
child: PopupMenuButton(
offset: Offset(0, 50),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 10,
vertical: 20
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (_selectedTitles.isNotEmpty)
Text("<"),
Flexible(
child: Text(
_selectedTitles.isEmpty
? "Select a value"
: _selectedTitles.map((item) => item).toList().join(", "),
overflow: TextOverflow.ellipsis,
),
),
if (_selectedTitles.isNotEmpty)
Text(">"),
SizedBox(width: 5),
Icon(Icons.arrow_drop_down)
],
),
),
itemBuilder: (context) => List.generate(
widget.items.length,
(index) => PopupMenuItem(
value: widget.items[index],
child: Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
// color: constants.Colors.white.withOpacity(0.1),
width: 1,
),
),
),
child: StatefulBuilder(
builder: (context, setStateSB) => CheckboxListTile(
value: _selectedTitles.contains(widget.items[index]),
onChanged: (bool? selected) {
_onItemSelect(selected!, index);
setStateSB(() {});
},
selected: selected,
title: Text(
widget.items[index],
),
),
),
),
),
)
),
);
here I add another example on how to have inside your popup, 2 buttons that allow you to select all values or unselect them:
String? selectedValue;
final List<String> _selectedTitles = [];
final List<int> _selectedTitlesIndex = [];
// final GFCheckboxType type = GFCheckboxType.basic;
@override
void initState() {
super.initState();
// if (widget.items.isNotEmpty) {
// _selectedTitles.add(widget.items[0]);
// }
}
void _onItemSelect(bool selected, int index) {
setState(() {
if (selected == true) {
_selectedTitles.add(widget.items[index]);
_selectedTitlesIndex.add(index);
} else {
_selectedTitles.remove(widget.items[index]);
_selectedTitlesIndex.remove(index);
}
});
}
void _selectAll(bool selected) {
setState(() {
if (selected == true) {
_selectedTitles.clear();
_selectedTitles.addAll(widget.items);
_selectedTitlesIndex.clear();
for( int i = 0 ; i <= widget.items.length; i++ ) {
_selectedTitlesIndex.add(i);
}
} else {
_selectedTitles.clear();
_selectedTitlesIndex.clear();
}
Navigator.of(context).pop();
});
}
@override
Widget build(BuildContext context) {
return Container(
width: 150,
child: PopupMenuButton(
offset: Offset(0, 50),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 0,
vertical: 20
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (_selectedTitles.isNotEmpty)
Text("<"),
Flexible(
child: Text(
_selectedTitles.isEmpty
? "Select a value"
: _selectedTitles.map((item) => item).toList().join(", "),
overflow: TextOverflow.ellipsis,
),
),
if (_selectedTitles.isNotEmpty)
Text(">"),
SizedBox(width: 5),
Icon(Icons.arrow_drop_down)
],
),
),
itemBuilder: (context) {
List<PopupMenuEntry> items1 = List.generate(
widget.items.length,
(index) => PopupMenuItem(
padding: EdgeInsets.zero,
value: widget.items[index],
child: Container(
decoration: BoxDecoration(
border: Border(
bottom: index == widget.items.length - 1
? BorderSide.none
: BorderSide(
// color: constants.Colors.white.withOpacity(0.1),
width: 1,
),
),
),
child: StatefulBuilder(
builder: (context, setStateSB) => CheckboxListTile(
value: _selectedTitles.contains(widget.items[index]),
onChanged: (bool? selected) {
_onItemSelect(selected!, index);
setStateSB(() {});
},
selected: false,
title: Text(
widget.items[index],
),
),
),
),
),
);
return [
PopupMenuItem(
value: "select all",
padding: EdgeInsets.zero,
child: Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
// color: constants.Colors.white.withOpacity(0.1),
width: 1,
),
),
),
child: Row(
children: [
TextButton(
child: Text(
"Select all",
),
onPressed: () {
_selectAll(true);
},
),
Spacer(),
TextButton(
child: Text(
"Unselect all",
),
onPressed: () {
_selectAll(false);
},
)
],
),
),
),
...items1
];
}
),
);
}
Upvotes: 1
Reputation: 587
try this
import 'package:flutter/material.dart';
class DropdownWidget extends StatefulWidget {
List<String> items;
DropdownWidget({
Key? key,
required this.items,
}) : super(key: key);
@override
State<DropdownWidget> createState() => _DropdownWidgetState();
}
class _DropdownWidgetState extends State<DropdownWidget> {
String? selectedValue;
bool selected = false;
int selectedInd = 0 ;
final List _selectedTitles = [];
final List _selectedTitlesIndex = [];
@override
void initState() {
super.initState();
if (widget.items.isNotEmpty) {
_selectedTitles.add(widget.items[0]);
}else{
print("null");
}
}
void _onItemSelect(bool selected, int index) {
if (selected == true) {
setState(() {
_selectedTitles.add(widget.items[index]);
_selectedTitlesIndex.add(index);
});
} else {
setState(() {
selectedInd = index ;
_selectedTitles.remove(widget.items[index]);
_selectedTitlesIndex.remove(index);
});
}
}
@override
Widget build(BuildContext context) {
return SizedBox(
width: 150,
child: DropdownButtonHideUnderline(
child: DropdownButton(
hint : Center(child: Text(_selectedTitles.isEmpty ? "selectedEV"
: _selectedTitles[selectedInd] , textAlign: TextAlign.end,)) ,
items: List.generate(
widget.items.length,
(index) => DropdownMenuItem<String>(
value: widget.items[index],
child: Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors.white.withOpacity(0.1),
width: 1,
),
),
),
child: StatefulBuilder(
builder: (context, setStateSB) => CheckboxListTile(
value: _selectedTitles.contains(widget.items[index]),
onChanged: (bool? selected) {
_onItemSelect(selected!, index);
setStateSB(() {});
},
selected: selected,
title: Text(
widget.items[index],
),
),
),
),
),
),
value: selectedValue,
onChanged: (value) {
setState(() {
selectedValue = value as String;
print(value);
});
},
icon: Icon(Icons.arrow_drop_down),
iconSize: 21,
itemHeight: 66,
selectedItemBuilder: (context) {
return _selectedTitles.map(
(item) {
return Row(
children: [
const SizedBox(width: 8),
Text(
item,
),
],
);
},
).toList();
},
),
),
);
}
}
Upvotes: 0