98

In the code below, textAlign property doesn't work. If you remove DefaultTextStyle wrapper which is several levels above, textAlign starts to work.

Why and how to ensure it is always working?

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new DefaultTextStyle(style: new TextStyle(fontSize: 10.0), child: new Column(children: <Widget>[
        new Text("Should be left", textAlign: TextAlign.left,),
        new Text("Should be right", textAlign: TextAlign.right,)
      ],))
    );
  }
}

Both approaches, suggested by Remi apparently don't work "in the wild". Here is an example I nested both inside rows and columns. First approach doesn't do align and second approach makes application just crash:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new Directionality(textDirection: TextDirection.ltr, child: new DefaultTextStyle(
            style: new TextStyle(fontSize: 10.0, color: Colors.white),
            child: new Column(children: <Widget>[
              new Row(children: <Widget>[
                new Container(color: Colors.grey, child: new Column(children: <Widget>[
                  new Align(alignment: Alignment.centerLeft, child: new Text("left")),
                  new Align(alignment: Alignment.centerRight, child: new Text("right")),
                ],)),
                new Container(color: Colors.grey, child: new Column(children: <Widget>[
                  new Align(alignment: Alignment.centerLeft, child: new Text("left")),
                  new Align(alignment: Alignment.centerRight, child: new Text("right")),
                ],)),
              ],),
              /*new Row(children: <Widget>[
                new Container(color: Colors.grey, child: new Column(children: <Widget>[
                  new SizedBox(width: double.infinity, child: new Text("left", textAlign: TextAlign.left,)),
                  new SizedBox(width: double.infinity, child: new Text("right", textAlign: TextAlign.right)),
                ],)),
                new Container(color: Colors.grey, child: new Column(children: <Widget>[
                  new SizedBox(width: double.infinity, child: new Text("left", textAlign: TextAlign.left)),
                  new SizedBox(width: double.infinity, child: new Text("right", textAlign: TextAlign.right)),
                ],)),
              ],)*/]
    )));
  }
}

What I get from code is

enter image description here

i.e. text is centered, ignoring alignment of Align element.

Dims
  • 37,353
  • 77
  • 251
  • 478

8 Answers8

208

DefaultTextStyle is unrelated to the problem. Removing it simply uses the default style, which is far bigger than the one you used so it hides the problem.


textAlign aligns the text in the space occupied by Text when that occupied space is bigger than the actual content.

The thing is, inside a Column, your Text takes the bare minimum space. It is then the Column that aligns its children using crossAxisAlignment which defaults to center.

An easy way to catch such behavior is by wrapping your texts like this :

Container(
   color: Colors.red,
   child: Text(...)
)

Which using the code you provided, render the following :

enter image description here

The problem suddenly becomes obvious: Text don't take the whole Column width.


You now have a few solutions.

You can wrap your Text into an Align to mimic textAlign behavior

Column(
  children: <Widget>[
    Align(
      alignment: Alignment.centerLeft,
      child: Container(
        color: Colors.red,
        child: Text(
          "Should be left",
        ),
      ),
    ),
  ],
)

Which will render the following :

enter image description here

or you can force your Text to fill the Column width.

Either by specifying crossAxisAlignment: CrossAxisAlignment.stretch on Column, or by using SizedBox with an infinite width.

Column(
  children: <Widget>[
    SizedBox(
      width: double.infinity,
      child: Container(
        color: Colors.red,
        child: Text(
          "Should be left",
          textAlign: TextAlign.left,
        ),
      ),
    ),
  ],
),

which renders the following:

enter image description here

In that example, it is TextAlign that placed the text to the left.

Rémi Rousselet
  • 165,280
  • 57
  • 395
  • 345
  • 1
    But don't you agree, that all you described are tricks and workarounds, meaning bad design of the library? – Dims Aug 01 '18 at 19:56
  • 3
    This is definitely not a trick/workaround. This is the official solution. Flutter uses a constraint-based layout with composition at its core. It is the functional programming of Layout. It is absolutely awesome – Rémi Rousselet Aug 01 '18 at 20:08
  • 2
    In first case you specified "left" twice, in second case you specified infinite width. These are definitely tricks despite they are official and functional. – Dims Aug 01 '18 at 20:11
  • 1
    Ah sorry I forgot to remove the `textAlign` on the `Align` example. Fixed. And the "infinite width" in flutter simply says "I want as much space as possible". – Rémi Rousselet Aug 01 '18 at 20:15
  • Okay, then the first way is better, although it still doesn't work for me outside this simple example... – Dims Aug 01 '18 at 20:25
  • P.S. Also strictly speaking, it is not functional, when outside affects inside... – Dims Aug 01 '18 at 20:29
  • But it is functional here. We didn't change the content, we changed the props passed to the "function". In flutter these props are constraints. – Rémi Rousselet Aug 01 '18 at 20:31
  • It's going to be hard to help you without seing your problem though. Maybe make another question with a more precise example – Rémi Rousselet Aug 01 '18 at 20:32
  • You most likely didn't understand something. I can't help without seeing your code though – Rémi Rousselet Aug 01 '18 at 20:43
  • See my update please. I nested both you approaches into rows and cols. In first row I put your first approach and in second one I put second. First doesn't work, second crashes the renderer (because of infinite width, uncomment to see). – Dims Aug 01 '18 at 20:59
  • Duh, that's a radically different layout. Both your examples need a different solution. Considering this, do you mind creating a new question? – Rémi Rousselet Aug 01 '18 at 21:03
  • But in short, the solution is to wrap both `Container` into an `Expanded` – Rémi Rousselet Aug 01 '18 at 21:08
  • Why is it different? I missed something? I can't create question on each my layout, I want general approach working in predictable way. – Dims Aug 01 '18 at 21:19
  • The `Align` thing worked here too. The problem here is that it's your columns which don't fill the row. To expand widgets on the main axis of `Column`/`Row` you need to wrap them into `Expanded`. – Rémi Rousselet Aug 01 '18 at 21:21
  • I wrapped both aligns into container, which is grey, it is evident, that it is rectangular and there is space to align. Nevertheless, alignment doesn't happen – Dims Aug 02 '18 at 07:33
  • Use expanded, not align – Rémi Rousselet Aug 02 '18 at 07:35
  • Your second problem is not related to alignment. You simply want one child of a row/column to expand in the row/column main axis. – Rémi Rousselet Aug 02 '18 at 13:04
  • I don't understand why. See my screenshot. Text is obviously centered, i.e. `Align` is just ignored without any reason. Space between cells is unrelated problem. – Dims Aug 02 '18 at 16:11
  • This doesn't even answer the question. The question is when does textalign work, and your answer is to use something else...not to mention that means every text element needs both and align AND a container around it....it's a ridiculous workaround. – Hasen Jul 25 '19 at 11:39
  • The answer is it never works and it's a bug. It shouldn't be aligning itself to ITSELF..it should be aligning itself to the width of the column it's in... – Hasen Jul 25 '19 at 11:41
  • The `Container` has nothing to do with the solutions. It's just there for debug purpose. Similarly, the second example shows how to use `textAlign` instead of using `Align` wiget. – Rémi Rousselet Jul 25 '19 at 11:47
