Search code examples
flutterdartflutter-layout

How can Flutter Widgets be sized relatively to each other?


I'm a couple days into learning Flutter, and I keep running into a situation where I want to scale a collection of widgets (aka a Row, Column, Stack, etc) down when the screen shrinks, akin to what Flexible() does. Except unlike Flexible(), I want all children to scale down when the container shrinks, not just the largest elements. Consider this example of a Column() (green) with two children: a red child matching its parent's width, and a blue child with half the parent's width:

enter image description here

In the above case, if the green Column() were to be constrained such that its width was less, you would end up with something like such:

enter image description here

However, what I am wanting is for each of the child elements (red/blue) to scale their width/height relative to each other, like this:

enter image description here

How can I accomplish this?

In the specific Column() case I illustrated above, my workaround was to add a Row() containing the blue widget as well as a Padding(), both with equal flex properties, so that when the Column() shrunk the blue element scaled correctly. I feel like this is a hack though, and wouldn't be as feasible if I had many elements with differing widths/alignments. It would be a nightmare to add one Padding() for left/right aligned elements and two for centered ones. Is there a better way?

I'd also like to know of a similar solution for using Stack()s. Using the Positional() element seems to set the width/height in a way that the Stack() crops any overflow. It'd be nice to have a Stack() that scales all its children the same, just like if it was a single image, and similar to my Column() example above.


Solution

  • You can have a look at FractionallySizedBox class, you can specify the widthFactor and heightFactor e.g. 0.5 so that it is always half the size of the parent container.

    Example:

      Flexible(
                child: FractionallySizedBox(
                  widthFactor: 0.5,
                  heightFactor: 0.5,
                  alignment: FractionalOffset.centerLeft,
                  child: Container(
                      color: Colors.blue),
                ),
              ),