Incoming constraints for Container in Flutter. Do i get it wrong? - flutter

As documentation says
Containers with no children try to be as big as possible unless the
incoming constraints are unbounded, in which case they try to be as
small as possible
Well when I make incoming constraints unbounded for inner Container i suppose that it should be as small as possible but it expands for entire screen.
body: Container(
color: Colors.red,
constraints: const BoxConstraints(
maxHeight: double.infinity,
maxWidth: double.infinity,
),
child: Container(
color: Colors.green,
),
),
Why?

If you read the documentation a bit further, you'll see that constraint arguments on the Container itself will override this behavior:
Containers with no children try to be as big as possible unless the incoming constraints are unbounded, in which case they try to be as small as possible. Containers with children size themselves to their children. The width, height, and constraints arguments to the constructor override this.
Try wrapping the inner childless Container in an UnconstrainedBox, and you'll see it will shrink to zero width and height.
body:
Container(
color: Colors.red,
width: double.infinity,
height:double.infinity,
child: UnconstrainedBox(
child: Container(
color: Colors.green,
),
),
)

Although red container has infinite size, You put it in a scaffold's body which has specific size. so your red container get specific size then your grin container with no child get size as much as its parents.

The red container actually will has size as small as posibble depends its child.
the green container has no child, then as the documentation said it will try to be as big as possible unless the incoming constraints are unbounded,
if you change the child , like Text widget, or Column, or other widget, it will not get the maximum size.

Related

Flutter Container inside a Container and Text widget

Container(
color: Colors.green,
width: 300,
height: 300,
child: Container(
color: Colors.purple,
width: 200,
height: 200,
),
),
when I do this why the child container size is the same as parent container size? but when i pass alignment: Alignment.center inside the parent container, this give a expected output?
Output
Because the parent widget forces the child widget to be the same exact size.
From the docs:
If a child wants a different size from its parent and the parent
doesn’t have enough information to align it, then the child’s size
might be ignored. Be specific when defining alignment.
You could also wrap the inner Container in a Center widget and it would also work.
See the examples here https://docs.flutter.dev/development/ui/layout/constraints

How to dynamically change container size with text quantity in flutter?

I want to create a container in flutter which changes its height according to the amount of text present in it.
If there is more text, it should cover more height, if text is less, it should cover less height.
You can use fitted Box and width of container will help you to increase height dramatically.
FittedBox(fit: BoxFit.fill,
child: Container(width: 70,
child:
Text('hello '), color: Colors.red,
)
)

Flutter dynamic data in a container