61

Specify crossAxisAlignment: CrossAxisAlignment.start in your column

Lukas Schneider
  • 618
  • 8
  • 19
The real me
  • 619
  • 7
  • 8
  • 1
    Shouldn't that be?: crossAxisAlignment: CrossAxisAlignment.start – Keplerian Apr 10 '19 at 23:27
  • That wouldn't work since he has one text widget aligned left and one to the right... – Hasen Jul 25 '19 at 11:36
  • @TSR this only work if the column already has one element that occupies the entire width (for example a `Row` would work, or `Align( ... centerLeft)` – TSR Mar 01 '20 at 20:40
17

textAlign property only works when there is a more space left for the Text's content. Below are 2 examples which shows when textAlign has impact and when not.


No impact

For instance, in this example, it won't have any impact because there is no extra space for the content of the Text.

Text(
  "Hello",
  textAlign: TextAlign.end, // no impact
),

enter image description here


Has impact

If you wrap it in a Container and provide extra width such that it has more extra space.

Container(
  width: 200,
  color: Colors.orange,
  child: Text(
    "Hello",
    textAlign: TextAlign.end, // has impact
  ),
)

enter image description here

CopsOnRoad
  • 109,635
  • 30
  • 367
  • 257
12

In Colum widget Text alignment will be centred automatically, so use crossAxisAlignment: CrossAxisAlignment.start to align start.

Column( 
    crossAxisAlignment: CrossAxisAlignment.start, 
    children: <Widget>[ 
    Text(""),
    Text(""),
    ]);
Navin Kumar
  • 1,940
  • 2
  • 12
  • 32
5

Set alignment: Alignment.centerRight in Container:

Container(
    alignment: Alignment.centerRight,
    child:Text(
       "Hello",
    ),
)
Lay Leangsros
  • 7,922
  • 6
  • 30
  • 37
1

For maximum flexibility, I usually prefer working with SizedBox like this:

Row(
                                children: <Widget>[
                                  SizedBox(
                                      width: 235,
                                      child: Text('Hey, ')),
                                  SizedBox(
                                      width: 110,
                                      child: Text('how are'),
                                  SizedBox(
                                      width: 10,
                                      child: Text('you?'))
                                ],
                              )

I've experienced problems with text alignment when using alignment in the past, whereas sizedbox always does the work.

Tommy95
  • 11
  • 4
1

You can use the container, It will help you to set the alignment.

Widget _buildListWidget({Map reminder}) {
return Container(
  color: Colors.amber,
  alignment: Alignment.centerLeft,
  padding: EdgeInsets.all(20),
  height: 80,
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.center,
    children: <Widget>[
      Container(
        alignment: Alignment.centerLeft,
        child: Text(
          reminder['title'],
          textAlign: TextAlign.left,
          style: TextStyle(
            fontSize: 16,
            color: Colors.black,
            backgroundColor: Colors.blue,
            fontWeight: FontWeight.normal,
          ),
        ),
      ),
      Container(
        alignment: Alignment.centerRight,
        child: Text(
          reminder['Date'],
          textAlign: TextAlign.right,
          style: TextStyle(
            fontSize: 12,
            color: Colors.grey,
            backgroundColor: Colors.blue,
            fontWeight: FontWeight.normal,
          ),
        ),
      ),
    ],
  ),
);
}
Anit Kumar
  • 7,239
  • 1
  • 16
  • 25
0

You can align text anywhere in the scaffold or container except center:-

Its works for me anywhere in my application:-

new Text(

                "Nextperience",

//i have setted in center.

                textAlign: TextAlign.center,

//when i want it left.

 //textAlign: TextAlign.left,

//when i want it right.

 //textAlign: TextAlign.right,

                style: TextStyle(

                    fontSize: 16,

                    color: Colors.blue[900],

                    fontWeight: FontWeight.w500),

              ), 
Suraj Rao
  • 28,186
  • 10
  • 88
  • 94
M A Hafeez
  • 51
  • 1
  • 3