Home > Enterprise >  How can Flutter Widgets be sized relatively to each other?
How can Flutter Widgets be sized relatively to each other?

Time:11-23

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.

CodePudding user response:

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: Scaffold(
        appBar: AppBar(title: const Text(_title)),
        body: const MyStatelessWidget(),
      ),
    );
  }
}

class MyStatelessWidget extends StatelessWidget {
  const MyStatelessWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return SizedBox.expand(
      child: FractionallySizedBox(
        widthFactor: 0.5,
        heightFactor: 0.5,
        alignment: FractionalOffset.center,
        child: DecoratedBox(
          decoration: BoxDecoration(
            border: Border.all(
              color: Colors.blue,
              width: 4,
            ),
          ),
        ),
      ),
    );
  }
}

FractionallySizedBox Widget is a widget that sizes its child to a fraction of the total available space. To make it easy to understand how FractionallySizedBox works

CodePudding user response:

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),
            ),
          ),
  • Related