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

OSCHINA-MIRROR/CarGuo-GSYFlutterBook

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

Простые советы по работе с Flutter 3.0: ThemeExtensions и Material3

Эта статья рассказывает о двух важных компонентах в Flutter 3.0: ThemeExtensions и Material3, возможно, вы ещё не знакомы с ними.

ThemeExtensions

Каждый из нас уже использовал Theme в Flutter, где можно изменять глобальные свойства ThemeData, чтобы настроить внешний вид приложения, например, отключить эффекты нажатия для InkWell и TextButton.

theme: ThemeData(
    primarySwatch: Colors.blue,
    // Отключение эффекта водяной пленки для InkWell
    splashFactory: NoSplash.splashFactory,
    // Отключение эффекта высветления для InkWell
    highlightColor: Colors.transparent,
    textButtonTheme: TextButtonThemeData(
        // Отключение эффекта водяной пленки для TextButton
        style: ButtonStyle(splashFactory: NoSplash.splashFactory),
    ),
),

Разработчики также могут использовать метод Theme.of(context) для чтения глобальных стилей ThemeData. Однако, что делать, если вам нужна опция, которой нет в ThemeData, или вы хотите, чтобы эта опция была доступна только для определённого компонента?

Flutter 3 предлагает решение этой проблемы через ThemeExtensions.

Разработчики могут расширить возможности ThemeData, создав собственные расширения путём наследования от ThemeExtension и переопределения методов copyWith и lerp, как показано ниже:

@immutable
class StatusColors extends ThemeExtension<StatusColors> {
    static const light = StatusColors(open: Colors.green, closed: Colors.red);
    static const dark = StatusColors(open: Colors.white, closed: Colors.brown);

    const StatusColors({required this.open, required this.closed});
    final Color open;
    final Color closed;

    @override
    StatusColors copyWith({Color? open, Color? closed}) {
        return StatusColors(open: open ?? this.open, closed: closed ?? this.closed);
    }

    @override
    void lerpFrom(StatusColors a, StatusColors b, double t) {}

    @override
    void lerpTo(StatusColors a, StatusColors b, double t) {}
}
```  final Color? open;
  final Color? closed;

  @override
  StatusColors copyWith({
    Color? success,
    Color? info,
  }) {
    return StatusColors(
      open: success ?? this.open,
      closed: info ?? this.closed,
    );
  }

  @override
  StatusColors lerp(ThemeExtension<StatusColors>? other, double t) {
    if (other is! StatusColors) {
      return this;
    }
    return StatusColors(
      open: Color.lerp(open, other.open, t),
      closed: Color.lerp(closed, other.closed, t),
    );
  }

  @override
  String toString() => 'StatusColors('
      'open: $open, closed: $closed'
      ')';
}
```После этого можно будет настроить `StatusColors` в расширении темы `Theme`, а затем получить конфигурацию с помощью `Theme.of(context).extension<StatusColors>()`.

```dart
theme: ThemeData(
  primarySwatch: Colors.blue,
  extensions: <ThemeExtension<dynamic>>[
    StatusColors.light,
  ],
),

...

@override
Widget build(BuildContext context) {
  // Получаем цвет статуса из ThemeExtensions
  final statusColors = Theme.of(context).extension<StatusColors>();

  return Scaffold(
    extendBody: true,
    body: Container(
      alignment: Alignment.center,
      child: ElevatedButton(
        style: TextButton.styleFrom(
          backgroundColor: statusColors?.open,
        ),
        onPressed: () {},
        child: Text("Кнопка"),
      ),
    ),
  );
}

Не сложно, правда? С помощью ThemeExtensions сторонние пакеты могут предоставлять объекты ThemeExtensions, что позволяет реализовать более гибкую настройку стилей.

Material3

Material3 также известна как MaterialYou — это новая стандартная модель дизайна пользовательского интерфейса, представленная Google вместе с Android 12. В Flutter 3.0 вы можете активировать её с помощью useMaterial3: true.

theme: ThemeData(
  primarySwatch: Colors.blue,
  // Активация использования Material3
  useMaterial3: true,
),
```Однако перед активацией Material3 вам стоит узнать больше о ней, так как она значительно влияет на стиль вашего пользовательского интерфейса.

На следующем рисунке показано различие между компонентами `AppBar`, `Card`, `TextButton` и `ElevatedButton` при использовании `primarySwatch: Colors.blue`:

