On this example im trying to add to the CheckboxListTile the values i have saved on my List.
But for somereason im stuck here and i cant figure it out how to solve this problem.
Global List
List<String> _lstNomeData = new List<String>();
Values Map
Map<String, bool> values = {
'$_lstNomeData[index]': false,
};
Get selected checkbox values
var tmpArray = [];
getCheckboxItems() {
values.forEach((key, value) {
if (value == true) {
tmpArray.add(key);
}
});
print(tmpArray);
tmpArray.clear();
}
Body
body: Column(
children: <Widget>[
Expanded(
child: ListView(
children: values.keys.map((String key) {
return new CheckboxListTile(
title: new Text(key),
value: values[key],
activeColor: Colors.blue,
checkColor: Colors.white,
onChanged: (bool value) {
setState(() {
values[key] = value;
});
},
);
}).toList(),
),
),
],
)
Error
Print of the error displayed
You are on the right track. You can do two things here:
Prefill the map with false for every key (what you are trying to do)
Assume that if the map does not have a key, the answer is false (default)
Second approach is probably even better because by prefilling the map with false you could not distinct between false being actually answered by the user or if it was set by default. If a key is not in the map you know that the user has not answered the question so far. I will go and show how to work with the second approach:
Keep your global list as it is:
List<String> _lstNomeData = [];
Initialise the map (which represents the answers from the user for each question) with an empty Map:
Map<String, bool> answers = {};
Now correctly reference those answers in your Checkbox widget and make use of the onChanged property:
ListView(
children: _lstNomeData.map((key) =>
CheckboxListTile(
title: Text(key),
// Here we check if the answers map has this key and if it does, use the bool value, otherwise set it to false (user has not answered this so far)
value: answers[key] ?? false,
activeColor: Colors.blue,
checkColor: Colors.white,
onChanged: (answer) =>
setState(() => answers[key] = answer)
),
).toList(),
),
Related
I am trying to create a list of type User, and if that list is not empty, provide the next User in the list. I've read as many Flutter docs as my brain can hold, and I'm at a loss.
class _SwipePageState extends State<SwipePage> implements PreferredSizeWidget {
getUsers() async {
Box box = await Hive.openBox('usersBox');
swipableUsers = box.values.toList();
}
List swipableUsers = <User>[];
#override
Widget build(BuildContext context) => Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(100),
child: Container(color: Colors.transparent),
),
body: Padding(
padding: const EdgeInsets.all(8),
child: Column(
children: [
swipableUsers.isEmpty
? const Text('No more users')
: Stack(children: swipableUsers.map(buildUser).toList()),
Expanded(child: Container()),
const BottomButtonsWidget()
],
),
),
);
Widget buildUser(User currentUser) {
int userIndex = swipableUsers.indexOf(currentUser);
bool isUserInFocus = userIndex == swipableUsers.length - 1;
//Do other stuff with currentUser
The error is at : Stack(children: swipableUsers.map(buildUser).toList()), and the error is the title of this question, The argument type 'List<dynamic>' can't be assigned to the parameter type 'List<Widget>'
Is there any chance to save my little app, or have I tangled things so much it's hopeless? Thanks in advance for your answers :)
You need to generate a list of widgets using the swipableUsers variable, but you are returning the list of User to the Stack's children attribute.Try this instead:
Stack(children: List.generate(swipableUsers.length,(index)=>buildUser(swipableUsers[index])))
Here is what I'm trying to do.
Here is my ListItems class:
class ListItems {
String? title;
String? text;
DateTime? selectedDayTime;
ListItems(
{required this.title, required this.text, required this.selectedDayTime});
}
In my AddTask class, I'm trying to add some items to my list. Here is my code:
ElevatedButton(
onPressed: () {
setState(() {
itemList.add(
ListItems(
title: _titleController.text,
text: _textController.text,
selectedDayTime: _selectedDay,
),
);
Navigator.pop(context);
});
print(itemList.length);
},
child: Text("Add Task"),
),
itemList is a List list. However, everytime I try to add new item to my itemList, itemList.length never changes. I dont know why this happening so I need help.
Swap Navigator with print line.
ElevatedButton(
onPressed: () {
setState(() {
itemList.add(
ListItems(
title: _titleController.text,
text: _textController.text,
selectedDayTime: _selectedDay,
),
);
print(itemList.length);
//Navigator.pop(context); keep it here also
});
Navigator.pop(context);
},
child: Text("Add Task"),
),
Does it make any difference if you include your print statement inside the setState? I don't see any reason for your code not to work.
You could also try to type your itemList to be of type List<ListItems>, if you haven't already. I don't think it's causing any issues, but it can't hurt to be thorough.
I am fetching an array of images from AWS in a List and I am displaying it using .map. I don't know if I am doing it right. I am having an error 'package:flutter/src/painting/_network_image_io.dart': Failed assertion: line 25 pos 14: 'url != null': is not true. But works perfectly fine if I manually display it like this, Image.network('https://thisIsJustSampleLink.s3.us-east-2.amazonaws.com/id/sampleOnly/bb.jpg')
Here is my code. Fetching data from the database. The babyimage[] is an array of images link from AWS.
List <String> _babyList = List();
Future<void> getApplicantInfo() async {
AuthService().getRequestorApplicants().then((val) async {
requestorApplicants.clear();
_babyList.clear();
for (var i = 0; i < val.data.length; i++) {
var temp = val.data[i];
setState(() {
requestorApplicants.add(new RequestorApplicantsList(
parentname: temp['parentname'],
babyname: temp['babyname'],
));
_babyList.add(temp['babyimage[]']);
});
}
});
}
Displaying the list using Image.network
Container(
height: MediaQuery.of(context).size.height,
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.vertical,
children: <Widget>[
Column(
children: _babyList.map((e) => Image.network(e)).toList(),
),
],
)),
in this code _babyList.map((e) => Image.network(e)).toList() some of urls (or maybe all) are null. Add filter to remove null elements.
_babyList.where((e) => e != null).map((e) => Image.network(e)).toList(growable:false)
if they can't be null check your code, maybe there is a bug somwhere
so i was creating this app which is an item catalogue for an online shop using StaggeredGridView, here i add a function to sort the item from a list, so that i can sort it by price or make it back to default sorting, but i encounter a problem where the list cant go back to default sorting when i select it, here is the code :
class ItemCatalogState extends State<ItemCatalog>{
sortedBy sorted = sortedBy.init;
bool isInit = true;
var selectedList = [];
void sortItem(List<Item> initialList){
switch (sorted) {
case sortedBy.lowestPrice:
setState(() {
selectedList.sort((a,b){return a.price.compareTo(b.price);});
});
break;
case sortedBy.highestPrice:
setState(() {
selectedList.sort((a,b){return b.price.compareTo(a.price);});
});
break;
case sortedBy.init:
//NOT WORKING
setState(() {
selectedList = initialList;
});
break;
default:
}
}
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
List<Item> itemList = Provider.of<List<Item>>(context);
if(isInit&&itemList!=null){
selectedList = itemList.map((e) => Item(image: e.image,name: e.name,isReady: e.isReady,price: e.price,seller: e.seller)).toList();
isInit = false;
}
sortItem(itemList);
return Container(
child: DropdownButtonHideUnderline(
child: DropdownButton(
value: sorted,
items: [
DropdownMenuItem(
child: Text('Default',),
value: sortedBy.init,),
DropdownMenuItem(
child: Text('Lowest',),
value: sortedBy.lowestPrice,),
DropdownMenuItem(
child: Text('Highest'),
value: sortedBy.highestPrice,),
],
onChanged: (value){
setState(() {
sorted = value;
});
}),
),
),
Container(
decoration: BoxDecoration(
color: kGrayMainColor,
),
child: StaggeredGridView.countBuilder(
itemCount: selectedList!=null?selectedList.length:itemList.length,
crossAxisCount: 2,
itemBuilder: (context, index) {
Item currentItem = selectedList!=null?selectedList[index]:itemList[index];
return ItemTile(item: currentItem, size: size,);
},
),
),
),
]),]
);
}
It was supposed to call the original List when i click the default drop down, but nothing changed, could i possibly wrong at copying the list to selectedList? Thankyou and any advice regarding my other bad code practice is appreciated since im still learning.
Inside sortItems you set selectedList to be equal to initialList. From that point on, both variables are now pointing at the same collection of objects, which means anything you do to one, you will also do to the other. And since you are getting the collection through provider, these changes will also affect the original list that was provided.
Instead of a direct assignment, copy initialList again so that the two lists are never pointing to the same collection.
Incidentally, there's a much easier way to create copies of lists:
selectedList = List.from(initialList);
On another note, I'm assuming that the default value of sorted is sortedBy.init. That makes the initial copy within your build method redundant as the sortItems method immediately overwrites the value of selectedList. Instead, just depend on sortItems to generate your list without having to worry about initialization:
void sortItem(List<Item> initialList){
switch (sorted) {
case sortedBy.lowestPrice:
selectedList = List.from(initialList)
..sort((a,b) => a.price.compareTo(b.price));
break;
case sortedBy.highestPrice:
selectedList = List.from(initialList)
..sort((a,b) => b.price.compareTo(a.price));
break;
case sortedBy.init:
selectedList = List.from(initialList);
break;
}
setState(() {}); // Just call this once to reduce code duplication and verbosity
}
#override
Widget build(BuildContext context) {
...
List<Item> itemList = Provider.of<List<Item>>(context);
sortItems(itemList);
...
}
This is how I would solve it (I changed your List<Item> to a List<String> for simplicity, but you get the gist):
Load the original list into the _sortedList variable (initially in didChangeDependencies) via the Provider and repeat this whenever you are in need of the original list again.
(My Provider returns ['aa', 'dd', 'cc'], so I could get in that map() you do on the list as well :) )
enum SortOrder { ascending, descending, original }
class _TestState extends State<Test> {
var _sortedList = List<String>();
#override
void didChangeDependencies() {
super.didChangeDependencies();
_loadOriginalList();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
RaisedButton(
child: Text('Ascending'),
onPressed: () => setState(() => _sortList(SortOrder.ascending)),
),
RaisedButton(
child: Text('Descending'),
onPressed: () => setState(() => _sortList(SortOrder.descending)),
),
RaisedButton(
child: Text('Original'),
onPressed: () => setState(() => _sortList(SortOrder.original)),
),
],
),
ListView.builder(
shrinkWrap: true,
itemCount: _sortedList.length,
itemBuilder: (context, index) => Center(
child: Text(_sortedList[index]),
),
),
],
),
);
}
void _sortList(SortOrder sortOrder) {
switch (sortOrder) {
case SortOrder.ascending:
_sortedList.sort();
break;
case SortOrder.descending:
_sortedList.sort();
_sortedList = _sortedList.reversed.toList();
break;
case SortOrder.original:
_loadOriginalList();
break;
}
}
void _loadOriginalList() {
final originalList = Provider.of<List<String>>(context, listen: false);
_sortedList.clear();
_sortedList.addAll(originalList.map((e) => e.substring(0, 1)));
}
}
I would like to create a dropdown or a list of all free FontAwesomeIcons to allow the user choose the one he/she like more. Also if You write something, the list have to filter the icons(that´s optional).
List<IconData> fontAwesomeIcons = [FontAwesomeIcons.accessibleIcon,FontAwesomeIcons.americanSignLanguageInterpreting,FontAwesomeIcons.assistiveListeningSystems,FontAwesomeIcons.audioDescription,];
You can do the following:
DropdownButton<IconData>(
value: dropdownValue,
onChanged: (IconDatanewValue) {
setState(() {
dropdownValue = newValue;
});
},
items: <IconData>[FontAwesomeIcons.accessibleIcon,FontAwesomeIcons.americanSignLanguageInterpreting,FontAwesomeIcons.assistiveListeningSystems,FontAwesomeIcons.audioDescription]
.map<DropdownMenuItem<IconData>>((IconData value) {
return DropdownMenuItem<IconData>(
value: value,
child: Text(value),
);
})
.toList(),
),
The DropdownMenuItem is a class used to represent the items.
onChanged is called when the user selects an item.
Check the docs for more information:
https://api.flutter.dev/flutter/material/DropdownButton-class.html