133

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.

Ravindra S. Patil
  • 11,757
  • 3
  • 13
  • 40
ludell
  • 1,333
  • 2
  • 9
  • 9

8 Answers8

186

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(...)
      ],
    ),
  )
)
Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432
128

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

RajaKumar
  • 1,509
  • 1
  • 10
  • 11
41

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.

WSBT
  • 33,033
  • 18
  • 128
  • 133
  • Internal flutter changes to that logic have a bigger chance of breaking your code if you just mimic what Flutter does under the hood. Better practice is to use `constraints: BoxConstraints.expand()`. –  Mar 16 '21 at 13:18
  • @andreyrk Thanks! While your statement is generally correct, there is however no risk here. Flutter engine uses constraint solver to force bigger values into what's allowed by its parent, and that's one of the most fundamental principles behind how Flutter layout works. `BoxConstraints.expand()` merely exploits the same fact. I've updated my answer in an attempt to explain it better. If you're unfamiliar with these topics, you might want to look into how Flutter engine performs layout under the hood. – WSBT Mar 16 '21 at 21:25
  • 1
    This is the way to go. Simple to read and understand, without adding another widget to the tree (at least in the code you see). – Dave Jun 29 '21 at 15:16
  • 1
    upvote for the explanation, ty – evals Sep 29 '22 at 18:19
35

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

Omar Masri
  • 367
  • 3
  • 2
  • 4
    Hey, I've been trying this approach doesn't seem to work. Can you help ? The widget just vanishes if I don't set a height of the container inside it. – temporarya Apr 06 '20 at 18:20
  • 14
    no need to set `flex: 1` since it's the value by default – Kirill Karmazin Jul 15 '20 at 09:44
  • This worked for me when I was trying to expand a container inside a card widget with a column. I have a material button inside a container at the end of the card that I wanted to center in the remaining portion of the card. Didn't give the infinity problem. Thanks! – M A F Jan 22 '21 at 21:36
  • this doesn't work for me. The following assertion was thrown while applying parent data.: Incorrect use of ParentDataWidget. The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of type FlexParentData to a RenderObject, which has been set up to accept ParentData of incompatible type ParentData. Usually, this means that the Expanded widget has the wrong ancestor RenderObjectWidget. Typically, Expanded widgets are placed directly inside Flex widgets. The offending Expanded is currently placed inside a IntrinsicHeight widget. – david weng Apr 23 '21 at 07:50
6

There are many answers which suggest using two things

  1. constraints: BoxConstraints.expand(),
  2. 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

  1. App Bar
  2. Top Bar Space(Exist on the above App Bar)
  3. 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:

enter image description here

Hardik Vaghani
  • 2,163
  • 24
  • 46
Jitesh Mohite
  • 31,138
  • 12
  • 157
  • 147
3

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

2

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

bulwatam
  • 21
  • 2
1

This work works for me

height: MediaQuery.of(context).size.height,
ncutixavier
  • 455
  • 5
  • 4