How do I use radio buttons in a ListView Flutter? - flutter

I have a list of varieties [Chocolate, Strawberry, Vanilla]
This list can change depending on the menu item ordered (i.e. [BBQ, Medium, Peri-Peri, Lemon & Herb])
My current code which display the button correctly but is not functional is:
ListView.builder(
shrinkWrap: true,
itemCount: varietyList.length,
itemBuilder: ((context, index) {
return GFRadioListTile(
titleText: varietyList[index],
size: 25,
activeBorderColor: Colors.black,
focusColor: Colors.black,
type: GFRadioType.basic,
value: 0,
groupValue: 1,
onChanged: (value) {},
inactiveIcon: null,
);
})),
Where ```int number = 20'''. This variable and amount was based off another post where the code looked as follow:
ListView.builder(
shrinkWrap: true,
itemCount: varietyList.length,
itemBuilder: ((context, index) {
return RadioListTile(
value: index,
groupValue: number,
onChanged: (ind) => setState(() => number = ind),
);
})),
But it says "A value of type 'Object?' can't be assigned to a variable of type 'int'."
How can I get the radio button functional?

to fix the "object cant be int" problem I had to add as int for the ind object.
GFRadioListTile(
padding: const EdgeInsets.all(13),
color: Colors.white,
radioColor: Color.fromARGB(255, 138, 5, 5),
title: Text(
varietyList[index],
style: const TextStyle(
fontSize: 25, color: Colors.black),
),
size: 28,
activeBorderColor: Colors.black,
focusColor: Colors.black,
type: GFRadioType.basic,
value: index,
groupValue: number,
onChanged: (ind) =>
setState(() => number = ind! as int),
inactiveIcon: null,
);

Related

Flutter AutoComplete Widget, not letting me choose text outside of an Array

My code is as follows:
final TextEditingController _locationController = TextEditingController();
late TextEditingController myController;
late List<String> locationSuggestions; // Populated with options in code first
Autocomplete<String>(
initialValue: TextEditingValue(text:_locationController.text),
optionsMaxHeight: 50,
optionsBuilder: (TextEditingValue textEditingValue) {
if (textEditingValue.text.isEmpty) return const Iterable<String>.empty();
return locationSuggestions.where((String option) {
return option
.toLowerCase()
.contains(textEditingValue.text.toLowerCase());
});
},
optionsViewBuilder: (context, onSelected, options){
return Material(
elevation: 8,
child: ListView.separated(
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 0.0),
itemBuilder: (BuildContext context, int index) {
final String option = options.elementAt(index);
return ListTile(
dense: true,
// tileColor: Colors.deepOrange,
title: SubstringHighlight(
text: option,
term: myController.text,
textStyleHighlight: const TextStyle(fontWeight: FontWeight.w700, fontSize: 16.0),
),
onTap: () => onSelected(option),
);
},
separatorBuilder: (context, index) => const Divider(),
itemCount: options.length,
));
},
onSelected: (String value)=> myController.text = value,
fieldViewBuilder: (context, controller, focusNode, onEditingComplete){
myController = controller;
return TextFormField(
controller: myController,
focusNode: focusNode,
maxLines: 1,
maxLength: 30,
keyboardType: TextInputType.text,
textCapitalization: TextCapitalization.sentences,
decoration: InputDecoration(
labelText: 'Location',
prefixIcon: Icon(
Icons.add_location,
size: 35.0,
color: Theme.of(context).colorScheme.primary,
)),
onEditingComplete: onEditingComplete,
//onTap: ()=>FocusManager.instance.primaryFocus?.unfocus(),
);
},
),
The Problem:
When I go and type the text, I see options appearing below, if I choose one of the options, all goes well and good.
BUT... I am not able to type a new 'similar' custom option. So for example, if I get a suggestion for the word 'Apple' and I just want to stop typing at App, I can't do it. The done button on the keyboard does not hide the keyboard and if I try to move away from the field the entire 'Apple' appears in the text field. I tried experimenting with unfocus but it is not the right way and I am sure I am missing a feature here.

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

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

Making Unique List Tile item in Flutter from Builder

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

How can I use GridListView with firebase?

I have a question about GridListView with firestore.
I want to use GridList with firestore but some errors are happen.
lib/main.dart:75:15: Error: No named parameter with the name 'children'. children: workoutList ^^^^^^^^ ../../Developer/flutter/packages/flutter/lib/src/widgets/scroll_view.dart:1729:3: Context: Found this candidate, but the arguments don't match. GridView.builder({
Could you give me some ideas?
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
children: workoutList
.map(
(workout) => CheckboxListTile(
title: Text(
workout.title,
style: TextStyle(
color: Colors.white
),
),
value: workout.isDone,
onChanged: (bool value) {
workout.isDone = !workout.isDone;
model.reload();
},
),
)
.toList()
);
The error message is quite explanatory. All it's telling you is that the GridView.builder() constructor has no parameter 'children'. The code below is way to achieve what you're trying to do:
return GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount: workoutList.length,
itemBuilder: (BuildContext context, int index) {
var workout = workoutList[index];
return CheckboxListTile(
title: Text(
workout.title,
style: TextStyle(color: Colors.white),
),
value: workout.isDone,
onChanged: (bool value) {
workout.isDone = !workout.isDone;
model.reload();
},
);
},
);