Jump to content

Данная статья является полной информацией о темах в FGX Native и актуальным руководством, начиная с 1.19.0.0.

  1. Введение
    1. Виды тем
    2. Акцентный цвет
    3. Системная тема и тема приложения
  2. Системная тема
    1. Получение параметров системной темы
    2. Механизмы отслеживания системной темы
    3. Как управлять системной темой в приложении
    4. Запрет автоматической смены системной темы в приложении
    5. Темная тема
  3. Тема FGX Native
    1. Цветовая система Material Design
      1. Основной цвет
      2. Вторичный цвет
      3. Цвета поверхности, фона и ошибок
      4. Цвета "На"
      5. Альтернативные цвета
      6. Прочее
    2. Генерация темы в FGX Native
    3. Применение темы
      1. Приложение
      2. Форма
      3. Принцип смены темы
    4. Использование ресурсов темы
      1. Типы значений
      2. Приоритет
      3. Применение ресурсов темы
      4. Фиксация темы
    5. Расширение темы
  4. Пример разработки приложения с поддержкой темной и светлой тем и разных цветовых оттенков.
    1. Создание тем в дизайнере ресурсов
    2. Настройки тем в проекте
    3. Программная смена тем и акцентированного цвета
  5. Советы

1. Введение

Тема — это совокупность настроек, цветов, звуков, шрифтов, курсоров, иконок, фоновых изображений и других элементов, отвечающих за интерфейс приложения.

Themes.jpg

1.1 Виды тем

В современном мире обычно различают два вида тем:

  1. Светлая тема - преимущественно использует светлые цвета в UI.
  2. Темная тема - преимущественно использует темные цвета в UI.

Именно эти два вида распространены в Android и iOS. Далее, в каждом виде могут быть уже темы разных цветовых палитр, с разными акцентными цветами и т.д.

1.2 Акцентный цвет

Акцентный цвет - это дополнительный цвет, который контрастирует или дополняет основные цвета, используемые в приложения. По умолчанию, в iOS такой цвет голубой, а в Android - изумрудный.

Вот некоторые задачи, для которых используют акцентные цвета:

  • Привлечение внимания. Яркий акцентный цвет привлекает взгляд пользователей и помогает им ориентироваться на странице.
  • Организация информации. Использование акцентного цвета для заголовков и подзаголовков помогает организовать информацию на странице и делает её более понятной для пользователей.
  • Выделение важных элементов. Акцентный цвет помогает выделить важные элементы, такие как акционные предложения или срочные сообщения, и привлечь внимание пользователей к ним.

При выборе акцентного цвета часто используют правило 60-30-10: 60% — основной цвет, 30% — акцентный, 10% — второй акцентный цвет, если он имеется.

1.3 Системная тема и тема приложения

В дальнейшем, когда мы будем говорить про тему, то мы будем рассматривать два типа тем:

  1. Системная тема (Обязательная). Это та, которая поставляется вместе с операционной системой и все приложения используют ее по умолчанию.
  2. Тема приложения (Необязательная). Это та, которая поставляется вместе с приложением и предназначена для переопределения системной темы.

2. Системная тема

Тема операционной системы / системная тема — это совокупность настроек, цветов, звуков, шрифтов, курсоров, иконок, фоновых изображений и других элементов, отвечающих за интерфейс ОС. Эти ресурсы уже включены в дистрибутив операционной системы. Практически каждое приложение прямо или косвенно использует эти ресурсы. При запуске приложения, каждый компонент выбирает цвета, настройки шрифтов и многое другое из текущей темы системы.

Разработчик может оставить внешнее отображение компонентов, как есть, доверив их системе. Либо же, может переопределить их на уровне своего приложения и настроить внешний вид уже так, как он хочет на уровне темы приложения. 

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

2.1 Получение параметров системной темы