![Различия в стилях компонентов](http://img.cdn.guoshuyu.cn/20220605_N2/image1.png)

Как видно, произошли изменения в закругленности углов и в базовых цветах. Кроме того, помимо более округлого внешнего вида, некоторые эффекты взаимодействия также были изменены, такие как:

- Эффект клика и дефолтный стиль диалогового окна;
- Дефолтный эффект прокрутки списка "overscroll" на Android;

| Интерактивный эффект                                             | Пример списка                                               |
| ---------------------------------------------------------------- | ------------------------------------------------------------ |
| ![](http://img.cdn.guoshuyu.cn/20220605_N2/image2.gif)           | ![Пример прокрутки списка](http://img.cdn.guoshuyu.cn/20220605_N2/image3.gif) |

В Flutter 3 (Material Design 3) в основном влияние оказывает параметр `useMaterial3`, который затрагивает следующие виджеты:

* [AlertDialog]
* [AppBar]
* [Card]
* [Dialog]
* [ElevatedButton]
* [FloatingActionButton]
* [Material]
* [NavigationBar]
* [NavigationRail]
* [OutlinedButton]
* [StretchingOverscrollIndicator]
* [GlowingOverscrollIndicator]
* [TextButton]

### Вопрос: Какие различия между Material3 и Material2?

Пример с виджетом AppBar показывает, что способ получения цвета фона отличается в Material2 и Material3. В Material3 отсутствует проверка на темную яркость (`Brightness.dark`). Это значит, что Material3 не поддерживает темную тему?На самом деле, это не так. Основное отличие заключается в том, что стиль Material3 теперь генерируется автоматически. В `_TokenDefaultsM3` используется скрипт для создания версий стилей, а текущая версия  `v0_92`.

![image-20220605_N2_image5](http://img.cdn.guoshuyu.cn/2bkzj/image5.png)

В папке gen_defaults можно найти данные, используемые для автоматической генерации стилей Material3.

![image-20220605_N2_image6](http://img.cdn.guoshuyu.cn/2bkzj/image6.png)

Основной причиной того, почему в Material3 нет необходимости использовать `Brightness.dark`, является то, что `ColorScheme` уже выполняет эту проверку внутри себя.

![image-20220605_N2_image7](http://img.cdn.guoshuyu.cn/2bkzj/image7.png)

Сейчас в Flutter 3.0 ключевой частью темы являются параметры `colorScheme`. Параметры типа `primaryColorBrightness` и `primarySwatch` будут в будущем废弃。Поэтому, если вы сейчас всё ещё используете `primarySwatch`, то в `ThemeData` внутренне будет преобразовано через `ColorScheme.fromSwatch` метод в `ColorScheme`.

```dart
ColorScheme.fromSwatch(
  primarySwatch: primarySwatch,
  primaryColorDark: primaryColorDark,
  accentColor: accentColor,
  cardColor: cardColor,
  backgroundColor: backgroundColor,
  errorColor: errorColor,
  brightness: effectiveBrightness,
);

Вы также можете использовать методы ColorScheme.fromSeed или colorSchemeSeed для прямого конфигурирования ColorScheme в ThemeData.

Вопрос: А что такое ColorScheme?

ColorScheme представляет собой набор цветовых значений, используемых для стилизации компонентов UI. Он позволяет создавать согласованную цветовую схему для всего приложения.

тема: ThemeData(
  цветовая_схема: ColorScheme.fromSeed(seedColor: Color(0xFF4285F4)),
  /// Включает использование стиля Material3
  useMaterial3: true,
),
```**Здесь мы сталкиваемся с интересной концепцией: пакет HCT цветов в рамках Material3: [material-color-utilities](https://github.com/material-foundation/material-color-utilities)**.

В рамках Material3 цвета не вычисляются строго по RGB, а проходят через преобразование с использованием [material-color-utilities](https://github.com/material-foundation/material-color-utilities). Через внутренний объект `CorePalette`, RGB преобразуется в значения, связанные с HCT, для расчета отображения.

![](http://img.cdn.guoshuyu.cn/20220605_N2/image8.png)

HCT  это аббревиатура для Hue (тон), Chroma (насыщенность) и Tone (тональность). Благодаря открытому гуглом плагину [material-color-utilities](https://github.com/material-foundation/material-color-utilities) можно легко использовать пространство цветов HCT. На данный момент этот репозиторий поддерживает Dart, Java и TypeScript, а также скоро будет поддерживать C/C++ и Objective-C.

![](http://img.cdn.guoshuyu.cn/20220605_N2/image9.png)

Благодаря HCT, например, метод `ColorScheme.fromSeed(seedColor: Color(0xFF4285F4))` позволяет создать серию тематических цветов всего одним seedColor. Это и есть причина того, почему в Material3 можно иметь более богатую цветовую палитру.

![](http://img.cdn.guoshuyu.cn/20220605_N2/image10.png)

> Дополнительно читайте [«Принципы дизайна цвета HCT»](https://material.io/blog/science-of-color-design).

# Подведение итогов

Напоследок давайте вспомним основные моменты:

- Расширение `ThemeData` с помощью `ThemeExtensions`
- Активация Material3 с помощью `useMaterial3` и настройка более богатой цветовой палитры с помощью `ColorScheme`.Теперь你可以询问你的设计师:你知道什么是HCT吗? -> Теперь你可以询问你的设计师:你知道什么是HCT?

Так как задача состоит в переводе на русский язык, исправлю:

Теперь вы можете спросить своего дизайнера: знаете ли вы, что такое HCT?

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