Reputation: 4575
I have a container that I want to start off at a minimum size and grow (if its contents grow while user is adding content) to a maximum size, then stop.
The correct widget for this seems to be ConstrainedBox, like so:
new ConstrainedBox(
constraints: new BoxConstraints(
minHeight: 35.0,
maxHeight: 60.0,
),
child: ...child with growing content (has default height 25.0)...
),
however, this starts the box off at the maxHeight.
I tried to use hasBoundedHeight, but can not seem to construct the correct syntax for it or find an example in documentation.
What is the best way to get the box working as described?
Upvotes: 156
Views: 206384
Reputation: 277527
There's no notion of "Starts from max/min size".
The thing is, ConstrainedBox
only add constraints to it's child. But in the end, it doesn't pick a size.
If you want your child to hit minSize, then they have to not expend. Which translate into not having a width/height of double.INFINITY
. Fact is that double.INFINITY
is the default value of many widgets, including Container
.
On the other hand, some widgets such as DecoratedBox
have a default size of 0.
Which means that this code :
return new ConstrainedBox(
constraints: new BoxConstraints(
minHeight: 5.0,
minWidth: 5.0,
maxHeight: 30.0,
maxWidth: 30.0,
),
child: new DecoratedBox(
decoration: new BoxDecoration(color: Colors.red),
),
);
Will render a 5.0*5.0 red square.
Upvotes: 254
Reputation: 6284
Let me explain:
If child of BoxConstraints
is (Column
widget) or (ListView
widget), maxHeight
will not work as expected, it will work as height
, to solve that:
1 - If child of BoxConstraints
is Column
, your code need to be like this:
Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * .30
),
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: const [
// growable childrens
],
),
),
);
2- If child of BoxConstraints
is ListView
, your code need to be like this:
Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * .20,
),
child: ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: const [
// growable childrens
],
),
);
As is the case if child of BoxConstraints
is Row
, maxWidth
will not work as expected, it will work as width
, to solve that you need to set mainAxisSize
to MainAxisSize.min
like this:
Container(
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * .15
),
child: SingleChildScrollView(
child: Row(
mainAxisSize: MainAxisSize.min,
children: const [
// growable childrens
],
),
),
);
Upvotes: 8
Reputation: 34250
Below Example will help you to grow Size of the widget as required
Container(
color: Colors.blueAccent,
constraints: BoxConstraints(
minHeight: 100, minWidth: double.infinity, maxHeight: 400),
child: ListView(
shrinkWrap: true,
children: <Widget>[
...List.generate(
10, // Replace this with 1, 2 to see min height works.
(index) => Text(
'Sample Test: ${index}',
style: TextStyle(fontSize: 60, color: Colors.black),
),
),
],
),
),
Output for Min Height for Single Item:
Output for Min Height for 10 Items:
Note: This will show widgets as per mentioned max-height.
Upvotes: 49
Reputation: 21
try to use Contraints box instead of Sized box because sized box have not min height and min width property they just have height and width property
ConstrainedBox(
constraints: const BoxConstraints(
maxHeight: Dimension.d9,
minHeight: Dimension.d9,
maxWidth: 144.0
),
);
Upvotes: 0
Reputation: 7952
As Remi's answer points out, if your ConstrainedBox
is initially maxing out a dimension when you expected it to be closer to or at the min, it's because a child wants to be big. (Re: Constraints go down. Sizes go up. Parent sets position.) If you aren't sure which child is causing it, one handy way is to use the Widget Inspector in your IDE and check the properties of the descendants, then check the docs as to why and adjust accordingly.
For example, I've run into this e.g. when wrapping a widget in Center
. Normally without constraints the centered widget would match the child's height. However, when putting the Center
inside a ConstrainedBox
, all of a sudden it blew up to the max constraints. After checking the docs, I saw that:
This widget will be as big as possible if its dimensions are constrained and widthFactor and heightFactor are null
, explaining the new layout.If a dimension is unconstrained and the corresponding size factor is null then the widget will match its child's size in that dimension
, which explains the behavior without the
ConstrainedBox
. If a size factor is non-null then the corresponding dimension of this widget will be the product of the child's dimension and the size factor
,
i.e. set the Center
's heightFactor: 1
.So pay attention to how your children behave! If you impose external constraints, they may be greedy (or not, just like real kids ;).
Upvotes: 1
Reputation: 1593
For Column
for example, minHeight
is not working. I solved it using this hack:
ConstrainedBox(
constraints: BoxConstraints(minHeight: 150),
child: Stack(
children: [
Column(
children: [dynamicChild1, dynamicChild2],
),
],
),
);
So, just by wrapping Column
in Stack
. Now the Column size became 150 and more.
Upvotes: 4
Reputation: 21
Yes, ConstrainedBox is the right widget for the purpose. If you'll give only minHeight parameter for eg. 300, the child will be of minimum height and will increase its size according to its content.
Here's an example:
ConstrainedBox(
constraints: BoxConstraints(
minHeight: 300,
),
child: Container(child : SomeWidget(),)
If height required by SomeWidget() is less than 300, it will be of height 300. Otherwise, it will increase it's height accordingly. For decoration and structuring your SomeWidget(), you can use padding and other properties of Container.
Upvotes: 2
Reputation: 811
You can use deviceWidth and deviceHeight to check for min and max condition. Use the following code to get the deviceWidth and deviceHeight in build method.
double deviceWidth = MediaQuery.of(context).size.width;
double deviceHeight = MediaQuery.of(context).size.height;
In width
and height
property of Container
use deviceWidth
and deviceHeight
to form your condition.
Container(
width: deviceWidth<200?50:deviceWidth*0.5,
height: deviceHeight<500?50:deviceHeight>800?200:deviceHeight*0.2,
child: //child,
)
Note: Only Ternary Operator ?:
works for specifying condition for height and width
Upvotes: 3