В FGX Native предоставляет кроссплатформенный механизм для получения некоторых параметров системной темы и отслеживания их изменения. В любой момент времени вы можете запросить параметры системной темы через FGX.SystemInfo.TfgSystemInfo.Appearance:

  /// <summary>Данные о отображении операционной системы.</summary>
  TfgSystemAppearance = class
  private
    function GetSystemColor(const Index: TfgSystemColorType): TAlphaColor;
    function GetThemeKind: TfgSystemThemeKind;
  public
    /// <summary>
    ///   Акцентный цвет операционной системы. Обычно используется для подчеркивания элементов компонентов.
    /// </summary>
    property AccentColor: TAlphaColor index TfgSystemColorType.Accent read GetSystemColor;
    /// <summary>Вид системной темы.</summary>
    property ThemeKind: TfgSystemThemeKind read GetThemeKind;
  end;
  • ThemeKind - вид системной темы (Светлая/Темная). 
  • AccentColor - акцентный цвет в текущей теме.

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

2.2 Механизмы отслеживания изменений системной темы.

При изменении любых параметров системной темы, которые влияют на приложение, система оповещает приложение о таких изменениях. Эти изменения можно узнать следующими способами:

Первый способ: На уровне формы есть событие TfgForm.OnSystemAppearanceChanged, которое вызывается каждый раз, когда меняется один из параметров отображения системной темы.

TfgSystemAppearanceChangedEvent = procedure(Sender: TObject; const AAppearance: TfgSystemAppearance) of object;

В параметре AAppearance (FGX.Platform.TfgSystemAppearance) передается объект, позволяющий извлечь базовую информацию о теме.

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

Второй способ: Если вы хотите отслеживать изменения в системной теме вне формы, то вы можете подписаться на широковещательную рассылку на сообщение FGX.Platform.TfgSystemAppearanceChangedMessage

/// <summary>Уведомление о смене системной темы.</summary>
TfgSystemAppearanceChangedMessage = class(TObjectMessage<TfgSystemAppearance>);

Полученный объект TfgSystemAppearance удалять не нужно.

2.3 Управление системной темой в приложении.

Как мы упомянули выше, системная тема определяет внешний вид вашего приложения по умолчанию. Однако, пользователи вашего приложения могут иметь свои предпочтения в использовании светлой или темной темы в рамках вашего приложения. И поэтому FGX Native предлагает механизм для указания этого предпочтения.

Управление применением системной темой к приложению осуществляется при помощи настроек Application.Themes. Вид системной темы указывается в свойстве: Application.Themes.Kind.

  TfgThemeKind = (SystemDefault, Light, Dark);

Допускает три варианта значений:

  1. Light - приложение использует светлую тему.
  2. Dark - приложение использует темную тему.
  3. SystemDefault - приложение использует такую же тему, как и в системе. При смене темы в системе, автоматически изменится тема и в приложении. Только, если приложение поддерживает темную тему (смотри следующий раздел).

2.4 Запрет автоматической смены темы в приложении

Если ваше приложение не поддерживает темную тему. Например, если вы используете свой дизайн или вы не предусмотрели отображение приложения в темной теме, то вы можете отключить темную тему для приложения, чтобы приложение не пыталось её использовать. Это выполняется в настройках проекта Project -> FGX Options -> Приложение -> Темы. Необходимо снять галку "Включить темную тему".

2.5 Темная тема

Не смотря на то, что темная системная тема появилась относительно давно, ее полноценная поддержка есть не на всех версиях.

  • iOS 13.0+. До 13 версии поддержки нет.
  • Android 10+ (Level 29+). До 10 версии есть только адаптация.

3. Тема FGX Native

Тема FGX Native представляет собой ни что иное, как заранее определенный набор цветовых ресурсов, которые помещены в одну папку и имеют относительно этой папки "известные" для FGX Native названия. В качестве цветовой системы использует цветовая системы Material Design 2.0 по умолчанию. Не смотря на это, вы можете использовать свои цветовые системы, которые вам могут быть удобнее. Выбор в большей степени зависит от вашего дизайна приложения.

