Making Unique List Tile item in Flutter from Builder - flutter

I was wondering if it was possible to make items in List View unique in the sense that if I want to add something to the one, it only changes that particular list tile item, for example, if I added a leading icon from the DropDown to the one on the list, it adds that icon only to that particular list tile, and not the others (I can then add other icons from the dropdown to other list tile items).
Here's the code for it, I am not sure if this is possible since the builder is made from Bloc and an existing class Person, basically a template for each list item.
child: BlocConsumer<PersonBloc, List<Person>>(
builder: (context, personList) {
return ListView.separated(
itemBuilder: (BuildContext context, int index) {
print("personList: $personList");
Person person = personList[index];
return ListTile(
key: UniqueKey() //added unique key here, but it still fails
//for example, is it possible to make this list tile unique
//if I make change to it, it only changes the one I change, and not
//all of them in a list at once
//leading: DropDownButton() -> if I had a dropdown here with icon choices
//would it be possible for that icon only to be chosen for a particular item on the list?
trailing: Icon(Icons.person),
title: Text("${person.name} ${person.age}",
style: TextStyle(fontSize: 30)),
subtitle: Text(
"person.name",
style: TextStyle(fontSize: 25),
),
onTap: () => showDialog(context, person, index));
},
itemCount: personList.length,
separatorBuilder: (BuildContext context, int index) =>
Divider(color: Colors.black),
);
},
listener: (BuildContext context, personList) {},
),
more is explained in the comments.
EDIT
The UniqueKey() doesn't work, I tested in on my old test app I was making that works similarly with the ListTile as well, and when you change the dropdown for one, it changes automatically for all the items:
Also, here's the dropdown just so you can see if something should be changed there:
Widget _buildSize() {
return DropdownButton<String>(
focusColor: Colors.white,
value: _chosenSize,
//elevation: 5,
style: TextStyle(color: Colors.white),
iconEnabledColor: Colors.black,
items: <String>[
'',
'S',
'M',
'L',
'XL',
].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: TextStyle(color: Colors.black),
),
);
}).toList(),
hint: Text(
"Size",
style: TextStyle(
color: Colors.black, fontSize: 14, fontWeight: FontWeight.w500),
),
onChanged: (String value) {
setState(() {
_chosenSize = value;
});
},
);
}

you can create an id field on existing Person class.
or you can use key, here about key
https://api.flutter.dev/flutter/foundation/Key-class.html
Edit :
sorry for my mistake, for reference link only. this is simple example of my solution
This is example of key usage
ListTile(
key:UniqueKey(),
)
take a look this link too
https://medium.com/flutter/keys-what-are-they-good-for-13cb51742e7d
*EDIT
The unique key is is wrong answer sorry.
first you have to create a list to contain your widget values
List<String> _yourWidgets = [];
then change your widget methods to retrieve the index
Widget _buildSize(int index) {
return DropdownButton<String>(
focusColor: Colors.white,
value: _chosenSize,
//elevation: 5,
style: TextStyle(color: Colors.white),
iconEnabledColor: Colors.black,
items: <String>[
'',
'S',
'M',
'L',
'XL',
].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: _yourWidgets[index],
child: Text(
value,
style: TextStyle(color: Colors.black),
),
);
}).toList(),
hint: Text(
"Size",
style: TextStyle(
color: Colors.black, fontSize: 14, fontWeight: FontWeight.w500),
),
onChanged: (String value) {
setState(() {
_yourWidgets[index] = value;
});
},
);

Related

Flutter checkbox not deselecting after select

