Align text baseline with text inside a column, using Flutter
Asked Answered
D

3

8

I'm having trouble aligning widgets. I have seen questions on here asking about similar things, however, none of them seem to work for my specific task. I'm trying to create a widget containing an icon and two text widgets. The icon is supposed to be centered over the first text widget, and the other text widget is supposed to be aligned with the baseline of the first.

The way I have gone about doing this is to place the icon and the first text widget in a column, and then place that column in a row together with the second text widget. I'm using crossAxisAlignment: CrossAxisAlignment.baseline and textBaseline: TextBaseline.ideographic in the row widget but for some reason the second text aligns with the icon. It looks like this:

enter image description here

If I instead use crossAxisAlignment: CrossAxisAlignment.end the text widgets do not align properly:

enter image description here

I have tried to put the text widgets in a row and place them in a column together with the icon, but then the icon is no longer centered over the first text widget:

enter image description here

Here's the code used for the first image, the other images are just rearrangements of the same code.

return Row(
  crossAxisAlignment: CrossAxisAlignment.baseline,
  textBaseline: TextBaseline.ideographic,
  children: [
    Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Icon(
          widget.icon,
          color: color_text_highlight,
          size: 20,
        ),
        Text(
          widget.data,
          style: TextStyle(
            fontSize: 28,
            fontFamily: 'Quicksand',
            color: color_text_highlight,
          ),
        ),
      ],
    ),

    SizedBox(width: 5),

    Text(
        widget.label,
        style: TextStyle(
          fontSize: 12,
          fontFamily: 'Roboto',
          color: color_text_dark,
        )
    ),
  ],
);

Any help is appreciated!

Dripping answered 14/6, 2020 at 11:39 Comment(0)
C
23

Column defines its own baseline as a baseline of its first child*. That's why the label at right gets aligned to the bottom of icon:

example screenshot

A simple fix is to make "17:59" the first child of the Column (the icon will go below now) and then use VerticalDirection.up to swap them back:

example screenshot

Row(
  mainAxisSize: MainAxisSize.min,
  crossAxisAlignment: CrossAxisAlignment.baseline,
  textBaseline: TextBaseline.alphabetic,
  children: [
    Column(
      mainAxisSize: MainAxisSize.min,
      verticalDirection: VerticalDirection.up, // <-- reverse direction
      children: [
        Text('17:59', style: TextStyle(fontSize: 32)), // <-- first child
        Icon(Icons.timer),
      ],
    ),
    Text('mm:ss'),
  ],
)

* actually, of first child that has a baseline itself, anyway Icon does have it

Christmas answered 1/8, 2020 at 23:55 Comment(0)
Y
3

There may be a solution like this, but the solution may cause problems because it depends on the font size. You will need to change the padding value accordingly.

   Column(
        children: [
          Row(
            crossAxisAlignment: CrossAxisAlignment.end,
            children: [
              Column(
                children: [
                  Icon(
                    Icons.timer,
                    color: Colors.lightGreen,
                    size: 20,
                  ),
                  Text(
                    "17:59",
                    style: TextStyle(
                      fontSize: 28,
                      fontFamily: 'Quicksand',
                      color: Colors.lightGreen,
                    ),
                  ),
                ],
              ),
              SizedBox(width: 5),
              Padding(
                padding: EdgeInsets.only(bottom: 4),
                child: Text("mm:ss",
                    style: TextStyle(
                      fontSize: 12,
                      fontFamily: 'Roboto',
                      color: Colors.white70,
                    )),
              ),
            ],
          ),
        ],
      )

Google Nexus 9 Tablet Google Nexus 9 Tablet

Google Pixel 3a XL Google Pixel 3a XL

Google Pixel 2 Google Pixel 2

Yocum answered 14/6, 2020 at 12:16 Comment(2)
Thanks for the answer! Do you know if this will scale well with different screen sizes?Dripping
Since flutter font sizes are in dp, it will be the same in every screen size. I attach screenshots to answerYocum
F
1

Row allows for a crossAxisAlignment of baseline, set the text baseline too or it will throw an error

        Row(
          crossAxisAlignment: CrossAxisAlignment.baseline,
          textBaseline: TextBaseline.alphabetic,
Fanning answered 19/10, 2022 at 10:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.