skip to Main Content

I have this text:
Centered text with no icon next to it

img

I’d like to place an info icon just on the right, keeping the text centered. When I put both inside a centered and center-aligned row, the text shifts to the left like this:

no centered text with an icon next to it

I want the position of the icon to be relative to the text, so if the text changes, the icon is always close to the right:

Others are not centered text with icon next to it

But in both of this cases, the text is shifted and I need it centered.

Code:

Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
            colors: (_boolExample ? [const Color(0xffdf1b0c), const Color(0xff6b0a2b)] : [const Color(0xff89ff8e), const Color(0xff45a7f5)]),
            stops: const [0, 1],
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
          ),
        ),
        child: Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                (_boolExample ? "TEXT EXAMPLE" : "ANOTHER TEXT EXAMPLE"),
                style: const TextStyle(
                  fontSize: 36,
                  fontStyle: FontStyle.italic,
                  fontWeight: FontWeight.bold,
                  color: Color.fromARGB(255, 255, 255, 255),
                ),
              ),
              const Padding(
                padding: EdgeInsets.all(8.0),
                child: InfoPopupWidget(
                  contentTitle: 'Info Popup Details',
                  child: Icon(Icons.info),
                ),
              )
            ],
          ),
        ),
      ),

If I place a SizedBox of width 40 on the left, the text keeps centered but it seems pretty inelegant and inflexible: what if I wanted to add more items to the right?

I also tried adding a Container wrapped with Expanded on the left, and wrapping each other item in the row with expanded too:

<Widget>[
              Expanded(child: Container()),
              Expanded(
                child: Text(
                  (_boolExample ? "TEXT EXAMPLE" : "ANOTHER TEXT EXAMPLE"),
                  style: const TextStyle(
                    fontSize: 36,
                    fontStyle: FontStyle.italic,
                    fontWeight: FontWeight.bold,
                    color: Color.fromARGB(255, 255, 255, 255),
                  ),
                ),
              ),
              const Expanded(
                child: Padding(
                  padding: EdgeInsets.all(8.0),
                  child: InfoPopupWidget(
                    contentTitle: 'Info Popup Details',
                    child: Icon(Icons.info),
                  ),
                ),
              )
            ],

But it just moves everything to the left. The same with Spacer.

I tried using Align inside ot the Widget children but it just aligns them within the "cell" of the row they’re inside.

Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Align(
                alignment: Alignment.center,
                child: Text(
                  (_boolExample ? "TEXT EXAMPLE" : "ANOTHER TEXT EXAMPLE"),
                  style: const TextStyle(
                    fontSize: 36,
                    fontStyle: FontStyle.italic,
                    fontWeight: FontWeight.bold,
                    color: Color.fromARGB(255, 255, 255, 255),
                  ),
                ),
              ),
              const Padding(
                padding: EdgeInsets.all(8.0),
                child: InfoPopupWidget(
                  contentTitle: 'Info Popup Details',
                  child: Icon(Icons.info),
                ),
              )
            ],
          ),
        ),

Resulting in this:

Using Align

image

I looked for a way to make the first item centered and the row to grow to the right, but I couldn’t find it. I think that maybe a row is not the right tool for this. What widget could help me achieve this and how?

2

Answers


  1. In your case maybe you can consider using Stack

    Here is the code:

    import 'package:flutter/src/widgets/framework.dart';
    import 'package:flutter/src/widgets/placeholder.dart';
    import 'package:flutter/material.dart';
    
    class AlignTest extends StatelessWidget {
      AlignTest({super.key});
    
      bool _boolExample = true;
    
      @override
      Widget build(BuildContext context) {
        return Container(
          decoration: BoxDecoration(
            gradient: LinearGradient(
              colors: (_boolExample
                  ? [const Color(0xffdf1b0c), const Color(0xff6b0a2b)]
                  : [const Color(0xff89ff8e), const Color(0xff45a7f5)]),
              stops: const [0, 1],
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
            ),
          ),
          child: Center(
            child: Stack(
              // Allow widgets to show even if it already overflow
              // If this has not set to Clip.none, then the circle avatar in this case
              // would not able to show because it's already overflow
              clipBehavior: Clip.none,
              // set the default alignment to center, so the `Text` child could align
              // to center automatically
              alignment: Alignment.center,
              children: [
                // align to center based on the default alignment setting of this stack
                Text(
                  (_boolExample ? "TEXT EXAMPLE" : "ANOTHER TEXT EXAMPLE"),
                  style: const TextStyle(
                    fontSize: 36,
                    fontStyle: FontStyle.italic,
                    fontWeight: FontWeight.bold,
                    color: Color.fromARGB(255, 255, 255, 255),
                  ),
                ),
                // use `Positioned` to set the postion of this child relatively
                const Positioned(
                    // this means, the right edge of this child will has a dictance of
                    // -30 with the right of the stack widget (this actually makes the child
                    // overflowed by 30 unit)
                    //
                    // In your cases, you still need to know the size of this child in advance
                    // in order to set a corrent relative distance
                    right: -30,
                    child: SizedBox.square(
                      dimension: 30,
                      child: Center(
                        child: CircleAvatar(
                          backgroundColor: Colors.red,
                        ),
                      ),
                    )),
              ],
            ),
          ),
        );
      }
    }
    
    

    As its name suggests, Stack in Flutter allows you to stack widgets together and set their align behaviour and position seperately.

    In the example code above, we set the default align behaviour to center, and we set the position of the CircleAvatar using Positioned. Please check the code comment for more info and explanation

    I’m also learning flutter now and my solution may not be the best one, but hope this could helps you

    Login or Signup to reply.
  2. As pskink mentioned, you can use CompositedTransformTarget with CompositedTransformFollower for the icon.

    final _layerLink = LayerLink();
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              CompositedTransformTarget(
                link: _layerLink,
                child: ColoredBox(
                  color: Colors.cyanAccent,
                  child: Text(
                    "ANOTHER TEXT EXAMPLE",
                    style: const TextStyle(
                      fontSize: 36,
                      fontStyle: FontStyle.italic,
                      fontWeight: FontWeight.bold,
                      // color: Color.fromARGB(255, 255, 255, 255),
                    ),
                  ),
                ),
              ),
              CompositedTransformFollower(
                followerAnchor: Alignment.centerRight,
                targetAnchor: Alignment.centerRight,
                offset: Offset(8, 0),
                link: _layerLink,
                child: InfoPopupWidget(contentTitle: 'Info Popup Details', child: Text('x')),
              ),
            ],
          ),
        );
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search