Упрощение Работы с Расширениями темам в Flutter: Инструменты и Пакеты для Генерации Стилей

от автора

Содержание

  1. Пример организации и работы с темами через контекст

  2. Немного о кодогенерации

Как работать с темами

В Flutter есть встроенный инструмент для работы с темами — ThemeData. В нем хранится все стили для всех сущностей. Например, можно переопределить TextTheme и кастомизировать шрифты в приложении или изменить фон для Scaffold. Но как быть если 12 текстовых стилей вам не хватает?

Храним темы в BuildContext

Если вам недостаточно полей в TextTheme или вы хотите добавить больше цветов в приложение, используйте ThemeExtension. ThemeExtension позволяет хранить собственные свойства темы.

Рассмотрим на примере текстовых стилей
Для начала нужно создать файл, который будет наследовать ThemeExtension. В нашем случае это будет AppThemeTextStyles. Нужно сразу добавить необходимые текстовые стили.

  1. Конструктор

  2. Метод copyWith

  3. Метод lerp

class AppThemeTextStyles extends ThemeExtension<AppThemeTextStyles>{  final TextStyle header;   final TextStyle body;      const AppThemeTextStyles({     required this.header,     required this.body,   });  @override   $AppThemeTextStyles copyWith({     TextStyle? header,     TextStyle? body,   }) {     return AppThemeTextStyles(       header: header ?? this.header,       body: body ?? this.body,     );   }      @override   AppThemeTextStyles lerp(       ThemeExtension<AppThemeTextStyles>? other, double t) {     if (other is! AppThemeTextStyles) return this;     return AppThemeTextStyles(       header: TextStyle.lerp(header, other.header, t)!,       body: TextStyle.lerp(body, other.body, t)!,     );   } } 

Отлично, теперь мы можем создавать darkTextStyle, lightTextStyle, blueTextStyle или любой другой TextStyle.

static const AppThemeTextStyles darkTextStyle = AppThemeTextStyles(     header: TextStyle(     fontSize: 24,     fontWeight: FontWeight.bold,     color: Colors.black,   ),     body: TextStyle(     fontSize: 16,     fontWeight: FontWeight.normal,     color: Colors.black,   ),   );   static const AppThemeTextStyles lightTextStyle = AppThemeTextStyles(     header: TextStyle(     fontSize: 24,     fontWeight: FontWeight.bold,     color: Colors.blue,   ),     body: TextStyle(     fontSize: 16,     fontWeight: FontWeight.normal,     color: Colors.blue,   ),   );   static const AppThemeTextStyles blueTextStyle = AppThemeTextStyles(     header: TextStyle(     fontSize: 16,     fontWeight: FontWeight.normal,     color: Colors.black,   ),     body: TextStyle(     fontSize: 24,     fontWeight: FontWeight.bold,     color: Colors.white,   ); 

Теперь нужно добавить наше расширение в тему.

ThemeData createLightTheme(){     return ThemeData(       extensions: const <ThemeExtension<dynamic>>[         lightTextStyle,       ],     );   }  ThemeData createDarkTheme(){     return ThemeData(       extensions: const <ThemeExtension<dynamic>>[         darkTextStyle,       ],     );   } 

А для добавления данных о стиле в BuildContext нужно только создать расширение (extension).

extension BuildContextExtention on BuildContext {     AppThemeTextStyles get appText =>         Theme.of(this).extension<AppThemeTextStyles>()!;    } 

И всё. Теперь можно получить доступ к текстовым стилям через context.appText.header. Стиль будет зависеть от выбранной темы приложения. Вы можете добавить всё, что угодно: цвета, текстовые стили — всё, что может зависеть от выбранной темы.

А так ли это удобно?

Да, только для добавления стиля нужно внести его в несколько мест в ThemeExtension.

А можно ли это как то автоматизировать?

Да, для работы с темами есть пакет theme_tailor.

И я написал небольшой кодогенератор: extension_theme_generator. Он генерирует файл для текстовых стилей и цветов. Работает просто:

  • Отмечаем декоратором @TextStyleAnnotation() все текстовые стили.

  • Отмечаем декоратором @ColorAnnotation() классы с цветами.

// Пример для работы с цветами @ColorAnnotation()   class LightColors {     static const Color primary = Color(0xFFFFFFFF);     static const Color secondary = Color(0xFFEEEEEE);     static const Color background = Color(0xFFEDF6F6);   }      @ColorAnnotation()   class DarkColors {     static const Color primary = Color(0xFF000000);     static const Color secondary = Color(0xFF111111);     static const Color textColor = Color(0xFF111111);  // Также создастся, но для `LightColors` будет красным.      static const Color background = Color(0xFF015D60);      } 
  • Запускаем команду flutter pub run build_runner build.

  • Профит! Осталось добавить созданные AppThemeColors и AppTextStyles в ваши темы.

Пример с кодогенератором

Полный пример тут

//example/lib/theme import 'package:flutter/material.dart';   import 'package:extension_theme_generator/extension_theme_generator.dart';      part 'text_styles.dart'; // Тут все текстовые стили  part 'app_colors.dart';  /// тут все для цветов    part 'theme.g.dart'; /// путь до выходного файла 
//example/lib/theme/text_styles.dart part of 'theme.dart';      @TextStyleAnnotation()   class DarkTextStyle {     static const TextStyle header = TextStyle(       fontSize: 24,       fontWeight: FontWeight.bold,       color: Colors.white,     );   }         @TextStyleAnnotation()   class LightTextStyle {     static const TextStyle header = TextStyle(       fontSize: 24,       fontWeight: FontWeight.bold,       color: Colors.black,     );   }   
// example/lib/theme/app_colors.dart part of 'theme.dart';      @ColorAnnotation()   class LightColors {     static const Color primary = Color(0xFFFFFFFF);     static const Color secondary = Color(0xFFEEEEEE);   }      @ColorAnnotation()   class DarkColors {     static const Color primary = Color(0xFF000000);     static const Color secondary = Color(0xFF111111);      }      

Посетить телеграмм канал автора можно посетить тут

Подкинте программисту на кофе, ему еще песика кормить,

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

Работали ли вы с несколькими темами в приложении?

0% Не, всегда одна тема0
75% Да, есть темная и светлая сторона3
25% Да, я работаю с тремя и более темами в одном приложении1

Проголосовали 4 пользователя. Воздержавшихся нет.

ссылка на оригинал статьи https://habr.com/ru/articles/833626/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *