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

OSCHINA-MIRROR/CarGuo-GSYFlutterBook

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

Небольшие хитрости Flutter 3.16: советы по переходу на Material 3 по умолчанию

Если говорить о самых проблематичных аспектах обновления до Flutter 3.16, то это точно Material 3 по умолчанию (M3).

Не потому что в M3 много багов или использование его стало сложнее с версией 3.16, но поскольку хотя с версии 3.16 значение параметра useMaterial3 в MaterialApp по умолчанию установлено как true, вы всё равно можете использовать useMaterial3: false, чтобы отключить этот режим.

Почему же это считается проблемой? Потому что в будущем компоненты Material 2 будут отключены и удалены, поэтому переход на M3 — это предупреждение, которое можно игнорировать, используя useMaterial3: false. Однако эта техническая задолженность может стать серьёзной проблемой в будущем.

Будете ли вы продолжать работать без обновлений?

Почему это так важно? Потому что адаптация к M3 требует значительных усилий, особенно если учесть все детали. M3 представляет собой новую цветовую схему, которая полностью отличается от схемы M2:

  • Цветовая схема автоматически определяет цвета для различных компонентов
  • M2 и M3 совершенно несовместимы, что приведёт к изменениям внешнего вида всех компонентов

Пример

Как показано на изображении выше, видим следующие изменения:- Изменение цветовой схемы AppBar

  • Преобразование FloatingActionButton из круглого в прямоугольное с изменением цвета
  • Изменение стиля кнопок ElevatedButton и TextButton
  • ...Казалось бы, ничего особенного, но сколько мест используют FloatingActionButton? Будете ли вы корректировать каждый AppBar вручную? Есть ли возможность глобальной конфигурации для ElevatedButton и TextButton? В этой статье мы предоставляем рекомендации по адаптации, чтобы помочь вам преодолеть эти трудности.

Основная причина проблемы заключается в том, что мало кто из китайских продуктов использует Material Design. Переход от M2 к M3 для разработчиков является чистым негативным изменением.

Начнем

Сначала отметим, что официальная рекомендация по использованию цветовых схем для Material 3 — это метод ColorScheme.fromSeed(), который позволяет создать цветовую схему. Конечно, вы также можете использовать ColorScheme.fromImageProvider для создания цветовой схемы на основе изображения, однако большинство людей скорее всего этого не сделает. Также есть метод ColorScheme.fromSwatch, но он менее гибкий по сравнению с fromSeed, поэтому последний вариант является лучшим выбором.

Поскольку по умолчанию цветовая схема M3 переходит с синего на фиолетовый, если вы используете стандартную цветовую схему, вам потребуется её настроить. Цель данной статьи — восстановление внешнего вида приложения M2 при работе с M3, поскольку это действительно больше, чем просто изменение цвета.Если ваш прежний ThemeData выглядел как приведённый ниже код, то после выполнения вы заметите, что вместо обычного списка с эффектом M2, который должен был быть, теперь есть некий "неописуемый" эффект M3. Видно, что в данном случае primarySwatch не играет никакой роли.

ThemeData(
  primarySwatch: Colors.blue,
  ////
)
M2 M3

Сначала нам нужно добавить colorScheme. Однако, после добавления этого свойства ничего не изменится, так как компонент всё ещё находится под влиянием цветовой схемы M3. Поэтому следующим шагом будет глобальное восстановление AppBar.

ThemeData(
  primarySwatch: Colors.blue,
  colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
),

Делай это.

AppBar

Как показано ниже, мы сначала добавляем AppBarTheme, чтобы фон AppBar снова стал синим. Но при этом текст и значки AppBar остаются чёрными.

ThemeData(
  primarySwatch: Colors.blue,
  colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),

  appBarTheme: AppBarTheme(
    backgroundColor: Colors.blue,
  ),
),