I have an API with an array list of values that passes values to my Radio button successfully. When I select each the select value parses but I'm unable to deselect the select radio button. Below is my flutter code:
ListView.builder( shrinkWrap:true,
physics:const NeverScrollableScrollPhysics(),
itemCount:dataOptions == null? 0: dataOptions.length,
itemBuilder:(BuildContext context,int index) {
return Container(
padding:
const EdgeInsets
.only(
bottom:
0.0),
child: Card(
elevation: 0,
child:
ListTile(
title: Text(
dataOptions[index]['option_title']),
leading:
Radio(
value: dataOptions[index]["option_price"],
//below will be the default value.
groupValue: dataOptions[index]["option_id"],
onChanged: (value) {
setState(
() {
dataOptions[index]["option_id"] = value;
debugPrint("radioSel:$value");
});
},
activeColor: Colors.green,
),
trailing:
Text(dataOptions[index]['option_price'].toString(), style:TextStyle(fontFamily: 'Montserrat',
color: colorPink, fontWeight: FontWeight.bold,
fontSize: 15,
),
),
)));
})
Since groupValue stores the currently selected value and you use the individual dataOptions[index]["option_id"] as groupValue all radio buttons are independent from each other.
If this is intended, check out checkboxes as they are meant to be used for this behavior. CheckBox
To deselect a Radio widget if another one in the group is selected do the following.
//Set default option if prefered
String? _groupValue;
Radio(
value: dataOptions[index]["option_price"],
groupValue: _groupValue,
onChanged: (value) {
setState(() {
_groupValue = value;
});
},
),
I added this and it worked.
toggleable: true,
reference: https://api.flutter.dev/flutter/material/Radio/toggleable.html

How to make DropdownButton menu width to fit text?

I want to have a dropdown button that has a width based on the menu text length. The dropdown arrow does not have any additional spacing between text.
Like this:
Currently, I am getting this:
My dropdown button arrow is positioned based on the longest text.
My code:
Widget dropdownList(){
return Container(
child: DropdownButton<Location>(
value: _selectedValue,
icon: const Icon(Icons.expand_more),
iconSize: 30,
underline: SizedBox(),
onChanged: (Location? newValue) {
setState(() {
_selectedValue = newValue!;
});
},
style: const TextStyle(color: Colors.blue),
selectedItemBuilder: (BuildContext context) {
return locationList.map((Location value) {
return Container(
child: Text(
value.name,
style: const TextStyle(color: Colors.black,fontSize: 30,
fontWeight: FontWeight.w300),
),
);
}).toList();
},
items: locationList.map<DropdownMenuItem<Location>>((Location value) {
return DropdownMenuItem<Location>(
value: value,
child: Text(value.name, style: TextStyle(color: Colors.black,fontSize: 15,
fontWeight: FontWeight.w300)),
);
}).toList(),
),
);
}
According to the documentations there is a property for DropDownButton called isExpanded:
isExpanded → bool
Set the dropdown's inner contents to horizontally fill its parent. [...]
final
so just set:
isExpanded = true;

Dropdownbutton restrict shown items