Прежде, чем перейти непосредственно к использованию темы в FGX Native, следует разобраться с принципом построения и использования системы Material Design.  

3.1 Цветовая система Material Design

Примечание: Данный текст частично взят и переработан с учетом специфики FGX Native с официального сайта Material Design.

Система цветов помогает вам применять цвета в UI вашего приложения осмысленным образом. В системе Material Design 2.0 вы выбираете основной (Primary) и дополнительный (Secondary) цвета для представления вашего бренда. Затем на основании этих двух цветов строятся все остальные цвета, включая темные и светлые варианты каждого цвета.

Базовая цветовая тема состоит из следующих цветов:

  1. Первичный/Основной (Primary) и вторичный (Secondary) цвета.
  2. Варианты основных и дополнительных цветов (Primary Varian, Secondary Variant). Эти цвета в FGX Native имеют следующие названия:  
    1. "Primary\Dark Primary", "Secondary\Dark Primary" - Темный вариант основного и вторичного цветов
    2. "Primary\Light Primary", "Secondary\Light Primary" - Светлый вариант основного и вторичного цветов
  3. Дополнительные цвета пользовательского интерфейса, такие как цвета фона, поверхностей, ошибок, типографики и иконок.

image.png

3.1.1. Основной цвет

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

image.png

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

image.png

3.1.2 Вторичный цвет

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

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

Вторичные цвета лучше всего подходят для:

  • Плавающие кнопки действий
  • Элементы управления выбором, такие как ползунки и переключатели
  • Выделение выделенного текста
  • Индикаторы прогресса
  • Ссылки и заголовки

Как и основной цвет, ваш вторичный цвет может иметь темные и светлые варианты. Цветовая тема может использовать ваш основной цвет, вторичный цвет и темные и светлые варианты каждого цвета.

3.1.3 Цвета поверхности / фона и ошибок

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

  • Цвета поверхности (Surface) влияют на поверхности компонентов, таких как карточки TfgForm / TfgCardPanel / TfgBottomSheetLayout / TfgDrawerLayout, списки TfgCollectionView/TfgListMenu и меню.
  • Цвет фона (Background) отображается за прокручиваемым содержимым. Базовый фон и цвет поверхности — #FFFFFF.
  • Цвет ошибки (Error) указывает на ошибки в компонентах, такие как недопустимый текст в текстовом поле. Базовый цвет ошибки — #B00020.

image.png

Если попробовать упростить эту модель и перенести ее на компоненты FGX Native, то можно выделить основные правила использования:

  1. Background обычно используется, как самый задний цвет контейнера верхнего уровня. Например, TfgForm.
  2. Surface используется, как цвет заднего фона для контейнеров, которые лежат на контейнере с фоном Background. Чаще всего это TfgCardPanelTfgBottomSheetLayout

image.png

3.1.4 Цвета На/On

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

Эта категория цветов называется «На/On» цветами, ссылаясь на тот факт, что они окрашивают элементы, которые появляются «на» поверх поверхностей и используют следующие цвета: основной цвет, вторичный цвет, цвет поверхности, фоновый цвет или цвет ошибки. Когда цвет появляется «на» поверх основного цвета, он называется «над основным цветом». Они маркируются с использованием исходной цветовой категории (например, основной цвет) с префиксом «On».

«On» цвета применяются в основном к тексту, иконографии и штрихам. Иногда они применяются к поверхностям.

image.png

Такие цвета есть для всех цветов: основного, вторичного, поверхности, фона и ошибок цветов. В FGX Native такой набор состоит из 6 цветов:

  1. Text - основной цвет текст. 
  2. Secondary Text - цвет дополнительного текста. Используется для выделения второстепенной текстовой информации, как примечание, подзаголовок и тд.
  3. Icon - цветовой оттенок иконок, отображаемых на текущем цвете.
  4. Dividers - цвет полосок разделителей. Например, полоса-разделитель элементов в списке TfgCollectionView.
  5. Hint Text - цвет текста для подсказки ввода текста в поля ввода (TextPrompt)
  6. Disabled Text - текст на компонентах, не доступных для взаимодействия.

