1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/CarGuo-GSYFlutterBook

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Flutter-Font-Cool.md 23 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 10.03.2025 00:06 5767d61

Этот раздел поможет вам глубже понять «холодные» знания о шрифтах и отрисовке текста в процессе разработки с использованием Flutter. Это позволит вам лучше понять и запомнить важные моменты, связанные с отрисовкой шрифтов в Flutter.

В конце концов, таких материалов слишком мало.

Давайте начнем с простого примера отображения текста, как показано ниже:

@override
Widget build(BuildContext context) {
  return Scaffold(
    backgroundColor: Colors.black,
    body: Container(
      color: Colors.lime,
      alignment: Alignment.center,
      child: Container(
        alignment: Alignment.center,
        child: Container(
          height: 200,
          alignment: Alignment.center,
          child: new Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                child: new Text(
                  "H",
                  style: TextStyle(
                    fontSize: 100,
                  ),
                ),
              ),
              Container(
                height: 100,
                width: 100,
                color: Colors.red,
              )
            ],
          ),
        ),
      ),
    ),
  );
}

Пример

1. TextStyle

Для ответа на этот вопрос мы добавили синий фон контейнеру, содержащему текст, а также красный квадрат размером 100x100 для сравнения:```dart @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, body: Container( color: Colors.lime, alignment: Alignment.center, child: Container( alignment: Alignment.center, child: Container( height: 200, alignment: Alignment.center, child: new Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( color: Colors.blue, child: new Text( "H", style: TextStyle( fontSize: 100, ), ), ), Container( height: 100, width: 100, color: Colors.red, ) ], ), ), ), ), ); }


### ОписаниеНа следующем скриншоте можно видеть, что буква H имеет верхний и нижний отступы. Размер синего контейнера превышает 100 пикселей, но сам черный символ H находится внутри красного квадратика размером 100x100 пикселей.

![Скриншот](http://img.cdn.guoshuyu.cn/20200619_Flutter-Font-Cool/image2)

Фактически, синий контейнер представляет собой высоту строки (line height). В `TextStyle` есть параметр `height`, который влияет на высоту строки.

По умолчанию значение параметра `height` равно `null`. Когда его установите в значение `1`, высота строки становится равной ширине символов:

![Скриншот](http://img.cdn.guoshuyu.cn/20200619_Flutter-Font-Cool/image3)

Что такое параметр `height`? По документации, если параметр `height` установлен, то высота строки будет равна произведению значения `height` на значение `fontSize`.

На следующем скриншоте показана сравнительная высота строк при значении `height` как `null` и `1`.

![Скриншот](http://img.cdn.guoshuyu.cn/20200619_Flutter-Font-Cool/image4)

Кроме того, на этом скриншоте также показано положение базовой линии относительно символов. Это объясняет, почему символ H с `fontSize` 100 не заполняет полностью высоту синего контейнера.

При значении `height` равном 1, символ H располагается над базовой линией, которая предназначена для других символов, таких как g и j. На следующем скриншоте показан пример использования символа g вместе с включенным отображением базовой линии в режиме отладки Flutter.

![Скриншот](http://img.cdn.guoshuyu.cn/20200619_Flutter-Font-Cool/image5)![Screenshot](http://img.cdn.guoshuyu.cn/20200619_Flutter-Font-Cool/image5)

Пример использования символа `g` демонстрирует соответствие ожидаемому результату. Приведённый ниже код показывает, что происходит, когда мы устанавливаем высоту (`height`) равной **2**, а также добавляем контейнер с высотой **200** пикселей и фиолетовым фоном. В результате можно заметить, что синий блок полностью заполняет фиолетовый прямоугольник, так как текст с размером шрифта **100** после умножения на **x2** имеет высоту **200**.


```dart
@override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Container(
        color: Colors.lime,
        alignment: Alignment.center,
        child: Container(
          alignment: Alignment.center,
          child: Container(
            height: 200,
            color: Colors.purple,
            alignment: Alignment.center,
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Container(
                  color: Colors.blue,
                  child: new Text(
                    "Hg",
                    style: TextStyle(
                      fontSize: 100,
                      height: 2,
                    ),
                  ),
                ),
                Container(
                  height: 100,
                  width: 100,
                  color: Colors.red,
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Результат

Однако здесь текст "Hg" смещен вниз, причины этого смещения будут объяснены далее, а также будет проведен новый сравнительный анализ.Наконец, приведенная ниже диаграмма демонстрирует сравнение высоты текста при различных значениях параметра height в TextStyle, предоставляемое официальной документацией.Сравнение

Два. StrutStyle

Представим, что вернемся к ранее упомянутому значению по умолчанию для шрифтов — мере. Как же эта мера строится? Ответ заключается в использовании StrutStyle.

В приведенном ниже коде мы добавляем StrutStyle к предыдущему коду:

  • Установка forceStrutHeight на значение true, поскольку именно это свойство позволяет принудительно переопределить значение height для Text;
  • Установка height в StrutStyle на значение 1, таким образом, значение height в TextStyle, равное 2, становится бесполезным.
@override
Widget build(BuildContext context) {
  return Scaffold(
    backgroundColor: Colors.black,
    body: Container(
      color: Colors.lime,
      alignment: Alignment.center,
      child: Container(
        alignment: Alignment.center,
        child: Container(
          height: 200,
          color: Colors.purple,
          alignment: Alignment.center,
          child: new Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                color: Colors.blue,
                child: new Text(
                  "Hg",
                  style: TextStyle(
                    fontSize: 100,
                    height: 2,
                  ),
                  strutStyle: StrutStyle(
                    forceStrutHeight: true,
                    fontSize: 100,
                    height: 1
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    ),
  );
}

Приведенный ниже текст представляет собой перевод исходного текста с сохранением структуры и формата:


Результат представлен ниже на рисунке, хотя значение height в TextStyle равно 2, отображение происходит согласно значению height в StrutStyle, равному 1.

Затем, просмотрев документацию по параметру height в StrutStyle, можно заметить, что эффект этого параметра всё ещё зависит от множителя размера шрифта (fontSize). Однако здесь добавлено дополнительное пояснение к параметру fontSize: ascent + descent = fontSize. Где:

  • ascent — это часть над базовой линией;

  • descent — это часть под базовой линией;

  • а их совместное действие представлено на следующем рисунке:

В Flutter параметры ascent и descent нельзя установить отдельно через код.

Кроме того, значение параметра fontSize в StrutStyle и TextStyle имеет различное влияние: когда мы устанавливаем значение параметра fontSize в StrutStyle равным 50, а значение параметра fontSize в TextStyle остаётся равным 100, как показано на следующем рисунке, можно заметить, что размер чёрного текста не меняется, а синий участок становится размером 50.

Некоторые могут спросить, зачем тогда нужен параметр fontSize в StrutStyle?

При таких условиях, если поместить текст "Hg\nHg" в виде двухстрочного текста, можно заметить, что строки накладываются друг на друга после переноса, поэтому параметр fontSize в StrutStyle также влияет на высоту строки.

Кроме того, в StrutStyle есть ещё один параметр, который также влияет на высоту строки, это параметр leading.Как показано на следующем рисунке, добавление параметра leading позволяет полностью контролировать высоту строки в Flutter. По умолчанию значение параметра leading равно null, его эффект также является множителем размера шрифта (fontSize) и распределяется поровну сверху и снизу.

Поэтому, как показано в приведённом ниже коде, при значении параметра fontSize в StrutStyle равном 100, значении height равном 1 и значении leading равном 1, можно видеть, что размер параметра leading увеличивает синий участок до 200, тем самым высота синего участка снова совпадает с высотой фиолетового участка. При этом содержимое теперь центрировано по сравнению с предыдущими примерами с буквой "H".

---
```  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Container(
        color: Colors.lime,
        alignment: Alignment.center,
        child: Container(
          alignment: Alignment.center,
          child: Container(
            height: 200,
            color: Colors.purple,
            alignment: Alignment.center,
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Container(
                  color: Colors.blue,
                  child: new Text(
                    "Hg",
                    style: TextStyle(
                      fontSize: 100,
                      height: 2,
                    ),
                    strutStyle: StrutStyle(
                      forceStrutHeight: true,
                      fontSize: 100,
                      height: 1,
                      leading: 1
                    ),
                    
                  ),
                  
                ),
                Container(
                  height: 100,
                  width: 100,
                  color: Colors.red,
                )
              ],
            ),
          )
          
        ),
      ),
    );
  }> Поскольку `leading` распределяется равномерно между верхней и нижней частями строки, а `height` увеличивает размер строки в соответствии с её высотой и глубиной, то есть `ascent` значительно превышает `descent`, при значении `height` равном 2, текстовое поле будет смещено вниз.

![](http://img.cdn.guoshuyu.cn/20200619_Flutter-Font-Cool/image13)

### Три. backgroundColor

На данном этапе вы должны иметь базовое понимание текстовых размеров, метрик и высоты строк в Flutter. Далее рассмотрим свойство `backgroundColor` в `TextStyle`.

> Введение этого свойства позволяет сделать сравнение с предыдущими материалами и развеять некоторые заблуждения.

Как показано ниже, значение `fontSize` в `StrutStyle` равно **100**, а `height` равно **1**. По нашим ранее данным, голубое пространство должно было бы совпадать по размеру с красной квадратной областью.

Затем мы установили `backgroundColor` в `TextStyle` как прозрачно-зелёный цвет. Результат представлен на следующем рисунке, где видно, что область `backgroundColor` превышает границы `StrutStyle` и отображается как **по умолчанию метрика шрифта**.
  
---  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Container(
        color: Colors.lime,
        alignment: Alignment.center,
        child: Container(
          alignment: Alignment.center,
          child: Container(
            height: 200,
            color: Colors.purple,
            alignment: Alignment.center,
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Container(
                  color: Colors.blue,
                  child: new Text(
                    "Hg",
                    style: TextStyle(
                      fontSize: 100,
                      backgroundColor: Colors.green.withOpacity(0.7),
                    ),
                    strutStyle: StrutStyle(
                      forceStrutHeight: true,
                      fontSize: 100,
                      height: 1,
                    ),
                    
                  ),
                ),
                Container(
                  height: 100,
                  width: 100,
                  color: Colors.red,
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
```![](http://img.cdn.guoshuyu.cn/2bkj.png)

Это интересно? На самом деле это демонстрирует, что метрика шрифта всегда была по умолчанию `ascent + descent = fontSize`. Мы можем изменять высоту строки с помощью свойства `height` в `TextStyle` или `StrutStyle`, но фактический размер шрифта (`fontSize`) остаётся неизменным.

Если заменить входной текст на `"H\ng"`, как показано ниже, можно получить ещё более интересный эффект.


![](http://img.cdn.guoshuyu.cn/2bkl.png)

### Четвёртый раздел: TextBaseline

И последнее, рассмотрим свойство `TextBaseline` в `TextStyle`, которое часто вызывает недопонимание.

Свойство `TextBaseline` имеет два значения: `alphabetic` и `ideographic`. Чтобы лучше объяснить их действие, мы используем `CustomPaint`, чтобы отобразить различные позиции базовой линии, как показано ниже.

``````markdown
  @override
  виджет build(BuildContext контекст) {
    return Scaffold(
      backgroundColor: Цвета.чёрный,
      тело: Container(
        цвет: Цвета.лимо,
        выравнивание: Alignment.center,
        ребёнок: Container(
          выравнивание: Alignment.center,
          ребёнок: Container(
            высота: 200,
            ширина: 400,
            цвет: Цвета.фиолетовый,
            ребёнок: CustomPaint(
              painter: Текст2Пейnter(),
            ),
          )
        )
      )
    );
  }
```Ниже приведены текстовые описания, пояснения, комментарии и инструкции, а также сообщения об ошибках, предупреждения и пользовательские инструкции:---

На следующем рисунке показана синяя линия, которая представляет собой базовую линию (baseline). Благодаря визуальному эффекту можно легко заметить, где должны располагаться тексты при использовании различных значений базовой линии.

![Изображение](http://img.cdn.guoshuyu.cn/20200619_Flutter-Font-Cool/image16)

Однако фактическое значение базовой линии не оказывает прямого влияния на способ выравнивания текста в объекте `TextStyle`. По умолчанию Flutter использует выравнивание по алфавитной базовой линии (`TextBaseline.alphabetic`). На следующем рисунке представлено описание этого вопроса от официальных представителей проекта.

![Изображение](http://img.cdn.guoshuyu.cn/20200619_Flutter-Font-Cool/image17)

> Это объясняет необходимость использования `CustomPaint`, так как стандартный компонент `Text` не позволяет достичь желаемого эффекта.Примером может служить следующий код, где, несмотря на использование значения `ideographic` для свойства `textBaseline` в компонентах `Row` и `Text`, достигнуть желаемого выравнивания не удается.

```markdown
@Override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Container(
        color: Colors.lime,
        alignment: Alignment.center,
        child: Container(
            alignment: Alignment.center,
            child: Row(
                crossAxisAlignment: CrossAxisAlignment.baseline,
                textBaseline: TextBaselineideographic,
                mainAxisSize: MainAxisSize.max,
                children: [
                  Text(
                    '我是中文',
                    style: TextStyle(
                      fontSize: 55,
                      textBaseline: TextBaselineideographic,
                    ),
                  ),
                  Spacer(),
                  Text('123y56',
                      style: TextStyle(
                        fontSize: 55,
                        textBaseline: TextBaselineideographic,
                      )),
                ])),
      ),
    );
  }

Даже если значение mainAxisAlignment установлено как center, текст всё равно может выглядеть неравномерно выровненным.image

С тех пор как были представлены "холодные" знания о шрифтах в Flutter, неизвестно, увеличилось ли количество ваших бесполезных знаний?

image

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/CarGuo-GSYFlutterBook.git
git@api.gitlife.ru:oschina-mirror/CarGuo-GSYFlutterBook.git
oschina-mirror
CarGuo-GSYFlutterBook
CarGuo-GSYFlutterBook
master