Edward Yuan
Edward Yuan

Reputation: 93

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

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,
            ),
          ],
        ),
      ],
    );

Upvotes: 9

Views: 24220

Answers (2)

Nitrodon
Nitrodon

Reputation: 3435

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.

Upvotes: 5

Md. Yeasin Sheikh
Md. Yeasin Sheikh

Reputation: 63559

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

Upvotes: 4

Related Questions