Пример ниже иллюстрирует ручное применение цветов темы для элементов кнопки. Если кнопка использует основной цвет "Primary", как фон. То, соответственно, иконка и текста должны использовать цвета из группы цветов "On Primary"

image.png

3.1.5 Альтернативные цвета

Используемая цветовая система является рекомендованной, но не обязательной. Вы всегда можете, как добавить в нее дополнительные основные "Primary" цвета, чтобы расширить разнообразие цветов, так и использовать любую другую, например из Material Design 3.0. 

Например, приложение LEDPanel из выступления про разработку приложения, как раз демонстрирует использование альтернативной цветовой системы:

image.pngimage.png

3.1.6 Прочее

Об остальных вариантах использования цветов и правил их применения следует обратиться к официальной документации.

3.2 Генерация темы FGX Native

Для того, чтобы добавить тему буквально в один клик, мы предлагаем генератор темы в дизайнере ресурсов (Project -> FGX Assets Manager). Он доступен либо в контекстном меню дерева ресурсов "Сгенерировать тему" image.png, либо через соответствующую иконку на панели инструментов.

image.png

В самом верху окна вам необходимо выбрать тип темы. Здесь все просто: "светлая" или "темная".

Затем выбираете два базовых цвета: Основной Primary/P и Вторичный Secondary/S цвета. Левой кнопкой мыши выбирается основной цвет P, а правой - вторичный S.

При выборе основных цветов, генератор автоматически определяет оттенок группы цветов "On" используемой на каждом из двух цветов. При необходимости вы можете откорректировать группы при помощи радиокнопок внизу. Если основной цвет яркий, то для соблюдения контраста, все элемента отображаемые На ярком цвете, должны быть темными и наоборот. После нажатия на кнопку "Сгенерировать", мы получаем наборы цветом согласно системе цветов Material Design.

image.png

Если вы планируете использовать несколько тем в вашем приложении, мы рекомендуем группировать темы по типу (Светлая / Темная) и цветовым оттенкам. Например, так:

image.png

Обратите внимание, что если вы хотите использовать темы вашем приложении, то вам как минимум надо сгенерировать светлую тем, а максимум, добавить еще и темную.

3.3 Применение темы

В FGX Native тема может применяться на двух уровнях:

  1. Приложение
  2. Форма

3.3.1 Приложение

Тема, применяемая на уровне приложения автоматически применяется ко всем формам и ко всем компонентам. Кроме случаев, о которых будет сказано далее. 

Тема может быть задана двумя способами.

1. На уровне настроек проекта (DesignTime) с 1.19.0.0: Этот основной способ и он позволяет применить тему, как в дизайнере, так и автоматически на старте приложения на устройстве.

Чтобы задать тему на уровне приложения, нужно зайти в настройки проекта Project -> FGX Options... -> Приложение -> Темы

image.png

В поле (1) мы можем указать способ выбора темы при старте приложения. Доступны три варианта:

  1. Согласно системной теме. Если на устройстве используется светлая тема, то будет использоваться светлая тема в приложении, если же в системе используется темная, то в приложении автоматически будет применена темная тема
  2. Светлая - Независимо от системной темы, внутри приложения будет использовать светлая тема. 
  3. Темная - Независимо от системной темы, внутри приложения будет использовать темная тема. 

В поле (2) указываем название светлой FGX Native темы из дизайнера ресурсов. Если вы использовали нашу рекомендацию по группировке и именованию тем, то это может быть "Themes\Light\Green" (Светлая тема с зеленым основным цветов).

В поле (3) включаем или отключаем поддержку темной темы в приложении. Возможно, ваш дизайн приложения не предусматривает темную тему или у вас ее нет. В этом случае, необходимо убедиться, что галка с этого поля снята.

