ListView is expanding the width of my widgets - flutter

It seems like ListView stretches the width of its children to 100% screen width.
For example, despite explicitly setting the width in the example below, the width is stretched.
ListView.builder(
shrinkWrap: true,
itemBuilder: (context, index) {
return SizedBox(
width: 120,
child: Container(
margin: EdgeInsets.all(10),
width: 100,
height: 200,
color: Colors.red),
);
},
itemCount: 3,
)
The only way I have avoided this problem has been to wrap the returned widgets in a Row, but I would prefer to avoid that if possible (don't want to clutter the code).

Just wrap your SizedBox inside Align, Center or UnconstrainedBox widgets.
Check more info here Layout Behavior https://api.flutter.dev/flutter/widgets/Container-class.html

Related

Change scroll bar color of a list

I have a List View builder that builds some widget and puts them in a scroll bar:
I want the scrollbar to be purple, which is right now. The problem is that whenever I scroll I get The Scrollbar attempted to use the PrimaryScrollController. This ScrollController should be associated with the ScrollView that the Scrollbar is being applied to.A ScrollView with an Axis.vertical ScrollDirection on mobile platforms will automatically use the PrimaryScrollController if the user has not provided a ScrollController. To use the PrimaryScrollController explicitly, set ScrollView.primary to true for the Scrollable widget.
Is there a way to create a similar result without getting this error? What goes wrong?
Code:
RawScrollbar(
thumbColor: Colors.purple,
child: ListView.separated(
// controller: c,
primary: false,
padding: EdgeInsets.only(left: 15.0, right: 15.0, top: 10.0),
separatorBuilder: (BuildContext context, int index) {
return Visibility(
visible: true,
child: Container(
height: height * margin,
width: width * .8,
));
},
itemCount: _foundEvents.length,
itemBuilder: (context, index) => EventCard(
width: width * .8,
cardPadding: width * .05,
height: getCardHeight(height, margin: margin),
event: _foundEvents[index]["event"],
isLoading: eventsState.eventIdLoading ==
_foundEvents[index]["event"].id,
),
),
)
In order to RawScrollbar could works, its need to Apply on primary scroll list. But now you are setting ListView's primary to false. So you need set primary to true.

ListView Builder vs SingleChildScrollView + Row combo

I want to make a responsive UI in my app. In my home page, I have ScrollView->Column->childrens structure.
When I want to use horizontal Listview.builder in my column, it throws me error because height is unbounded. I fix it with wrapping my listview builder with container and I give this container a height value. But I dont want to give this height hardcoded,
I want to make my container height to its own child's height. I searched it and found a solution like ScrollView->Row->list.generate instead of ListView.Builder. But is it okay to make it like this? Does it cause performance problems or is it a bad practice?
My list isn't big. It has max 20 elements
For example this throwing error:
#override Widget build(BuildContext context) {
return Container(
color: Colors.red,
child: SingleChildScrollView(
child: Column(
children: [
ListView.builder(
itemCount: 5,
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return Container(
width: 200,
height: 200,
);
},
)
],
)),
); }
But this does not throw an error
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: List.generate(
5,
(index) => Container(
width: 200,
height: 200,
color: Colors.red,
)),
),
),
],
));
}
To clarify for everyone:
ListViews generate their children "lazily" - meaning they won't be drawn until they have been shown on screen. This means, of course, that they do not know the height of their items.
For example, if the ListViews children have heights similar to this list:
ooooOooo
But only this part was shown on the screen:
oooo | Oooo
And the ListView set it's height to fit "o" then it wouldn't be able to fit "O" when it eventually came on screen.
On the other hand, Rows do draw all of their children on spawn, meaning that, while they do know the size for all their widgets, they can become very slow quickly.
I would not suggest using images inside rows with 2-digit+ children, as they can be laggy not only on their initial draw, but also while the user does other things in the page containing said row - things such as scrolling up/down the page.
While testing I found that a row with just 30 children of the same stack (a small AssetImage on top of an IconImage) would lag the entire page when just scrolling up/down - not even scrolling along the row itself.
My recommended solution for you Ahmet, even though you don't want to hard-code your ListView's height, is to settle and set your ListView's height using:
MediaQuery.of(context).size.height * (percentage of screen's height you'd like for the ListView to take).

Wrap item different height in vertical PageView - Flutter

I have a vertical PageView with different item height :
But I would like to wrap each item according their height.
The final result I want here:
How can we do this ?
UPDATE 2022:
After some time, I returned to this problem and have now created a smart and slim pub.dev package with way more features, less buggy, and maintained code.
SnappyListView(
itemCount: Colors.accents.length,
itemBuilder: (context, index) {
return Container(
height: 100,
color: Colors.accents.elementAt(index),
child: Text("Index: $index"),
),
);
For those still interested in a non-packages solution (not recommended), make sure to check out the edit queue of this answer.
first of all, you should use SafeArea in order to prevent your widgets go through the notch. see [this][1].
Then you should use ListView instead of PageView because PageView creates pages with the same sizes. in ListView create an array of int that stores height of widget and use it to create widgets with different size.
List<int> heights = [100, 120, 10];// and so on
\\then use it as follow:
ListView.builder(
itemCount: 6,
itemBuilder: (context, i){
return Container(
height:heights[i],
width: 200, // or any value you want
padding: const EdgeInsets.all(8.0),
alignment: Alignment.center,
child: YourWidget);
},
),
[1]: https://stackoverflow.com/questions/49227667/using-safearea-in-flutter#:~:text=SafeArea%20is%20basically%20a%20glorified,%22creative%22%20features%20by%20manufactures.

Negative margin in Flutter to stretch carousel

I have a view like that
And I would like the image carousel to be without a horizontal margin like:
My image carousel is inside 3rd party widget so I need something like a negative margin?
I've tried transform on Container, but it only translates one side.
Container(
height: 160,
transform: Matrix4.translationValues(-20, 0, 0),
child: ListView(
scrollDirection: Axis.horizontal,
children: [
...
],
),
),
Why dont you set the width to double.infinity and if you want to specify a margin work with the following?
margin: const EdgeInsets.only(top: 8.0),

How to dynamically increase the height of a list and scroll after reaching a max height?

Hi i'm trying to create a list view to which i dynamically add items in the app. I want the height of the list to grow till it reaches a defined max height, and then show a scrollbar when it overflows.
_buildPage() {
return Container(
width: widget.width,
constraints: BoxConstraints(
maxHeight: widget.maxHeight,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_buildTitle(),
_buildAddBump(),
ListView.builder(
itemCount: _items.length,
itemBuilder: (context, index) => _buildItem(_items[index]),
),
],
),
);
}
This is of course not working since a ListView needs a pre-defined height. But wrapping the ListView in an Expanded will take all the remaining height and the ListView will be at maxHeight even when the items in it don't need the height.
I've tried putting the items in a SingleChildScrollView with a Column as a child, but that doesn't seem to do anything. The widget just overflows when i add more items than the height can hold. Is there a way to give a max height constraint to a list and tell it to take the height of its contents till it reaches the max height?
UPDATE:
I tried to add shrinkWrap: true to the ListView, but it's still not working. The page renders without errors and the ListView height increases as items are added, but when the height goes beyond maxHeight, it just overflows instead of adding a scroll.
Seems like I found the solution and it's quite easy. Wrap your ListView inside Flexible and set shrinkWrap to true:
...
Flexible(
child: ListView.builder(
itemCount: _items.length,
itemBuilder: (context, index) => _buildItem(_items[index]),
shrinkWrap: true,
)
),
...
If it's not the solution, let me know what is wrong in comments.