Make container grow to fit width of sibling in column

Viewed 1441

I have two Container widgets in a Column, each containing a Text widget. I want the Container with the shortest text to expand to match the width of the other container containing the longer text. The container with the longer text should wrap the Text widget and its padding.

I can't get it to work without resorting to fixed widths on the containers:

return Column(
    mainAxisSize: MainAxisSize.min,
    children: [
        // This container has a shorter text than its sibling, so it should expand 
        // its width to match its sibling/parent
        Container(
            alignment: Alignment.center,
            width: 50, // I don't want this fixed width
            decoration: BoxDecoration(color: Colors.orange, borderRadius: BorderRadius.only(topLeft: Radius.circular(4), topRight: Radius.circular(4))),
            child: Padding(
                padding: const EdgeInsets.fromLTRB(8,4,8,4),
                child: Text('short'),
            )
        ),

        // This container has a longer text, so it should decide the width of the 
        // other container (and of the parent Column)
        Container(
            alignment: Alignment.center,
            width: 50, // I don't want this fixed width
            decoration: BoxDecoration(color: Colors.orange, borderRadius: BorderRadius.only(bottomLeft: Radius.circular(4), bottomRight: Radius.circular(4))),
            child: Padding(
                padding: const EdgeInsets.fromLTRB(8,4,8,4),
                child: Text('long text here'),
            )
        ),
    ]
);

I've tried a couple of ways to solve it involving Expanded and Flexible, but they all result in the "red screen of death" (or at least "annoyance").

EDIT

Just to be clear - I want the Column to just wrap its content, i.e. adjust its width to the width of the containers. In summary - everything should be as narrow as possible, except for the container with the shortest text, which should instead be as wide as its sibling (the container with the longer text).

2 Answers

I saw your Fiddle on a comment. And what you need is IntrinsicWidth.

  IntrinsicWidth(
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        // This container has a shorter text than its sibling, so it should expand
        // its width to match its sibling/parent
        Padding(
          padding: const EdgeInsets.symmetric(vertical: 1.0),
          child: Container(
            color: Colors.orange,
            child: Padding(
              padding: const EdgeInsets.fromLTRB(8, 4, 8, 4),
              child: Text(
                'short',
                textAlign: TextAlign.center,
              ),
            ),
          ),
        ),

        // This container has a longer text, so it should decide the width of the
        // other container (and of the parent Column)
        Padding(
          padding: const EdgeInsets.symmetric(vertical: 1.0),
          child: Container(
            color: Colors.orange,
            child: Padding(
              padding: const EdgeInsets.fromLTRB(8, 4, 8, 4),
              child: Text(
                'long text here',
                textAlign: TextAlign.center,
              ),
            ),
          ),
        ),
      ],
    ),
  ),

enter image description here

You can use something like this to take the entire width of the Widget (make sure to be inside a MaterialApp and a Scaffold/Material child (home):

Wrap(
   children: <Widget>[
      Container(
           color: Colors.red,
           child: IntrinsicWidth(
                child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                   Container(
                     color: Colors.black,
                     height: 200,
                     child: Align(
                       alignment: Alignment.bottomRight,
                       child: Text(
                            "Hello World",
                            style: TextStyle(color: Colors.white),
                          ),
                        ),
                      ),
                   Container(
                     color: Colors.blue,
                     height: 100,
                     child: Align(
                     alignment: Alignment.topRight,
                          child: Text(
                            "Bottom Text Longer Text",
                            style: TextStyle(color: Colors.white),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          )

The Align is not necessary, is just to showcase how the width actually works with "double.infinity" and moving a text to the bottom right or top right portion of it.

Related