В поле (4) указываем название темной темы из дизайнера ресурсов (если включена поддержка темной темы).

В момент старта приложения FGX Native применяет тему согласно вашим настройкам. Например, вот так:

 Screenshot_20250328-074208.pngScreenshot_20250328-074226.png

В режиме выполнения (Runtime): Этот способ может использоваться, если вы хотите позволить пользователю менять вашу тему в соответствии с его предпочтениями. За настройки темы (аналогичные 3.3.1) отвечает свойство Application.ThemeSettings:

/// <summary>Название светлой темы FGX Native, используемой по умолчанию во всех формах.</summary>
property LightThemeName: TfgThemeName read FLightThemeName write SetLightThemeName;
/// <summary>Название темной темы FGX Native, используемой по умолчанию во всех формах.</summary>
property DarkThemeName: TfgThemeName read FDarkThemeName write SetDarkThemeName;
/// <summary>Применяемая тема по умолчанию.</summary>
property ThemeKind: TfgThemeKind read FThemeKind write SetThemeKind;

По сути здесь те же свойства, что и в настройках проектах, кроме возможность отключить темную тему во всем приложении.

Например, если вы хотите добавить несколько вариантов тем для разных акцентных цветов, то вы можете это сделать так (если вы используете предложенные вариант группировки тем в дизайнере ресурсов)

  Application.ThemeSettings.LightThemeName := 'Themes\Light\' + AccentColorName;
  Application.ThemeSettings.DarkThemeName := 'Themes\Dark\' + AccentColorName;

В любой момент времени, изменяя название темы приведет к автоматическом применению темы ко всему приложению.

Узнать используемое в текущий момент времени название темы приложения можно через Application.ThemeName.

3.3.2 Форма

Если по каким-то соображениям, вы не хотите, чтобы на каком-то экране/форме у вас использовалась тема приложения, вы можете ее переопределить локально на уровне формы, указав ее имя в свойстве TfgForm.ThemeName:

image.png

В этом случае все вложенные компоненты будут автоматически использовать тему формы, а не приложения.

3.3.3 Принцип смены темы

Когда меняется тема в приложении или локально в рамках одной формы, форма сообщает всем компонентам дерева о необходимости сменить тему. У каждого компонента вызывается виртуальный метод TfgControl.ThemeChanged и передается имя новой темы "AThemeName":

/// <summary>Информирует, что изменена тема и следует обновить связи с ресурсами.</summary>
procedure ThemeChanged(const AThemeName: TfgThemeName); virtual;

Затем каждый компонент в зависимости от набора настроек выполняет применение новой темы к свойствам. Например, каждый компонент имеет задний фон BackgroundName, который поддерживает темизацию. Поэтому базовая реализация вызывает метод для установки нового имени темы для фона при помощи BackgroundLink.ChangeTheme (BackgroundLink - это сущность, связывающая ресурс фона с компонентом).

procedure TfgControl.ThemeChanged(const AThemeName: TfgThemeName);
begin
  TfgAssert.IsNotNil(BackgroundLink, 'BackgroundLink');

  if TfgDebugAssetsOption.Themes in TfgLibraryDiagnostics.DebugAssetsOptions then
    TfgLog.Trace(ThemesTag, SThemesApplyingNewTheme, [ToString, AThemeName]);

  BackgroundLink.ChangeTheme(AThemeName);
  SendMessage<TfgThemeName>(TfgControlMessages.WM_THEME_CHANGED, AThemeName);
end;

Если в имени ресурса используется указание на использование темы (наличие ":", как разделитель между название темы и ресурса), то происходит автоматическая замена старой темы на новую. В противном случае, ничего не происходит. 

3.4 Использование ресурсов темы

После того, как мы научились делать свою тему и применять ее, теперь необходимо научиться настройке внешнего вида компонента на основании текущей темы.