Ive got the following Problem:
I want the user to choose a day of month with a dropdownbutton. So my items are the numbers 1 to 31. Now the list got pretty long and the Dropdownbutton is really large. Is there a Solution to show e.g. only 5 Elements at the same time?
Widget buildDropdownMonthlyTurnus() {
return DropdownButton<int>(
value: _selectedDay,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.blue),
underline: Container(
height: 2,
color: Colors.blue,
),
onChanged: (int newValue) {
setState(() {
_selectedDay = newValue;
});
},
items: Constants.daysOfMonth.map((int value) {
return new DropdownMenuItem<int>(
value: value,
child: new Text(
value.toString(),
style: new TextStyle(color: Colors.black),
),
);
}).toList());
}
In the link you see my problem with the large list.
enter image description here
For this problem you can use listview, inside a container and show manage its size according to the list items shown, you don't need to use dropdown items at all.
Use the menuMaxHeight property of the DropdownButton class. It's a recent addition to control the height of the menu.
Widget buildDropdownMonthlyTurnus() {
return DropdownButton<int>(
menuMaxHeight: 200.0,
value: _selectedDay,
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
style: TextStyle(color: Colors.blue),
underline: Container(
height: 2,
color: Colors.blue,
),
onChanged: (int newValue) {
setState(() {
_selectedDay = newValue;
});
},
items: Constants.daysOfMonth.map((int value) {
return new DropdownMenuItem<int>(
value: value,
child: new Text(
value.toString(),
style: new TextStyle(color: Colors.black),
),
);
}).toList());

Changing Only Single List Tile in List View so it's Unique in Flutter

I was wondering if it was possible to make items in List View unique in the sense that if I want to add something to the one, it only changes that particular list tile item, for example, if I added a leading icon from the DropDown to the one on the list, it adds that icon only to that particular list tile, and not the others (I can then add other icons from the dropdown to other list tile items).
Here's the code for it, I am not sure if this is possible since the builder is made from Bloc and an existing class Person, basically a template for each list item. I have tried with adding UniqueKey(), but that seems not to do anything. Here's the code for the List View:
_chosenSize
String _chosenSize;
child: BlocConsumer<PersonBloc, List<Person>>(
builder: (context, personList) {
return ListView.separated(
itemBuilder: (BuildContext context, int index) {
print("personList: $personList");
Person person = personList[index];
return ListTile(
key: UniqueKey() //added unique key here, but it still fails
//for example, is it possible to make this list tile unique
//if I make change to it, it only changes the one I change, and not
//all of them in a list at once
leading: _buildSize(); //DROPDOWN HERE
trailing: Icon(Icons.person),
title: Text("${person.name} ${person.age}",
style: TextStyle(fontSize: 30)),
subtitle: Text(
"person.name",
style: TextStyle(fontSize: 25),
),
onTap: () => showDialog(context, person, index));
},
itemCount: personList.length,
separatorBuilder: (BuildContext context, int index) =>
Divider(color: Colors.black),
);
},
listener: (BuildContext context, personList) {},
),
Then here's the code for the DropDown:
Widget _buildSize() {
return DropdownButton<String>(
focusColor: Colors.white,
value: _chosenSize,
//elevation: 5,
style: TextStyle(color: Colors.white),
iconEnabledColor: Colors.black,
items: <String>[
'',
'S',
'M',
'L',
'XL',
].map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: TextStyle(color: Colors.black),
),
);
}).toList(),
hint: Text(
"Size",
style: TextStyle(
color: Colors.black, fontSize: 14, fontWeight: FontWeight.w500),
),
onChanged: (String value) {
setState(() {
_chosenSize = value;
});
},
)};
What happens is that when I change the 'size' option from the dropdown, it changes for all list tiles, I need it to change only for one and then save the state of it. Here's what happens:
You need to create a list for _chosenSize as well, which you pass to Widget _buildSize(String _chosenSize) with _buildSize(_chosenSize[index]) and also store it there with onChanged
class MyPageState extends State<MyPage> {
List<String> _chosenSizes = [];
...
return ListView.separated(
itemBuilder: (BuildContext context, int index) {
print("personList: $personList");
Person person = personList[index];
return ListTile(
key: UniqueKey() //added unique key here, but it still fails
//for example, is it possible to make this list tile unique
//if I make change to it, it only changes the one I change, and not
//all of them in a list at once
leading: _buildSize(index]); //DROPDOWN HERE
trailing: Icon(Icons.person),
title: Text("${person.name} ${person.age}",
style: TextStyle(fontSize: 30)),
subtitle: Text(
"person.name",
style: TextStyle(fontSize: 25),
),
onTap: () => showDialog(context, person, index));
},
itemCount: personList.length,
separatorBuilder: (BuildContext context, int index) =>
Divider(color: Colors.black),
);
...
Widget _buildSize(int index) {
return DropdownButton<String>(
focusColor: Colors.white,
value: _chosenSizes[index],
...
onChanged: (String value) {
setState(() {
_chosenSizes[index] = value;
});
},
)};
}

How to open dropDownButton from RaisedButton

Using Flutter.
When a user taps a button, I want focus to shift to a dropDownButton and open up the options. Here is my attempt (not working):
RaisedButton(
onPressed: () {setState(() {FocusScope.of(context).requestFocus(_node);exactTime = false;});},
color: Theme.of(context).primaryColor,
child: const Text(
'Estimate',
style: TextStyle(fontSize: 20)
),
)
DropdownButton<String>(
isExpanded: true,
focusNode: _node,
items: ageRanges.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value, style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)),
);
}).toList(),
value: pmhOnset,
onChanged: (String selected) {
setState(() {
pmhOnset = selected;
});
},
)
I don't get any errors. It just doesn't do anything. Any suggestions?
From what I have read it is not possible with out making your own DropDownButton class but that shouldn't be that hard after all just a matter of coping most of flutters code and changing it to fit your need I'll attach a link that I think you will find helpful.