Flutter show iconButton based on Map - flutter

i have a map like this:
static const Map<String, Map<String, String>> social = {
'personA': {
'twitch': 'https://www.twitch.tv/...',
'instagram': 'https://www.instagram.com/.../'
},
'personB': {
'twitch': 'https://www.twitch.tv/...',
'instagram': 'https://www.instagram.com/.../'
},
'personC': {
'facebook': 'https://www.facebook.com/...',
},
};
It's possible to show iconButton, with the font_awesome icon, for each
social related to each person, and on click redirect to the link?, how ?
i tried like this:
Row(
children: <Widget>[
ListView.builder(
itemBuilder: (_) {
return Constants.social[person].keys.map((e) =>
IconButton(icon: FaIcon(FontAwesomeIcons.e), onPressed: {
print("example");
});
);
}
)
],
),
but i receive the error:
The argument type 'Widget Function(BuildContext)' can't be assigned to the parameter type 'Widget Function(BuildContext, int)'
the variable person can contain personA, personB or personC.
For example for personA i want to to show 2 iconButton one for twitch and one for instagram but for personC i want to show only facebook icon.

ListView is a widget that represents a list of widgets arranged linearly.
You have multiple constructors for this widget. The one you used, ListView.builder() is the one suggested when there is a large number of children to be displayed. (In your example, if the Map contains many players.)
The default constructor only requires a List<Widget> and is considerably more simple. If you don't have a large map, I strongly suggest you to use this one instead. But since you tried using the builder one, you should do as follow:
First, have your data arranged in a List. This way you can access the elements through an integer index easily: List[0]. Ideally you should have the data already in a list form, but if you need you can convert it like this:
static const Map<String, Map<String, String>> social = {
'personA': {
'twitch': 'https://www.twitch.tv/...',
'instagram': 'https://www.instagram.com/.../'
},
'personB': {
'twitch': 'https://www.twitch.tv/...',
'instagram': 'https://www.instagram.com/.../'
},
'personC': {
'facebook': 'https://www.facebook.com/...',
},
};
List<Map<String,String>> listUsers = List().from(social.values);
For more information on these methods, check this and this.
Supply the number of itens your listview will have through the itemCount parameter:
[...]
ListView.builder(
itemCount: listUsers.length,
itemBuilder: (context, index) {
[...]
Your error says the builder function needs to receive another integer parameter:
'Widget Function(BuildContext)' can't be assigned to the parameter type
'Widget Function(BuildContext, int)```.
This integer parameter represents what widget in the list it will be. Your builder function needs to return only one widget, and it receives the index parameter so you can know which one it is:
Row(
children: <Widget>[
ListView.builder(
itemCount: listUsers.length,
itemBuilder: (context, index) {
return Column(children:[
if (listUsers[index].containsKey('twitch'))
IconButton(icon: FaIcon(FontAwesomeIcons.twitch), onPressed: (){//Access listUsers[index]['twitch'] here
}),
if (listUsers[index].containsKey('instagram'))
IconButton(icon: FaIcon(FontAwesomeIcons.instagram), onPressed: (){//Access listUsers[index]['instagram'] here
})
])
}
)
],
),
This should be enough to have your desired result. As a suggestion, you can read the official documentation which has many good examples and explanations. The Dart Language tour is also a great place for examples about the language. They are both well written and in this case would get you in the right track.

Related

Can I get a logic/code for highlighting the desired value in the list view builder in flutter

[
Can I get a logic/code for highlighting just the selected value from this list view which is inside a container and it is scrollable also that the axis is set to Horizontal.
I have used a list view builder to align the same and also generated the list of numbers.
Please check the sample image of the widget attached.
Blockquote
]1
It's hard to tell you exactly how to do it without any code examples, and I'm also not sure what you mean by selected. Is that already decided before building the list, or is it decided when the user selects from the list?
If it is already decided, you can pass a value from the parent component that tells the list to highlight a certain value.
If a user is selecting the value to highlight, you can use a combination of setState and onTap with GestureDetector. Here's a potential rough skeleton:
int selectedIndex?;
ListView.builder(
itemCount: litems.length,
itemBuilder: (BuildContext ctx, int index) {
return GestureDetector(
onTap: () {
setState(() {
selectedIndex = index;
});
},
child: Container(
backgroundColor: selectedIndex == index ? highlightedColor : undefined;
child: {{child content}}
),
);
}
)

Flutter Riverpod listview index length

I have a listview which is using flutter_riverpod. The listview have 2 variable.
First variable is word text and second variable is length of index.
ListView.builder(
itemCount: ref.watch(itemsProvider).length,
itemBuilder: (BuildContext context, int index) {
return Row(
children: [
Text(ref.watch(itemsProvider)[index]),
Text(ref.watch(itemsProvider)[index].length),
],
);
},
),
I am using this listview.builder. the first text of Row is working but second text of Row is not working.
The error:
the argument type 'int ' can't be assigned to the parameter type 'string'
How can I solve this problem. The is no problem in widget. I am using consumerwidget, ref and widgetref. and scopped runapp.
Text widget seeks from String, Use string format
Text("${ref.watch(itemsProvider)[index].length}"),
Also, you can use .toString()
More about dart-core

Avoid Bloc state-sharing with multiple Widget instances in Flutter

Good day everyone, I'm using Flutter with bloc and I'm trying to show a list of Channels which you can "Follow" o "Unfollow".
I have a custom ChannelContainer Widget that loads a list with channel titles and a custom widget JoinButton which shows whether the user can "Follow/Unfollow" depending on the state (If the channel is already being followed or not).
Widget _getChannelsList() {
List<Post> channelList = ContentService().getAllChannels();
return ListView.separated(
itemBuilder: (_, i) => ChannelContainer(
title: channelList[i].title,
description: channelList[i].description,
idChannel: channelList[i].id),
separatorBuilder: (_, i) => SizedBox(height: 5.0),
itemCount: channelList.length,
);
}
This is my custom JoinButton Widget:
#override
Widget build(BuildContext context) {
final channelBloc = BlocProvider.of<ChannelBloc>(context);
channelBloc.add(GetJoinStatus(idChannel));
return Container(
child: BlocBuilder<ChannelBloc, ChannelState>(builder: (context, state) {
var userIsJoined = state.userIsJoined;
if (userIsJoined) {
return ElevatedButton(
child: Text('Unfollow'),
onPressed: () {},
);
} else {
return ElevatedButton(
child: Text('Follow'),
onPressed: () {},
);
}
}),
);
}
I made a test checking the idChannel and returning true to even numbers and false to odd ones and thought that as I was creating multiple JoinButtons, each one would keep their state (followed or not) but as I'm firing the GetJoinStatus() event each time a JoinButton is instantiated and the state changes all the buttons get rebuilded and get the same state.
So, at the end I have a list of JoinButtons that are all getting just Follow or Unfollow but not mixed results.
What would be the best way to get the expected result? I've tried a lot of things that could work but anything compatible with bloc workflow... Thank you in advance!
I think the best way to do this is to have a map in your bloc state whose key is the channel id and the value is a boolean true if joined and false if not.

I am trying to get a key and and a corresponding value from a Dart map but I'm failing no matter what I try

Here is the data; it's a list and one of the items (credit vendors) is a map of k, v pairs. I want to put each key and each value in their own Text widget. The code is below.
List<Blog> blogs = [
Blog(
title:
"She changed religion to marry the man of her dreams- Hamidah and Efraim’s classy Kwanjula ",
description:
"Right after their arrival, Efraim and a select few of his entourage went right into "
"Hamidah’s parents’ house for the basic session of kwanula: to be accepted and born into this home. \n",
author: "James Arthur",
date: "09 Jan 20",
views: 3899,
comments: 23,
imagePath: "assets/images/intro.jpg",
creditVendors: [
{'Decorator': 'Parties & Events'},
{'Photography': 'Paramount Images'},
{'Food': 'Spectrum Restaurant'},
{'Juice': 'Dalausi Juice'},
{'Bridal': 'Sheena Collections'},
],
),
Blog(),
Blog(),
];
So I want to call creditVendors values within another class on a different page. Below is the code to illustrate what I am trying to achieve.
Container(
height: 200.0,
child: ListView.builder(
itemCount: widget.blog.creditVendors.length,
itemBuilder: (BuildContext, int index) {
Blog blog = blogs[index];
return Row(
children: [
Text(blog.creditVendors.keys),
Text(blog.creditVendors.value),
],
);
}),
)
You can iterate over maps by their values or keys. That won't be necessary since your creditVendors is an array itself.
Then you can use ListView widget to create widgets of your own choice from the values of the map.
Sample code
List<dynamic> creditVendors = [
{'Decorator': 'Parties & Events'},
{'Photography': 'Paramount Images'},
{'Food': 'Spectrum Restaurant'},
{'Juice': 'Dalausi Juice'},
{'Bridal': 'Sheena Collections'},
];
ListView.builder(
itemCount: creditVendors.length,
itemBuilder: (ctx, int index) {
return ListTile(
*emphasized text* title: Text(
'${creditVendors[index].keys.first} - ${creditVendors[index].values.first}'));
}),
You can get all the keys from a map using mapName.keys method
You can get all the values from a map using mapName.values method
Update:
You have to use nested ListView since you iterating over two lists -> one is blogs array and inside that you want to iterate over that blog's creditVendors list.
Please see the demo code:
ListView.builder(
itemCount: widget.blog.length,
shrinkWrap: true,
itemBuilder: (ctx, int _blogIndex) {
Blog_blog = blogs[_blogIndex];
return ListView.builder(
itemCount: _blog['creditVendors'].length,
shrinkWrap: true,
itemBuilder: (ctx, int index) {
return ListTile(
title: Text(
'${_blog['creditVendors'][index].keys.first} - ${_blog['creditVendors'][index].values.first}'));
});
}))
I hope you know that the blog list has only one elemet of type Blog
So I did it for only one element. If you have more just iterate rest everything will be same.
You should do the following:
Blog a = blog[0]; //this will put the first element in a
then:
define variables as maps because the content inside creditVendors is of type maps
and creditVendors is again a list data type.
// this is just to collect the data inside creditVendors.
Map decorator;
Map photography;
Map food;
Map juice;
Map bridal;
decorator = a.creditVendors[0];
photography = a.creditVendors[1];
food = a.creditVendors[2];
juice = a.creditVendors[3];
bridal = a.creditVendors[4];
Now:
you can access each map data as:
Text(decorator['Decorator'],)
Text(photography['Photography'],)
Text(food['Food'],)
Text(juice['Juice'],)
Text(bridal['Bridal'],)
PS. CreditVendor is a list of Maps

ListView renders multiple widget after calling setState in Flutter

I have this function that shows a showDialog widget with a child of ListView builder based on a list
My problem is that when I add items to the list using setState(In my case, stateSetter), the ListView re-render duplicated widget.
As I'm debugging the issue, I noticed that it only happens when I'm using a Column/Row widget.
//result in listview
(1st setState)
Product1
(2nd setState)
Product1
Product2
Product1
Product2
Code below:
void showProductDialog() {
//variable for ListViewBuilder
List<Product> _products = [];
showDialog(
//..context,builder, etc...
return AlertDialog(
//..title, etc..
content: StatefulBuilder(builder: (ctx, stateSetter) {
return Container(
child:Column(
children: [
ListView.builder(
itemCount: _products.length,
itemBuilder:(ctx,index) {
//problem occurs
return Column(children: _products.map((e) => Text(e.name)).toList()
}
),
RaisedButton.icon(
onPressed: () {
stateSetter((){
// adding new item to list
_products.add(Products(...))
})
...
Any help and suggestion will be much appreciated!
Thankyou!
EDIT: The list variable are behaving properly, when I print all the items, all of it are unique. The duplicate issue was only occured on rendering the items to Column
EDIT 2: The purpose of using column widget is to print data somehow properly.
Example of what to expect:
Product1
Name: Sample name
Price: $1
Product2
Name: Sample 2
Price: $2
i cant see the whole code but try this
Just clear the list before adding again
use
stateSetter((){
// clear the list to prevent duplication
_products.clear(),
// adding new item to list
_products.add(Products(...))
})
Sorry, my problem. I did not read your request carefully
My solution:
ListView.builder(
itemCount: _products.length,
itemBuilder:(_,index) {
return Text(_products[index].name); // remove Column
}
),