Компоненты FGX Native предлагают широкий набор свойств, отвечающих за изменение внешнего вида компонента. Например, TfgButton дает возможность поменять цвет фона, рамки, текста, перекрасить иконку и т.д.

image.png

3.4.1 Типы значений

Большинство компонентов уже настроены для работы с ресурсами будущей темы. Это значит, что часть свойств компонента, отвечающие за связь с ресурсами цвета и настройку внешнего вида, уже могут быть по умолчанию связаны с темой. Чтобы это понять, достаточно посмотреть на свойство в инспекторе объектов:

1. Если в свойстве ничего не указано, то значит будет использовать соответствующий цвет из системной темы. Например: у кнопки по умолчанию не используется цвет из темы, поэтому ее внешний вид и цвет будет отличаться в Android и iOS.

image.png

2. Если в свойстве бледно серым цветом указано название ресурса, то это название ресурса из темы FGX Native, которое будет использоваться, если в приложении создана тема. Например, форма по умолчанию использует цвет "Background":

image.png

На изображении выше видно, что по умолчанию форма использует белый цвет Background из светлой темы с зеленым основным цветом "Themes\Light\Green".

3. Если в свойстве значение указано бледно серым цветом и слева от названия вы видите рамку с красным крестиком, это значит, что либо в приложении нет темы FGX Native, либо в текущей теме нет ресурса с именем Background.

image.png

4. Если в свойстве название ресурса указано ярким цветом, то это значит, что цвет указан вручную и переопределяет цвет по умолчанию из темы, если он есть.  

image.png

5. Начиная с 1.19.0.0. Цветовое свойство допускает указание кода цвета напрямую в качестве имени ресурса. 

image.png

3.4.2 Приоритеты

Большинство цветовых свойств компонентов FGX Native присутствует в двух вариантах:

  1. С постфиксом "Name": TintColorName, ColorName
  2. Без постфикса "Name": TintColor, Color

Если вы видите такие парные свойства, значит они оба отвечают за настройку одной характеристики внешнего вида компонента. Приоритет у таких свойств следующий в порядке убывания и наличия: 

  1. Указанное вручную название ресурса цвета.
  2. Указанное название ресурса цвета из темы по умолчанию.
  3. Значение цвета из свойства Color, TintColor и т.д.
  4. Значение цвета из системной темы (определяется каждым компонентов самостоятельно реализацией).

Данное дублирование появилось с самого начала разработки FGX Native и было предназначено только для быстрого прототипирования компонентов в дизайнере и облегчения перехода разработчиков с VCL и FMX. Однако, использование цвета напрямую не было рекомендовано к использованию. Несмотря на это, главным и основным способом указания цвета остается использование цвета через имя ресурса. В будущих версиях мы планируем скрыть из дизайнера все свойства с прямым заданием кода цвета и перенесем эту возможность напрямую в свойство имени цвета (Как указано в конце раздела 3.4.1).

3.4.3 Применение ресурсов темы

Для корректного отображения некоторых компонентов, которые могут иметь несколько вариантов отображения (например, кнопка), вам необходимо настроить внешний вид, используя ручное указание ресурсов темы.

Например, мы используем в приложении заполненную (Contained) цветом кнопку с иконкой. Указываем цвета для иконки, текста и оттенок согласно системе цветов. И тогда при переключении темы с "Themes\Dark\Green" на "Themes\Light\Blue" внешний вид кнопки будет согласован с темами. 

При указании ресурса из темы важно (начиная с 1.19.0.0) использовать ":", как знак разделитель темы и ресурса темы. Соответственно, если у нас есть тема: "Themes\Light\Blue", а внутри цвет "Secondary\Color", то полное имя ресурса будет выглядит так "Themes\Light\Blue:Secondary\Color

 image.pngimage.png

При смене темы формы или приложения, все свойства, которые используют имена ресурсов с указанием темы с ":" будут автоматически обновлены на использование новой темы. 

