Home > Software engineering >  Flutter - How to put two Columns inside a Row, one Column expanded, the other fit its content text?
Flutter - How to put two Columns inside a Row, one Column expanded, the other fit its content text?

Time:12-17

Is there a way to achieve this layout with flutter? With one Column expanded, and the other Column shrink to fit the texts inside, within a Row.

I'm from a web background, I know I can do it with Flex-grow and Flex-shring along with whitespace:nowrap.

I would like to achieve this layout

I would like to achieve this layout

But in flutter I tried:

  1. This will give me two equal width columns:
Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Expanded(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisSize: MainAxisSize.min,
            children: [Text('Monthly Membership'), Text('Subscription')],
          ),
        ),
        Flexible(
          fit: FlexFit.tight,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(
                ' 100',
                maxLines: 1,
                softWrap: false,
                overflow: TextOverflow.fade,
              ),
              Text(
                '18 Sept 2021',
                maxLines: 1,
                softWrap: false,
                overflow: TextOverflow.fade,
              ),
            ],
          ),
        ),
      ],
    );
  1. This will give an error.

RenderBox was not laid out: RenderFlex#3024f relayoutBoundary=up1 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE

Row(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Expanded(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisSize: MainAxisSize.min,
            children: [Text('Monthly Membership'), Text('Subscription')],
          ),
        ),
        Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(
              ' 100',
              maxLines: 1,
              softWrap: false,
              overflow: TextOverflow.fade,
            ),
            Text(
              '18 Sept 2021',
              maxLines: 1,
              softWrap: false,
              overflow: TextOverflow.fade,
            ),
          ],
        ),
      ],
    );

CodePudding user response:

Your code-snippet just works fine, just missing alignment.
About your desire UI, you just need to set alignment.

 Card(
            color: Colors.grey,
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisSize: MainAxisSize.min,
                      children: const [
                        Text('Monthly Membership'),
                        SizedBox(height: 10),
                        Text('Subscription'),
                      ],
                    ),
                  ),
                ),
                Flexible(
                  fit: FlexFit.tight,
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      crossAxisAlignment: CrossAxisAlignment.end,
                      mainAxisSize: MainAxisSize.min,
                      children: const [
                        Text(
                          ' 100',
                          maxLines: 1,
                          softWrap: false,
                          overflow: TextOverflow.fade,
                        ),
                        SizedBox(height: 10),
                        Text(
                          '18 Sept 2021',
                          maxLines: 1,
                          softWrap: false,
                          overflow: TextOverflow.fade,
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
    

enter image description here

CodePudding user response:

Your second attempt fails because CrossAxisAlignment.stretch takes all of the horizontal space available, but a Row gives its children an unbounded width constraint. This forces the column to have infinite width, which is impossible. There are two options to fix this:

  1. Use a different crossAxisAlignment

This will make each child of the Column take as much space as it's going to take. Based on your image, you probably want CrossAxisAlignment.center, which will center the column's children. The column will take its width from the larger of the two Text widgets.

        Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          // ...
  1. Use IntrinsicWidth

IntrinsicWidth will measure the width that the Column wants to be, then give it that width. This will give the Column a tight width constraint in a second layout pass, which will make CrossAxisAlignment.stretch work as intended.

        IntrinsicWidth(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.stretch,
            // ...

Both options will layout the second column with unbounded width, which means that if you have very long text, it might make the first column very small. If you want to bound the width of the column, you can add a ConstrainedBox to either solution.

CodePudding user response:

BoxConstraints forces an infinite width.

hasSize "RenderBox was not laid out: RenderFlex#c927e relayoutBoundary=up1 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE" - that means the second column doesn't get any width, that's you need to set fixed height or Expand your widget.

Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Expanded(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisSize: MainAxisSize.min,
                children: [Text('Monthly Membership',), Text('Subscription')],
              ),
            ),
            Expanded(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                  Text(
                    ' 100',
                    maxLines: 1,
                    softWrap: false,
                    overflow: TextOverflow.fade,
                  ),
                  Text(
                    '18 Sept 2021',
                    maxLines: 1,
                    softWrap: false,
                    overflow: TextOverflow.fade,
                  ),
                ],
              ),
            ),
          ],
        )

And for more about flexible and Expand read this article

  • Related