0

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,
            ),
          ],
        ),
      ],
    );
Don Branson
  • 13,430
  • 10
  • 57
  • 100

2 Answers2

1

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.

Nitrodon
  • 2,434
  • 1
  • 5
  • 11
  • For this simple UI `Intrinsic` widget is not suited to use, Intrinsic is relatively expensive because it adds a speculative layout pass before the final layout phase. Avoid using it where possible. In the worst case, this widget can result in a layout that is O(N²) in the depth of the tree. I and @Yeasin already mentioned how to solve more conveniently – Jahidul Islam Dec 16 '21 at 20:44
  • I see this works fine with `Intrinsic`, @JahidulIslam do you mean there's a perfomance issue with this option? – Edward Yuan Dec 17 '21 at 00:14
  • @edward exactly, there's a performance issues – Jahidul Islam Dec 17 '21 at 04:08
0

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

Yeasin Sheikh
  • 16,243
  • 4
  • 15
  • 37
  • Not exactly what I'm looking for, If you add more text to "Monthly Membership" area, it will not go pass the 50% mark. I would like to have the left text expand all the wait til the right section – Edward Yuan Dec 17 '21 at 00:03
  • In that case, you can remove `Flexible` from second `Column` – Yeasin Sheikh Dec 17 '21 at 08:46
  • without the second `Flexible`, it would be my attempt #2 which give an error of `NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE` – Edward Yuan Dec 17 '21 at 18:19
  • Can you include parent's info, I'm not getting any error like you mentioned – Yeasin Sheikh Dec 17 '21 at 18:28
  • it's in a tab of the home screen so the full path would be: `Scaffold` -> `IndexedStack` -> `Scaffold` -> `SingleChildScrollView` -> `Column` -> `Padding` -> `Container` -> (The Row and Two columns) – Edward Yuan Dec 20 '21 at 18:42
  • try with Providing fixed height before column, – Yeasin Sheikh Dec 20 '21 at 18:45