3.4.4 Фиксация ресурса цвета

Возможны ситуации, когда необходимо использовать цвет из темы, но без автоматического обновления. Например, вы сделали несколько тем с разными акцентными цветами, и хотите их отобразить на форме. В таком случае, не нужно использовать ":", как разделитель ресурсов, а использовать "\". Тогда при смене темы такие значения не будут изменены.

image.png

3.5 Расширение темы

Использование темы не ограничено лишь цветами. Вы можете добавлять в структуру темы ресурсы любого типа и использовать их. Например, вы можете использовать разные наборы иконок в темах.

4. Пример разработки приложения с поддержкой темной и светлой тем и разных цветовых оттенков.

Рассмотрим применение тем на практике. В качестве площадки для практики возьмем любое приложение. Вы можете взять свое. Я же взял заготовку из демонстрационных проектов. 

image.png

В данном проекте нет никакого использования ресурсов, а так же нет никаких тем.

Перед нами стоят следующие задачи:

  1. Добавить поддержку темной и светлой тем.
  2. Добавить возможность переключать темы вручную.
  3. Добавить возможность переключать темы автоматически согласно настройкам системной темы на устройстве.
  4. Добавить возможность менять акцентированный цвет. В примере рассмотрим два цвета: зеленый и синий. На практике как цвета, так и их количество может быть любым.

4.1 Создание тем в дизайнере ресурсов

Добавление поддержки тем начинается с создания темы в дизайнере ресурсов. У нас должно быть два вида тем:

  1. Светлая
  2. Темная

А так же два вида акцентированного (Primary) цвета для каждого вида тем:

  1. Зеленый
  2. Синий.

В результате у нас должно получиться 4 темы. Для удобства организации тем в дизайнере ресурсов я решил использовать такую группировку:

  1. Первый уровень - Themes, сюда складываем все виды тем.
  2. Второй уровень - Dark/Light - группировка всех тем по виду.
  3. Третий уровень - Green/Blue акцентированный цвет.

Открываем дизайнер ресурсов Project -> FGX Assets Manager.

Создаем такую структуру.

image.png

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

image.pngimage.pngimage.pngimage.png

4.2 Настройки тем в проекте

Наши FGX Native темы готовы, теперь сохраняем изменения и переходим к настройке тем в проекте. Для этого открываем настройки проекта Project -> FGX Options...-> Приложение -> Темы.

  1. Выбираем конфигурацию "All Configurations - All platforms", чтобы наши настройки тем применились для всех платформ и конфигураций.
  2. Пусть при старте у нас будет использоваться такая же тема, как и в системе. Для этого в "Используемая тема при старте" (2) выбираем "Согласно системной теме"
  3. В поле "название светлой темы" (3) указываем одну из двух наших светлых тем. Будем считать, что зеленый акцентированный цвет будет использоваться по умолчанию. Поэтому указываем соответствующую светлую тему: "Themes\Light\Green"
  4. Включаем поддержку темной темы в приложении (4). 
  5. В поле "название темной темы" (5) указываем соответствующую темную тему: "Themes\Dark\Green"

image.png

Теперь при старте нашего приложения, приложение автоматически получит тему с зеленым акцентированным цветом соответствующего типа. Запускаем и проверяем. При старте в системе установлена светлая тема, она же и применилась в приложении. Меняем системную тему на темную при помощи панели управления Android или iOS и приложение автоматически меняет ее на темную.

 Screenshot_20250328-074208.pngScreenshot_20250328-074219.pngScreenshot_20250328-074226.png

Как вы можете видеть, компоненты уже адаптированы и заточены на использование тем FGX Native, поэтому в данном случае мы не выполняли никакой ручной настройки компонентов.

Половина дела уже сделана. Добавлена поддержка двух тем с автоматической синхронизацией с системной темой. Теперь необходимо добавить возможность ручного управления темами и акцентированным цветом. 