| | | | ------------------------------------------------------ | ------------------------------------------------------ |Чтобы вернуть значки и текст к белому цвету, характерному для M2, можно настроить iconTheme и titleTextStyle внутри AppBarTheme. После настройки видно, что UI компонента AppBar полностью восстановлен до состояния M2. Возможно, вас интересует вопрос, почему конфигурация включает значения size: 24.0 и Typography.dense2021.titleLarge?```dart AppBarTheme( iconTheme: IconThemeData( color: Colors.white, size: 24.0, ), backgroundColor: Colors.blue, titleTextStyle: Typography.dense2014.titleLarge, )


![](http://img.cdn.guoshuyu.cn/20231123_M3/image7.png) Это суть всей статьи: **восстановление M3 UI до состояния M2 при отсутствии удаления контрола M2**.

Например, в исходном коде версии 3.16 часто встречается конструкция `theme.useMaterial3 ?`, а внутри компонента `AppBar`:

- В `_AppBarDefaultsM3` цвет иконки задается через поле `onSurface`, размер — 24 пикселя;
- В `_AppBarDefaultsM2` иконка использует дефолтные настройки темы, то есть размер — 24 пикселя, цвет — белый.

![Иллюстрация](http://img.cdn.guoshuyu.cn/20231123_M3/image8.png)

| M2                                                                                          | M3                                                                                         |
| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| ![Иллюстрация](http://img.cdn.guoshuyu.cn/20231123_M3/image9.png)![Иллюстрация](http://img.cdn.guoshuyu.cn/20231123_M3/image10.png) | ![Иллюстрация](http://img.cdn.guoshuyu.cn/20231123_M3/image11.png)                     |

Поэтому мы можем использовать конфигурацию `IconThemeData` со значениями `color: Colors.white, size: 24.0`, чтобы восстановить состояние M2.

> Конечно, вы можете также изменять цвет через поле `onSurface` в `ColorScheme`, но это затронет слишком много мест, поэтому рекомендую использовать конфигурацию `IconThemeData` в `AppBarTheme`.Кроме того, можно заметить наличие ещё одного поля `Typography.dense2014.titleLarge`. Откуда взялось это поле? Вернёмся к `_AppBarDefaultsM3`: в M3 AppBar используется поле `textTheme.titleLarge` из `ThemeData`, а дефолтные шрифтные настройки берутся из объекта `Typography`.![Иллюстрация](http://img.cdn.guoshuyu.cn/20231123_M3/image12.png)

![Иллюстрация](http://img.cdn.guoshuyu.cn/20231123_M3/image13.png)

Объект `Typography` содержит множество дефолтных настроек шрифтов, например, `Typography.dense2014` имеет следующие настройки. Из вышеупомянутого кода видно, что **по умолчанию M2 использует `Typography.material2014`, которое совпадает с `Typography.dense2014`**, то есть использование `Typography.dense2014.titleLarge` в AppBar позволяет восстановить текстовый стиль AppBar M3 до состояния M2.

![Иллюстрация](http://img.cdn.guoshuyu.cn/20231123_M3/image14.png)

Дошли ли вы до этого места и поняли основной подход?

**С помощью условия `theme.useMaterial3` находите контролы, затем в исходном коде находитесь реализация M2, после чего модифицируете её в глобальном темовом конфигурационном файле**, например, для AppBar используется конфигурация `AppBarTheme`. Если реализация M2 использует какие-либо дефолтные настройки, следует найти их происхождение. Таким образом, работа с M3 требует значительных усилий.

## Карточка (Card)

Как показано на рисунке ниже, это изменения компонента `Card` между версиями M2 и M3. Вместо стандартной закруглённой формы цвет карточки изменился с белого на светло-голубой. Однако здесь есть небольшое ограничение: даже если вы установите цвет карточки как `Colors.white`, она всё равно будет иметь этот голубой оттенок.| M2                                                        | M3                                                        |
| ------------------------------------------------------- | ------------------------------------------------------- |
| ![](http://img.cdn.guoshuyu.cn/20231123_M3/image15.png) | ![](http://img.cdn.guoshuyu.cn/20231123_M3/image16.png) |

Как можно удалить этот цвет? Достаточно просто установить значение `surfaceTint` в `ColorScheme` на прозрачность. Как показано на следующих рисунках, эффект карточки реализован через использование компонента `Material`. В версии M3 `Material` использует значения `elevation` и `surfaceTint` для создания поверхности.

```dart
ColorScheme.fromSeed(
  seedColor: Colors.blue,

  /// влияет на цвет поверхности карточки, так как в M3 используется applySurfaceTint в Material
  surfaceTint: Colors.transparent,
),

Поэтому, чтобы удалить этот голубой оттенок, достаточно установить surfaceTint на прозрачность. Аналогичная логика применима и к компоненту BottomAppBar. Таким образом, если вам требуется восстановить внешний вид этих компонентов до состояния M2, достаточно установить surfaceTint на прозрачность.

image-20231123172627998Аналогичные изменения являются самыми сложными моментами при переходе на M3. Если вы не знакомы с внутренней реализацией этих компонентов, то после обновления вы можете столкнуться с тем, что, несмотря на указание белого цвета, карточка имеет светло-голубой оттенок. Это может стать настоящим испытанием для разработчиков. Поэтому здесь мы предлагаем использовать карточку (Card) как пример решения этой проблемы.Ещё один типичный компонент — это FloatingActionButton (FAB).

Floating Action Button (FAB)

Основное изменение компонента FloatingActionButton (FAB) между версиями M2 и M3 заключается в том, что он стал прямоугольным вместо круглого. Кроме того, его цвет больше не зависит от основного цвета темы. Мы можем не говорить сейчас о том, является ли эта "оптимизация" положительной или отрицательной, но рассмотрим, как можно вернуть FAB к внешнему виду версии M2.| M2 | M3 | | ------------------------------------------------------- | ------------------------------------------------------- | | | |

Сначала следует конфигурация параметра с именем floatingActionButtonTheme, который можно использовать для настройки FloatingActionButtonThemeData. Поэтому мы добавляем эту конфигурацию, возвращаем форму кнопки обратно к круглой форме и меняем цвет фона (backgroundColor) на синий.

