Как стать автором
Обновить

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

Уровень сложностиПростой
Время на прочтение4 мин
Количество просмотров368

Содержание

  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
80% Да, есть темная и светлая сторона4
20% Да, я работаю с тремя и более темами в одном приложении1
Проголосовали 5 пользователей. Воздержались 2 пользователя.
Теги:
Хабы:
Если эта публикация вас вдохновила и вы хотите поддержать автора — не стесняйтесь нажать на кнопку
-1
Комментарии0

Публикации

Истории

Работа

Swift разработчик
27 вакансий
iOS разработчик
23 вакансии

Ближайшие события

19 сентября
CDI Conf 2024
Москва
24 сентября
Конференция Fin.Bot 2024
МоскваОнлайн
30 сентября – 1 октября
Конференция фронтенд-разработчиков FrontendConf 2024
МоскваОнлайн