4.3 Программная смена тем и акцентированного цвета

Чтобы пользователь мог менять тему в приложении по своему усмотрению, создадим такую панель управления, выдвигаемую снизу экрана. Для этого используем TfgRadioButton и TfgBottomSheetLayout.

image.png

Чтобы пользователь видел акцентированный цвет, для нижней группы радио кнопок по отдельности указываем соответствующий акцентированный цвет из темных или светлых тем:

Для синего цвета используем такое указание название цвета: "Themes\Light\Blue\Primary\Color".

Важно: чтобы в качестве разделителя имени темы "Themes\Light\Blue" и ресурса "Primary\Color" использовался разделитель "\". В этом случае, при любой смене темы данное имя не будет изменяться. В противном случае, при смене темы цвет так же будет изменяться.

image.png

Задаем группы (TfgRadioButton.GroupName ) "ThemeKind" и "AccentColor" для трех верхних и двух нижних групп радиокнопок соответственно. Тип используемой темы задается при помощи перечисляемого типа "TfgThemeKind = (SystemDefault, Light, Dark);". Чтобы нам было удобнее, задаем трем верхним радио кнопкам соответствующие значениям TfgThemeKind целочисленные значения от 0 до 2 в свойстве Tag.

Теперь при выборе типа темы, нам нужно отразить это изменение в приложении. Для этого выбираем три верхних TfgRadioButton и пишем такой обработчик OnChanged.ChangeTheme:

procedure TFormMain.ChangeTheme(Sender: TObject);
var
  RadioButton: TfgRadioButton;
begin
  TfgAssert.IsClass(Sender, TfgRadioButton);

  RadioButton := TfgRadioButton(Sender);
  Application.ThemeSettings.ThemeKind := TfgThemeKind(RadioButton.Tag); // Свойство Tag содержит целочисленное значение TfgThemeKind
end;

Проверяем, Sender действительно ли является TfgRadioButton. Затем извлекаем целочисленное значение TfgThemeKind и устанавливаем его в настройки приложения Application.ThemeSettings.ThemeKind.

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

procedure TFormMain.ChangeAccentColor(Sender: TObject);
var
  RadioButton: TfgRadioButton;
  AccentColorName: TfgThemeName;
begin
  TfgAssert.IsClass(Sender, TfgRadioButton);

  RadioButton := TfgRadioButton(Sender);
  AccentColorName := RadioButton.Text;
  Application.ThemeSettings.LightThemeName := 'Themes\Light\' + AccentColorName;
  Application.ThemeSettings.DarkThemeName := 'Themes\Dark\' + AccentColorName;
end;

Берем название акцентированного цвета напрямую из названия TfgRadioButton. И формируем новое название тем.

Проверяем. Запускаем наше приложение.

Вот таким незамысловатым способом можно легко добавить поддержку тем в 1.19.0.0.

image.png

5. Советы

  1. При проектировании интерфейса всегда учитывайте, что у вас должна быть поддержка светлой и темной тем.
  2. Лучше сразу добавить в самом начале две базовые темы: светлая и темная с одним из основных цветов.
  3. При настройке внешнего вида компонентов, используйте ресурсы из темы, где это необходимо. Это сильно упростит вам дальнейшую настройку внешнего вида приложения и добавление поддержки новых тем. 
  4. Вы всегда можете проверить корректность внешнего вида приложения в дизайнере, вручную указав название темы в форме, либо воспользовавшись переключателем вида темы в дизайнере форм.
  5. Не используйте зашитые коды цветов прямо в компонентах (свойства Color, TintColor и т.д.), иначе при смене темы, эти цвета останутся без адаптации. 
  6. При любом использовании цветов, выносите его в ресурсы. Если вы понимаете, что данный цвет может зависеть от темы, то смело включайте его в состав тем.

0 Comments

Recommended Comments

There are no comments to display.

Recently Browsing 0

  • No registered users viewing this page.