I am new to flutter and I must say I am impressed comming from a c# background I was able to do a listview in under five mins that were horizontal and contained a few containers.
However, I would like my container to be dynamically showing a List contents what I have so far is a widget building my colours out
Widget horizontalList2 = new Container(
margin: EdgeInsets.symmetric(vertical: 20.0),
height: 200.0,
child: new ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Container(width: 160.0, color: Colors.blue,),
Container(width: 160.0, color: Colors.green,),
Container(width: 160.0, color: Colors.cyan,),
Container(width: 160.0, color: Colors.black,
child:Text("Test"),
child: Image.network(
'https://flutter.io/images/catalog-widget-placeholder.png',
height: 100,
width: 150
)
)
But as you see I am trying to create another text element I want image then a bit of text and another text much the same way as Netflix would work but it's for a weather app.
Can someone explain how the child elements works can ou not have more than one child in a container cause when i tried this i got the following error. And what I should do to have a second child element of text and base the listview of a Dynamic POCO List
The [child] contained by the container.
If null, and if the [constraints] are unbounded or also null, the container will expand to fill all available space in its parent, unless the parent provides unbounded constraints, in which case the container will attempt to be as small as possible.
You should use Multi-child layout widget, these accept children instead of child. A good example for you might be Row, Column or Stack.
Don't be scared of nesting your Widgets, you'll be doing it a lot!
ListView
Container
Row
Text
Image
Icon
Container
Row
Text
Image
Icon
When you find yourself repeating your widget tree like this, create a custom widget that outputs the subtree. The above might become:
ListView
MyColoredListItem
MyColoredListItem
You can find a full list of Multi-child layout widgets on the flutter docs here:
https://flutter.dev/docs/development/ui/widgets/layout#Multi-child%20layout%20widgets
For more information about creating your own widgets:
https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html
https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html

Flutter SizedBox vs LimitedBox

I have read docs for both SizedBox and LimitedBox, and didn't find any practical difference between the two.
Can anyone give an example when one may fail and other work?
So what I have found is, LimitedBox is only usable when the child is given unconstrained width/height by its parent.
And SizedBox simply creates a box with given width/height and doesn't allow child to go beyond given dimensions.
Example: (LimitedBox)
#override
Widget build(BuildContext context) {
return Scaffold(
body: LimitedBox(
maxHeight: 50, // no impact because it's child `Text` width/height isn't unconstrained
child: Text(
"A",
style: TextStyle(fontSize: 200),
),
),
);
}
Example (SizedBox)
#override
Widget build(BuildContext context) {
return Scaffold(
body: SizedBox(
height: 50, // has impact, it won't let Text to be of more than 50 logical pixels high
child: Text(
"A",
style: TextStyle(fontSize: 200),
),
),
);
}
Note: If anyone has better answer, I am happy to accept theirs.
LimitedBox is a SizedBox unless the parent widget imposes a constraint.
From Doc
A box that limits its size only when it's unconstrained.
Reference
Flutter doc
LimitBox:
LimitBox works only when it's size is unconstrained If this widget's
maximum width is unconstrained then its child's width is limited to
[maxWidth]. Similarly, if this widget's maximum height is
unconstrained then its child's height is limited to [maxHeight].
Example:
Center(
child: LimitedBox(
maxWidth: 50,
child: Container(
color: Colors.red,
width: 20,
height: 100,
)
),
),
Output:
This restricts Container Widget with a max-width as 50 but it's going to show widget till container width which is 20.
SizeBox:
It comes with fixed sizes that restrict its child to render on the
limited area. If either the width or height is null, this widget will
try to size itself to match the child's size in that dimension. If the
child's size depends on the size of its parent, the height and width
must be provided.
Example:
Center(
child: SizedBox(
width: 50,
child: Container(
color: Colors.red,
width: 20,
height: 100,
)
),
),
Output:
This will also behave like LimitedBox but the only difference here Container will be rendered till width 50 of SizeBox, it will not consider it's own width which is 20 and drawn till the parent widget.
Can anyone give an example when one may fail and other work?
They'll both work, but they'll do different things. The example from the LimitedBox documentation says:
This is useful when composing widgets that normally try to match their parents' size, so that they behave reasonably in lists.
Imagine that you are creating a reusable widget and don't have control over where it's used. You could use a SizedBox, but then your widget will always have the specified size, even if its size is already constrained by a parent widget.

Make container widget fill parent vertically

TL;DR Need the container to fill the vertical space so that it can act as a ontap listener. Have tried most solutions but nothing seems to work.
So what I am trying to do is to make my container fill up the vertical space while still having a fixed width. Two first is what I have and third is what I want. The idea is to have the container transparent with a gesture ontap listener. If anyone have a better idea as for a different solution, feel free to suggest.
Widget build(BuildContext context) {
return new GestureDetector(
onHorizontalDragUpdate: _move,
onHorizontalDragEnd: _handleDragEnd,
child: new Stack(
children: <Widget>[
new Positioned.fill(
child: new Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
new Container(
child: new IconButton(
padding: new EdgeInsets.only(top: 16.0, bottom: 16.0, left: 24.0, right: 24.0),
icon: new Icon(Icons.warning),
color: Colors.black12,
onPressed: () {},
)
),
],
),
),
new SlideTransition(
position: new Tween<Offset>(
begin: Offset(0.0, 0.0),
end: const Offset(-0.6, 0.0),
).animate(_animation),
child: new Card(
child: new Row(
children: <Widget>[
new Container(
width: 20.0,
height: 20.0,
color: Colors.amber,
),
new Expanded(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
_getListTile(),
_ifStoplineIsToBeShown()
],
),
)
],
)
),
),
],
)
);
}
I am quite sure that i have been missing something considering the fact that I have tried a lot of different things and nothing seems to work.
I have also uploaded an image with the debug painting here.
PS. I know I have set the height to a fixed value, but this is the only way to show the container.
The trick is to combine an IntrinsicHeight widget and a Row with crossAxisAlignment: CrossAxisAlignment.stretch
This force the children of Row to expand vertically, but Row will take the least amount of vertical space possible.
Card(
child: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
width: 20.0,
color: Colors.amber,
),
// Expanded(...)
],
),
)
)
To stretch the container to full height of the parent use property constraints:BoxConstraints.expand() in container widget. Container occupy the complete space independent of the of child widget
Container(
color: Colors.green,
child: Text("Flutter"),
constraints: BoxConstraints.expand(),
)
Please refer the link Container Cheat sheet for more about container
Simply pass in: double.infinity.
If you want a Container to fill all available space, you can just pass in:
width: double.infinity,
height: double.infinity
Explanation:
In Flutter, a child widget cannot exceed the "layout constraints" imposed by its parent widget. During the layout phase, Flutter engine uses a constraint solver to automatically correct "out-of-bound" values into what's allowed by its parent constraints.
For example, if you have a Container that's 50x50, and for its child, you pass in another Container that's 300x300, the inner container will be automatically corrected to "not exceed its parent", thus 50x50. Therefore, using sufficiently large values would always make sure you "fill parent".
In fact, even BoxConstraints.expand() exploits the same idea internally. If you open up the source code of expand(), you will see:
/// Creates box constraints that expand to fill another box constraints.
///
/// If width or height is given, the constraints will require exactly the
/// given value in the given dimension.
const BoxConstraints.expand({
double width,
double height,
}) : minWidth = width ?? double.infinity,
maxWidth = width ?? double.infinity,
minHeight = height ?? double.infinity,
maxHeight = height ?? double.infinity;
So if you are absolutely certain you want to fill all spaces, you can intuitively pass in a number bigger than the parent (or larger than the whole screen), like double.infinity.
As of Jan 2020 the simplest is to use an Expanded Widget
Expanded(flex: 1,
child: Container(..),
),
https://api.flutter.dev/flutter/widgets/Expanded-class.html
There are many answers which suggest using two things
constraints: BoxConstraints.expand(),
height: double.infinity,
But both these answer will give you an error like
BoxConstraints forces an infinite height.
We can avoid these by calculating the height of the screen like
App Bar
Top Bar Space(Exist on the above App Bar)
Remaining screen
1. Get the MediaQuery
final mediaQuery = MediaQuery.of(context);
2. Declare the AppBar Widget and same App Bar instance should be used in Scaffold App Bar
final PreferredSizeWidget appBar = AppBar(
title: Text('Home'),
);
3. Use calculated height
Container(
width: mediaQuery.size.width,
height: (mediaQuery.size.height -
appBar.preferredSize.height -
mediaQuery.padding.top),
color: Colors.red,
),
Output:
Set the height or width of a container to double.maxFinite
Container(
height: double.maxFinite,
width: 100,)
You can make your widget take the full size of a Container widget, and then set the container's height and/or width to double.maxFinite. This will make the Container take the height and/or width or its parent widget
I propose using Expanded widget (which allows us to avoid IntrinsicHeight widget), combine it with the Container's alignment property and therefore make it work properly even if the Container is not the only one at the screen.
Expanded(
child: Container(
alignment: Alignment.center,
child: Text('Your text', textAlign: TextAlign.center))),
That way one also avoids potential app's crash which occurs often when you accidentally expand to infinity some parts of the widget tree both horizontally and vertically (that is why you are not able to use BoxConstraints widget in many cases).
One can read more about the problems of passing constraints in Flutter here - a must read: https://medium.com/flutter-community/flutter-the-advanced-layout-rule-even-beginners-must-know-edc9516d1a2
This work works for me
height: MediaQuery.of(context).size.height,