За яких обставин властивість 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.