138

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?

Deborah
  • 4,316
  • 8
  • 31
  • 45

8 Answers8

224

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.

Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432
  • Ohhhhhh. So I need a new question, "how to listen and measure size of an object that starts at one size and ends up another" – Deborah Feb 08 '18 at 06:17
  • 34
    You usually won't need this. Most widgets have an option to "fit the smalest size". For example, `ListView`/`GridView` have `shrinkWrap` property. `Row`/`Column` have `mainAxisSize` which can be set to `MainAxisSize.min`, ... – Rémi Rousselet Feb 08 '18 at 09:49
  • My real concern is when the object grows to max size in this case. – Deborah Feb 08 '18 at 18:23
  • 3
    Yeah but you can combine this with a ConstrainedBox. – Rémi Rousselet Feb 08 '18 at 18:47
  • 2
    When the `ConstrainBox` is put in a `Container` it stops working. It follows the height set of the wrapping `Container` – lolelo Jun 24 '21 at 09:55
42

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:

enter image description here

Output for Min Height for 10 Items:

enter image description here

Note: This will show widgets as per mentioned max-height.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Jitesh Mohite
  • 31,138
  • 12
  • 157
  • 147
  • found `...List.generate` useful for combining array of elements and static elements inside a ListView, thanks – josevoid Apr 01 '22 at 08:23
6

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
        ],
      ),
    ),
);
NUACHE
  • 243
  • 2
  • 6
AnasSafi
  • 5,353
  • 1
  • 35
  • 38
3

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

Firosh Vasudevan
  • 671
  • 10
  • 11
2

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.

Dharman
  • 30,962
  • 25
  • 85
  • 135
K Y M
  • 21
  • 2
2

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.

Rodion Mostovoi
  • 1,205
  • 12
  • 16
1

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:

  1. This widget will be as big as possible if its dimensions are constrained and widthFactor and heightFactor are null, explaining the new layout.
  2. 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 the ConstrainedBox.
  3. 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 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 ;).

qix
  • 7,228
  • 1
  • 55
  • 65
0

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
      ),
    );
Anuj Kumar
  • 21
  • 3