While learning flutter, I was trying to add some padding to an Image widget which was wrapped inside an Expanded widget, my approach was to wrap the Expanded widget with a Padding widget, but as a result the image actually overflowed.
When I changed the code to wrapping the Image widget inside a Padding instead, it worked fine. So my question here is, why did the image overflow when I used the Padding on the Expanded widget instead of the image ? Is it not possible to do that in Flutter ?
I am pretty sure your issue was not overflowing of the Expanded widget when you wrapped it with Padding, but rather Flutter threw an Incorrect use of ParentDataWidget exception. That is because widgets like Expanded and Flexible has to be direct children of Column, Row or Flex widgets. That is why the only solution is to use the Padding over the child of Expanded.
Summarising, this code will not work:
Row(
children: const [
Padding(
padding: EdgeInsets.all(8.0),
child: Expanded(
child: Icon(Icons.icecream_outlined),
),
),
Text("SomeTextyTextHere"),
],
),
it will not work because Expanded has to be a direct child of Row.
This code however will work fine:
Row(
children: const [
Expanded(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.icecream_outlined),
),
),
Text("SomeTextyTextHere"),
],
),
Related
I'm having trouble with managing vertical overflow in my Flutter application.
Essentially, I have a main column with a container child that holds another column with 3 containers each containing a gridview:
stateful widget
Scaffold
body: Center
Column
Container
Column
Container
Gridview
Container
Gridview
Container
Gridview
What I've Tried:
Method 1:
to try and solve the vertical overflow, I have tried wrapping the containers in expanded, but the problem with that is it smushes everything together and I want all the content of the gridviews to be displayed at full height, with the ability to scroll down through the main column.
Method 2:
so next i tried wrapping the main column in a singlechildscrollview and removing the expanded wrappers from the containers, but that is giving me the "vertical viewport was given unbounded height" error.
What I Want:
ultimately, i want the containers to size automatically, to fit the content, and to be able to scroll down to view all of the content ion the main column.
i'm aware of the sizedbox solution, but again, i want the containers to resize automatically to fit the content inside.
what are my best options for achieving this?
UPDATE
these two official Flutter video explains this situation and the solution very well
https://youtu.be/ORiTTaVY6mM
https://youtu.be/LUqDNnv_dh0
it looks like what i want is to use sliverlists and slivergrids inside of a customscrollview instead of gridviews and listviews inside of a column
customscrollview
slivergrid
slivergrid
slivergrid
NOT
column
gridview
gridview
gridview
Try below code hope its help to you. try to wrap your GridView inside Expanded Widget
Center(
child: Column(
children: [
Expanded(
child: Container(
constraints: BoxConstraints(
maxHeight: double.infinity,
),
child: GridView(
shrinkWrap: true,
),
),
),
Expanded(
child: Container(
constraints: BoxConstraints(
maxHeight: double.infinity,
),
child: GridView(
shrinkWrap: true,
),
),
),
Expanded(
child: Container(
constraints: BoxConstraints(
maxHeight: double.infinity,
),
child: GridView(
shrinkWrap: true,
),
),
),
],
),
),
Or try flutter_staggered_grid_view Package hope its help to you.
I am having a problem with embedding a Row() widget as a child of parent Column() widget who was been constrained by a ConstrainedBox(maxHeight:150) widget.
With this scenario, I am getting a 'BoxConstraints forces an infinite height.' exception.
Here is the simplified code (I am only including the build() method for brevity):
#override
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: BoxConstraints(maxHeight: 150),
child: Column(
mainAxisSize: MainAxisSize.max,
children: [
Container(
color: Colors.yellow,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text("Hello"),
Text("There"),
],
),
),
],
),
);
}
I had read a previous post suggesting to use Expanded() to solve the exception so I wrapped the Container() widget above with Expanded() and that worked, but my question is WHY?
I was under the impression that Expanded() simply forces its associated child widget to occupy all of its parent's available space. But does it also get its child widget to recognize the constraints from its parent?
Another interesting aspect of this scenario is that if I wrap the Row() with Expanded() instead of Container(), it will not work and the exception will be thrown. For whatever reason, it has to be the Container().
All help greatly appreciated. I love Flutter, but I am still struggling with the nitty gritty of its layout algorithm.
/Joselito
This is because Rows and Columns will keep expanding based on their children,
for Row:- it will keep expanding horizontally and you'll usually see it overflows to the right of the screen.
For Column:- it will keep expanding vertically, and usually overflows the bottom.
By using Expanded, it will force Row and Column to expand infinitely, that is why there is an exception. It's different for container as it will follow it's parent's width and height.
https://flutter.dev/docs/development/ui/layout
I also had a lot of issues understanding constraints in flutter until I found this article. After a while I saw that the flutter team added the article in their documentation. Check it out, it's very good.
I am dynamically generating Chip widgets but the Wrap class is not wrapping overflowing widgets to next line.
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
physics: ClampingScrollPhysics(),
padding: const EdgeInsets.symmetric(
horizontal: 12,
),
children: [
Row(
children: [
Wrap(
spacing: 5,
children: _getChips(), // gets a list of chips
),
],
),
],
),
);
But I get this error in console
The following assertion was thrown during layout:
A RenderFlex overflowed by 94 pixels on the right.
The overflowing RenderFlex has an orientation of Axis.horizontal.
The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the RenderFlex to fit within the available space instead of being sized to their natural size.
This is considered an error condition because it indicates that there is content that cannot be seen. If the content is legitimately bigger than the available space, consider clipping it with a ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex, like a ListView.
Am I doing something wrong?
Try removing Row widget. Wrap with default direction is an alternative to Row that moves child widgets to the next line if there is no enough space.
Also, I'd recommend using SingleChildScrollView as a container instead of ListView to get scrolling behavior.
return Scaffold(
body: SingleChildScrollView(
physics: ClampingScrollPhysics(),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 12,
),
child: Wrap(
spacing: 5,
children: _getChips(), // gets a list of chips
),
),
),
);
I have two widgets in a row. The first widget is a black line with width 5.0, the second widget is a text widget whose size may vary according to the content. I want the first container to have the same height as of the second widget
One way is to make both widget child of an IntrinsicHeight widget and then declare the height of the first container as double.infinity. This should solve your problem. Example code is given below:
IntrinsicHeight(
child: Row(
children: <Widget>[
Container( //this is the first container
height: double.infinity
),
secondWidget(
)
],
)
Let me know if you have further query. Happy coding!
You can use Expanded widget. It divides siblings to the same height or width.
here is the code:
Row(
children: <Widget>[
Expanded(
child: Container(
color: Colors.red,
),
),
Expanded(
child: Container(
color: Colors.green,
),
)
And here is the result:
That is so easy. I wish it could help.
I've used both Expanded and Flexible widgets and they both seem to work the same.
What is the difference between Expanded and Flexible?
Scaffold(
appBar: AppBar(),
body: Column(
children: <Widget>[
Row(
children: <Widget>[
buildExpanded(),
buildFlexible(),
],
),
Row(
children: <Widget>[
buildExpanded(),
buildExpanded(),
],
),
Row(
children: <Widget>[
buildFlexible(),
buildFlexible(),
],
),
],
),
);
Expanded is just a shorthand for Flexible
Using Expanded this way:
Expanded(
child: Foo(),
);
is strictly equivalent to:
Flexible(
fit: FlexFit.tight,
child: Foo(),
);
You may want to use Flexible over Expanded when you want a different fit, useful in some responsive layouts.
The difference between FlexFit.tight and FlexFit.loose is that loose will allow its child to have a maximum size while tight forces that child to fill all the available space.
Widget under Flexible are by default WRAP_CONTENT although you can change it using parameter fit.
Widget under Expanded is MATCH_PARENT you can change it using flex.
Expanded - it is Flexible with set fit
class Expanded extends Flexible {
const Expanded({
Key key,
int flex = 1,
#required Widget child,
}) : super(
key: key,
flex: flex,
fit: FlexFit.tight,
child: child
);
}
You may use Flexible to resize the widgets in rows and columns. It's mainly used to adjust the space of the different child widgets while keeping the relation with their parent widgets.
Meanwhile, Expanded changes the constraints sent to the children of rows and columns; it helps to fill the available spaces there. Therefore, when you wrap your child in an Expanded widget it fills up the empty spaces.
Providing these videos from the Flutter's Official YouTube channel just to help out people, who might look for this in the upcoming future...
Expanded:
Flexible:
Expanded() is nothing more than Flexible() with
Flexible (fit: FlexFit.tight) = Expanded()
but, Flexible uses fit :FlexFit.loose by default.
FlexFit.tight = Wants to fit tight into parent taking as much space as possible.
FlexFit.loose = Wants to fit loose into parent taking as little space as possible for itself.
Expanded changes the constraints of a child widget so it fills any empty space. Expanded widget is a specialised Flexible widget with a set fit - Flexible(fit: FlexFit.tight. Expanded widgets also have a flex property.
Flexible makes the child widget flexible and resizable. You can add the flex or fit property to adjust the size and spacing.
Flexible fit properties include:
FlexFit.loose - The widget’s preferred size is used. (Default)
FlexFit.tight - Forces the widget to fill all of its extra space.
Flexible default will share the available space of the parent widget, but will NOT force the child to fit the space.
Expanded will share the available space of the parent widget, and force the child widget to change its width/height to fill the available space.
In fact, Expanded extends Flexible, which is a Flexible with FlexFit.tight. See the official document.
Here is a Container widget and three Flexible Widgets(flex = 1, fit = FlexFit.loose) in a row. We can see that the three flexible widgets share the same maxWidth (1/3 of the available screen width), and the blue one wants bigger than it, and the others want smaller. But as we can see, the blue guy has maxWidth as its width and the other widgets' width just fit their content.
Here is the code of the image above up:
Row(
mainAxisSize: MainAxisSize.max,
children: [
Container(
color: Colors.teal,
child: Text(
'Container Text ',
)),
Flexible(
child: Container(
color: Colors.blue,
child: Text(' Text.Flexible Text.Flexible Text.Flexible.')),
),
Flexible(
child: Container(
color: Colors.yellow, child: Text('Flexible Text.')),
),
Flexible(
child: Container(
color: Colors.lightGreen, child: Text('Flexible.')),
),
],
)