Bajji
Bajji

Reputation: 2383

How to center only one element in a row of 2 elements in flutter

In my layout I have two Widgets in a row, one text and the an icon.

As shown below, assume that * refers to the icon, and using "-" to represent the row:

----------------------------
           Text          *  
----------------------------

How do I make my text centered in the entire row, and the icon to the right end ?

Upvotes: 75

Views: 55613

Answers (10)

conmak
conmak

Reputation: 1470

You can always use a Stack with two children one as its own Row with an expansion to push elements to the walls and one as a Center item that has your desired center Widget. For example:

Stack(
  children: [
    Row(
      children: [
        leftWidgetHere,
        Expanded(
          child: Container(),
        ),
        rightWidgetHere,
      ],
    ),
    Center(
      child: centerWidgetHere,
    ),
  ],
);

As a useful component class:

class CenteredRow extends StatelessWidget {
  const CenteredRow({Key? key, required this.left, required this.center, required this.right}) : super(key: key);
  final Widget left;
  final Widget center;
  final Widget right;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Row(
          children: [
            left,
            Expanded(
              child: Container(),
            ),
            right,
          ],
        ),
        Center(
          child: center,
        ),
      ],
    );
  }
}

Upvotes: 1

Prawesh Panthi
Prawesh Panthi

Reputation: 348

I

I wanted this here , there are 3 items in one Row the first and second one is at top of that Row while the last Icon was at the center of that row vertically. My approach was use of IntrinsicHeight widget provider by flutter

Note : No any static height given in this solution

                IntrinsicHeight(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      Container(
                        alignment: Alignment.topLeft,
                        child: Icon(
                          Icons.offline_bolt_sharp,
                          color: AppColors.secondary,
                        ),
                      ),
                      hSpacing(times: .5),
                      Expanded(
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            RichText(
                              text: TextSpan(
                                text: '',
                                style: TextStyle(),
                                children: <TextSpan>[
                                  TextSpan(
                                      text: "Free Delivery ",
                                      style: TextStyle(
                                        fontSize: 12,
                                        color: AppColors.secondary,
                                        fontWeight: FontWeight.bold,
                                      ),
                                      recognizer: TapGestureRecognizer()
                                        ..onTap = () {}),
                                  TextSpan(
                                    text: "Tomorrow 5 Aug",
                                    style: TextStyle(
                                      fontSize: 12,
                                      color: AppColors.secondary,
                                    ),
                                    recognizer: TapGestureRecognizer()
                                      ..onTap = () {},
                                  )
                                ],
                              ),
                            ),
                            vSpacing(times: .5),
                            Text(
                              "On minimum spend of Rs ${commaNumber(3000)}",
                              maxLines: 1,
                              overflow: TextOverflow.ellipsis,
                              style: TextStyle(
                                color: AppColors.secondary,
                              ),
                            ),
                          ],
                        ),
                      ),
                      Center(
                        child: Container(
                          child: Icon(
                            Icons.arrow_forward_ios_outlined,
                            size: 20,
                            color: AppColors.secondary,
                          ),
                        ),
                      ),
                    ],
                  ),
                ))

This way you stretch all the element of Row to equal height then position by alignment property according to your need.

Upvotes: 0

Romix
Romix

Reputation: 85

For flexibility reasons I recommend to use Expanded widgets:

       Row(
            children: [
              Expanded(flex: 1, child: Container()),
              Expanded(
                flex: 8,
                child: Text('Your Text',
                  textAlign: TextAlign.center,
                ),
              ),
              Expanded(flex: 1, child: IconButton(...))
            ],
          )

Upvotes: 7

Add another icon in the start and set the opacity to zero.

Row(
   mainAxisAlignment: MainAxisAlignment.spaceBetween,
   children: [
      CloseButton(
         onPressed: () => Navigator.of(context).pop(),
      ),
      Text('text',),

      Opacity(
         opacity: 0,
         child: Icon(Icons.close),
         ),
       ],
     )

Upvotes: 0

Marcin Szałek
Marcin Szałek

Reputation: 5069

The main thing you need to notice is that if you don't want to use Stack you should provide same width-consuming widgets both on left and right.

I would do this with either Expanded and Padding

Row(
  children: <Widget>[
    Expanded(
      child: Padding(
        padding: const EdgeInsets.only(left: 32.0),
        child: Text(
          "Text",
          textAlign: TextAlign.center,
        ),
      ),
    ),
    Icon(Icons.add, size: 32.0,)
  ],
)

or with Row's mainAxisAlignment and a SizedBox

Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: <Widget>[
    const SizedBox(width: 32.0),
    Text("Text"),
    Icon(Icons.add, size: 32.0)
  ],
)

or with Expanded and a SizedBox on the left instead of the padding :). The padding or extra container on the left is so that the textAlign will truly center the text in the row taking into account the space taken up by the Icon.

Upvotes: 71

Gk Mohammad Emon
Gk Mohammad Emon

Reputation: 6938

For my case, I solved my centering problem by adjusting the flex property of the Spacer widget -

Row(children: [
        Spacer(flex: 3),//3 was for my case, It might be changed for your widgets
        Text('Center'),
        Spacer(flex: 1),//1 was also for my case, It might be changed on for your widgets
        Text("*")]); 

Upvotes: 1

Umut Arpat
Umut Arpat

Reputation: 566

This worked for me without Stack. But it is the other way around. "Text" goes to left "*" goes to center:

Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Expanded(
          child: Text("text",
              style: Theme.of(context).textTheme.caption),
        ),
        Text("*"),
        Spacer(),
      ],
    )

Upvotes: -1

CopsOnRoad
CopsOnRoad

Reputation: 267564

enter image description here

1. Using Row (not very flexible though)

Row(
  children: <Widget>[
    Expanded(child: Center(child: Text('Center'))),
    Text("#"),
  ],
)

2. Using Stack (flexible)

IntrinsicHeight(
  child: Stack(
    children: [
      Align(child: Text('Center')),
      Positioned(right: 0, child: Text('#')),
    ],
  ),
)

Upvotes: 26

Andrey Gordeev
Andrey Gordeev

Reputation: 32459

Simply use Expanded and Spacer widgets on left/right side and put your widget inside the Expanded:

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    Spacer(),
    Text('Text'),
    Expanded(
      child: Text('*'),
      ),
    ),
  ],
),

Result: Flutter center by one element in Row

Upvotes: 37

jon
jon

Reputation: 3600

I found it necessary to use a Stack to get Text to be truly centered:

Column(
  mainAxisSize: MainAxisSize.min,
  crossAxisAlignment: CrossAxisAlignment.stretch,
  children: [
    Stack(
      alignment: Alignment.center,
      children: [
        Align(
          alignment: Alignment.center,
          child: Text('Text'),
        ),
        Align(
          alignment: Alignment.centerRight,
          child: Text('*'),
        )
      ],
    ),
  ],
);

Upvotes: 19

Related Questions