floatingActionButtonTheme: FloatingActionButtonThemeData(
    backgroundColor: Colors.blue,
    shape: CircleBorder()
),

Осталось настроить цвет иконки. Мы можем изменить цвет иконки на белый каждый раз, когда используем Icon, но нам требуется глобальная конфигурация по умолчанию, чтобы вернуться к состоянию до M2. Для этого нам нужно найти, как цвет иконки получается внутри FAB.

Поиск реализации этого цвета привел меня в долгое путешествие...Изначально Icon получает свой цвет по умолчанию через IconThemeData. Так как в теме FAB нет возможности настроить iconTheme, то логично было бы установить глобальное значение iconTheme: IconThemeData. Однако после настройки это не работало.

Дальнейший поиск показал, что FAB использует RawMaterialButton для отображения иконки при нажатии. Внутри RawMaterialButton используется метод IconTheme.merge, поэтому по умолчанию цвет иконки внутри FAB определяется значением effectiveTextColor.

После длительного поиска связей между компонентами стало понятно:

  • Цвет effectiveTextColor берётся из TextSytle переданного в FAB.
  • textStyle берётся из extendedTextStyle.
  • extendedTextStyle берётся из foregroundColor.
  • foregroundColor по умолчанию берётся из floatingActionButtonTheme.foregroundColor.

image-20231123174431747

Похоже, что проблема была решена, необходимо глобально установить цвет иконки внутри FAB, для этого следует настроить foregroundColor в FloatingActionButtonThemeData. Как можно было бы догадаться, такое решение и название могут быть непонятны большинству.

К тому же, передача таких настроек является довольно "скрытой", что делает FAB отличным примером сложностей управления темами в Flutter: глубокие уровни передачи, сложные ссылки на темы, а также скрытые реализации слияния/copy.```dart floatingActionButtonTheme: FloatingActionButtonThemeData( backgroundColor: Colors.blue, foregroundColor: Colors.blue, shape: CircleBorder() ),


Кроме того, есть ещё одна интересная особенность **`IconThemeData`: при отсутствии полной конфигурации, то есть когда `isConcrete` не удовлетворено, остальные параметры будут заменены значениями по умолчанию при вызове `of(context)`**. Это важно для понимания процесса адаптации между Material Design 3 и Material Design 2.

![image](http://img.cdn.guoshuyu.cn/20231123_M3/image27.png)
![image](http://img.cdn.guoshuyu.cn/20231123_M3/image28.png)
![image](http://img.cdn.guoshuyu.cn/20231123_M3/image29.png)

# primarySwatch

И последнее, поговорим о `primarySwatch` в `ThemeData`. Почему мы говорим об этом? Потому что если вы используете `primaryColorDark` и `primaryColorLight` как настройки, после использования `ColorScheme.fromSeed`, они могут измениться таким образом, что восстановление до состояния Material Design 2 потребует установки `primarySwatch`.

![image](http://img.cdn.guoshuyu.cn/20231123_M3/image30.png)
![image](http://img.cdn.guoshuyu.cn/20231123_M3/image31.png)
![image](http://img.cdn.guoshuyu.cn/20231123_M3/image32.png)


# Заключение

Ниже приведён пример кода, который используется для перехода с Material Design 3 на Material Design 2. Хотя переход на Material Design 3 может представлять собой положительное обновление для команды Flutter, для пользователей в Китае это может быть отрицательным шагом, так как многие предпочитают более простую и знакомую версию дизайна.

```dart
return ThemeData(
  /// Для корректной работы `Theme.of(context).primaryColorLight` и `primaryColorDark`
  /// рекомендуется указывать `primarySwatch`.
  primarySwatch: color as MaterialColor,
)
```  /// В режиме Material Design 3 компонент Card будет использовать overlay

colorScheme: ColorScheme.fromSeed( seedColor: цвет, primary: цвет,

brightness: Brightness.light,

/// влияет на оттенок карточки, так как в M3 используется applySurfaceTint, а в Material — нет
surfaceTint: Colors.transparent,

),

/// вдохновлено значением iconThemeData.isConcrete, требуется полный набор параметров, чтобы избежать использования значения по умолчанию iconTheme: IconThemeData( size: 24.0, fill: 0.0, weight: 400.0, grade: 0.0, opticalSize: 48.0, color: Colors.white, opacity: 0.8, ),

/// изменение поведения по умолчанию для FloatingActionButton floatingActionButtonTheme: FloatingActionButtonThemeData( foregroundColor: Colors.white, backgroundColor: цвет, shape: CircleBorder()), appBarTheme: AppBarTheme( iconTheme: IconThemeData( color: Colors.white, size: 24.0, ), backgroundColor: цвет, titleTextStyle: Typography.dense2014.titleLarge, systemOverlayStyle: SystemUiOverlayStyle.light, ),


Опубликовать ( 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