За яких обставин властивість textAlign працює у Flutter?


84

У наведеному нижче коді textAlignвластивість не працює. Якщо ви видалите DefaultTextStyleобгортку, яка знаходиться на кілька рівнів вище, textAlignпочинає працювати.

Чому і як забезпечити, щоб вона завжди працювала?

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,)
      ],))
    );
  }
}

Обидва підходи, запропоновані Ремі, мабуть, не працюють "у дикій природі". Ось приклад, який я вклав як всередину рядків, так і стовпців. Перший підхід не виконує вирівнювання, а другий підхід змушує програму просто розбиватися:

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)),
                ],)),
              ],)*/]
    )));
  }
}

Що я отримую від коду

введіть тут опис зображення

тобто текст центрується, ігноруючи вирівнювання Alignелемента.


Чому ви використовуєте DefaultTextStyle як контейнер для 2 дочірніх текстів?
diegoveloper

2
Чому б я не?
Dims

Відповіді:


172

DefaultTextStyleне пов’язано з проблемою. Видалення його просто використовує стиль за замовчуванням, який набагато більший за той, який ви використовували, тому він приховує проблему.


textAlignвирівнює текст у зайнятому просторі, Textколи цей зайнятий простір перевищує фактичний вміст.

Справа в тому, що всередині Column, ваш Textзаймає мінімум простору. Тоді це те, Columnщо вирівнює своїх дітей, використовуючи те, за crossAxisAlignmentзамовчуванням center.

Найпростіший спосіб вловити таку поведінку - це обгортання текстів таким чином:

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

За допомогою коду, який ви надали, відображається наступне:

введіть тут опис зображення

Проблема раптом стає очевидною: Textне приймайте всю Columnширину.


Тепер у вас є кілька рішень.

Ви можете обернути Textв Alignдля мімічного textAlignповедінки

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

Що надасть наступне:

введіть тут опис зображення

або ви можете змусити вас Textзаповнити Columnширину.

Або вказавши crossAxisAlignment: CrossAxisAlignment.stretchна Column, або використовуючи SizedBoxз нескінченним width.

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

що робить наступне:

введіть тут опис зображення

У цьому прикладі саме TextAlignтекст розміщений ліворуч.


1
Але чи не згодні ви з тим, що все, що ви описали, - це трюки та обхідні шляхи, що означає поганий дизайн бібліотеки?
Dims

3
Це точно не обман / обхідний шлях. Це офіційне рішення. Flutter використовує макет на основі обмежень із композицією в його основі. Це функціональне програмування Layout. Це абсолютно приголомшливо
Ремі Русселет

1
У першому випадку ви двічі вказали "ліворуч", у другому - нескінченну ширину. Це точно хитрощі, незважаючи на те, що вони є офіційними та функціональними.
Dims

1
Ах, вибачте, я забув видалити textAlignна Alignприкладі. Виправлено. А «нескінченна ширина» у флаттері просто говорить «я хочу якомога більше місця».
Rémi Rousselet

Гаразд, тоді перший спосіб кращий, хоча він все ще не працює для мене поза цим простим прикладом ...
Dims

56

Вкажіть crossAxisAlignment: CrossAxisAlignment.startу колонці


1
Це не повинно бути?: CrossAxisAlignment: CrossAxisAlignment.start
кеплерівської

Це не спрацювало б, оскільки він має один текстовий віджет, вирівняний ліворуч, а другий праворуч ...
Хасен

@TSR це працює лише в тому випадку, якщо в стовпці вже є один елемент, який займає всю ширину (наприклад a Row буде працювати, абоAlign( ... centerLeft)
TSR

16

textAlignвластивість працює лише тоді, коли залишається більше місця для Textвмісту. Нижче наведено 2 приклади, які показують, коли textAlign впливає, а коли ні.


Без впливу

Наприклад, у цьому прикладі це не матиме жодного впливу, оскільки немає додаткового місця для вмісту Text.

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

введіть тут опис зображення


Має вплив

Якщо ви загортаєте його в Containerі надаєте додаткове width, щоб у ньому було більше додаткового місця.

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

введіть тут опис зображення


Ви також можете протестувати це за допомогоюVery \n Good Morning
CopsOnRoad

10

У віджеті Colum Вирівнювання тексту буде центровано автоматично, тому використовуйте crossAxisAlignment: CrossAxisAlignment.startдля вирівнювання старт.

Column( 
    crossAxisAlignment: CrossAxisAlignment.start, 
    children: <Widget>[ 
    Text(""),
    Text(""),
    ]);


1

Для максимальної гнучкості я зазвичай віддаю перевагу роботі з SizedBox наступним чином:

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

Раніше я мав проблеми з вирівнюванням тексту, коли використовував вирівнювання, тоді як Sizebox завжди виконує свою роботу.


0

Ви можете використовувати контейнер, це допоможе вам встановити вирівнювання.

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,
          ),
        ),
      ),
    ],
  ),
);
}

-1
GestureDetector(
          onTap: () {},
          child: Container(
            padding: EdgeInsets.all(5),
            color: buttonContainerColor,
            margin: EdgeInsets.only(top: 10.0),
            width: double.infinity,
            height: bottomContainerHeight,
            alignment: Alignment.center,
            child: Text(
              "CALCULATE",
              style: TextStyle(fontSize: 25.0, color: Colors.white),
            ),
          ),
        )
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.