flutter - correct way to create a box that starts at minHeight, grows to maxHeight
DartFlutterDart Problem Overview
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?
Dart Solutions
Solution 1 - Dart
There's no notion of "Starts from max/min size".
The thing is, ContrainedBox
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.
Solution 2 - Dart
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.
Blog: https://medium.com/flutterworld/flutter-how-to-set-the-minimum-height-to-widget-36967b310ffe
Solution 3 - Dart
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
Solution 4 - Dart
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.
Solution 5 - Dart
ConstrainedBox(
constraints: BoxConstraints(
minWidth: 70,
minHeight: 70,
maxWidth: 150,
maxHeight: 150,
),
child: Container(color: Colors.red, width: 10, height: 10),
)
You might guess that the Container
has to be between 70 and 150 pixels, but you would be wrong. The ConstrainedBox
only imposes additional constraints from those it receives from its parent.
Here, the screen forces the ConstrainedBox
to be exactly the same size as the screen, so it tells its child Container
to also assume the size of the screen, thus ignoring its constraints
parameter.
Solution 6 - Dart
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.
Solution 7 - Dart
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.- But:
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 theConstrainedBox
. - And this tells me how to fix it:
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 theCenter
'sheightFactor: 1
.
So pay attention to how your children behave! If you impose external constraints, they may be greedy (or not, just like real kids ;).