Flutter iterate through List with access to index - flutter

I tried some other solutions to this like using asMap() and forEach but kept getting different errors. Like it was saying the return type of my ChartBar isn't a 'MapEntry', as defined by anonymous closure, or The expression here has a type of 'void', and therefore cannot be used.
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.end,
children: myList.map((data) {
return ChartBar(
///etc
}).toList(),
)
I want the index as well.

mirkancal's suggestion didn't work because Map.map returns another Map (and therefore the enumeration callback you pass it is expected to return a MapEntry).
You instead need to use Map.entries so that you can use Iterable.map instead to construct a List:
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.end,
children: myList.asMap().entries.map((MapEntry entry) {
return ChartBar(entry.key, entry.value);
}),
)
You alternatively can use Dart's new collection-for construct:
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.end,
children: [for (MapEntry entry in myList.asMap().entries)
ChartBar(entry.key, entry.value)
],
)
In the above, entry.key will be the index, and entry.value will be the original value in myList.

For the index you could use indexOf(value) function from the list to get index value. For example:
List list = List.generate(3, (int index) => index * index); // [0, 1, 4]
list.indexOf(4) // returns 2
As for your other issue, I'd need to see more code to see how you populate myList. I would suggest this approach (if it fits) to render your Row children. Use a function to return that list, for example:
buildList() {
List<Widget> list = List<Widget>();
chartBars.forEach((chart) => { //chartBars list with info
// add your ChartBar widget to the list with appropiate info
list.add(ChartBar(someProperty: chart.property));
});
return list;
}
Then on your Row widget just call that function when you build it's children:
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.end,
children: buildList()
)

Related

how to set itemCount in map.toList()

i usually use ListView.builder but in this case im using list.map.toList() then now i need to limit the length of the item / itemCount but how ?
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: data
.map<Widget>(
(e) => card(e),
)
.toList(),
),
To limit the number of items displayed in the Row, you can use the take() method to create a new list with a limited number of items.
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: data
.map<Widget>((e) => card(e))
.take(5) // Limit the list to 5 items
.toList(),
)
You can use for loop with min from dart:math to solve this
Row(
mainAxisAlignment: MainAxisAlignment.start,
children:[
for(int i = 0; i < min(3, data.length); i++)
card(data[i]),
),

how to initialize a map in flutter/dart with widgets

what i am trying to is have containers widget to have unique id so that i can uniquely identify them i have tried :
Map<int,Container> box={
1:Container(),
2:Container(),
3:Container(),
};
Map<int,Widget> box={
1:Container(),
2:Container(),
3:Container(),
};
Column(
mainAxisAlignment: MainAxisAlignment.start,
children:<Widget> [
box[1],
],
),
Column(
mainAxisAlignment: MainAxisAlignment.start,
children:[
box[1],
],
),
tried both
is there any way to do this .
I believe you are trying to use List<Widget>
Define:
List<Widget> list = [Container(), Container(), Container()];
Use:
Column(
children: [list[0]],
);

Flutter: Scrollable row, alignment?

I am trying to create scrollable row that does not automatically center its items.
As you can see I have a row (that is scrollable via a SingleChildScrollView). However, the items are automatically centered by the SingleChildScrollView:
I want to be able to customize the alignment of the items to be either on the start or end. My code looks like this:
Widget buildHorizontalRow(List entries) {
var list = <Widget>[];
for (var entry in entries) {
list.add(Text(
entry.name,
));
}
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: list,
),
);
}
Note that when I remove the SingleChildScrollView completely, the items start on the left as expected. How do I make them start on the left and scrollable?
Update #1:
The parents of this row look like this:
Padding(
padding: const EdgeInsets.only(
left: 16.0, right: 16.0, bottom: 8.0, top: 8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [....
PS: Also please note that I do not want to use a ListView.
While using Column the default is crossAxisAlignment: CrossAxisAlignment.center,, using CrossAxisAlignment.start, solves the issue.
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
You can try this, it working from my side.
Widget buildHorizontalRow(List entries) {
var list = <Widget>[];
for (var entry in entries) {
list.add(Text(
entry.name,
));
}
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [Row(children:list),Expanded(child:Container(),),]
),
);
}

'Iterable<Widget>' can't be assigned to the list type 'Widget'

I'm learing flutter and I tried to recreate this from fireship.io.
I copied the code and I get this Error:
The element type 'Iterable<Widget>' can't be assigned to the list type 'Widget'.
Code:
List items = [
MenuItem(x: -1.0, name: 'house'),
MenuItem(x: -0.5, name: 'planet'),
MenuItem(x: 0.0, name: 'camera'),
MenuItem(x: 0.5, name: 'heart'),
MenuItem(x: 1.0, name: 'head'),
];
Container(
// <-- 4. Main menu row
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.end,
children: [items.map((item) => _flare(item))],
),
),
Class MenuItem:
class MenuItem {
final String name; // name is the filename of the .flr asset
final double
x; // x is the X-axis alignment of the item (-1 is far left, 1 is far right).
MenuItem({required this.name, required this.x});
I found a question with the same error but I couldn't solve it.
map returns iterable, so you've to convert that to list. Also you don't need to use [] there.
Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.end,
children: items.map((item) => _flare(item)).toList(),
),
),
try this way
children: [
...items.map((item) => _flare(item)).toList(),
],

Visibility Widget Occupies Area In Row Widget?

In my code, the third Container should not be included since it is wrapped in the Visibility widget. This is what I have tried,
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Container(...),
Container(...),
Visibility(visible:false, child: Container(...))
]
)
What it should look like:
What actually happened:
According to the Visibility documentation:
By default, the visible property controls whether the child is included in the subtree or not; when it is not visible, the replacement child (typically a zero-sized box) is included instead.
This shows that just because a widget is wrapped in the Visibility widget, doesn't mean it doesn't exist in the widget tree.
The best way to go about this would be to make the widget null so it isn't included in the widget tree.
bool notNull(Object o) => o != null;
bool isVisible = false;
...
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Container(...),
Container(...),
isVisible? Container(...) : null,
].where(notNull).toList(),
)
Or you could optionally create the list in a build method so that you can simply add your widget to the list if a certain condition is met.
Builder(
build: (context) {
bool isVisible = false;
List<Widget> _children = [
Container(...),
Container(...),
];
if (isVisible) {
_children.add(Container(...)); // Optional widget
}
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: _children,
);
}
),
Indeed your widget is not visible, but it does counts when calculating the spacing.
You can try using a builder
Builder(
build: (context) {
var children = [
Container(...),
Container(...),
];
if (your condition) {
childern.add(Container(...));
}
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: children
);
}
);