Skip to content
View in the app

A better way to browse. Learn more.

FGX Native

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Yaroslav Brovin

Administrators
  • Joined

  • Last visited

Blog Entries posted by Yaroslav Brovin

  1. Добрый день, уважаемые разработчики.
    Спешим порадовать вас главным нововведением 1.15.5.0 - это поддержка векторных изображений SVG.
    Добавление и использование
    В новой версии добавлен новый тип ресурсов - SVG изображение. В него вы можете загрузить SVG файл в дизайнере ресурсов для дальнейшего использования в компонентах. Добавление SVG изображения доступно в дизайнере ресурсов: Project -> FGX Assets Manager.
     
    При использовании данного изображения в компонентах, происходит автоматическое формирование растрового изображения TfgBitmap с требуемым текущим коэффициентом масштабирования окна и указанным размером иконки. При этом логический размер (dp, без учета коэффициента масштабирования) иконки указывается в окне редактирования SVG файла.

    Особенности реализации
    Как выяснилось в ходе разработки, iOS и Android не поддерживают SVG изображения. Вместо этого, они конвертируют SVG файлы в Android Studio / XCode в свой внутренний промежуточный формат, которыйв свою очередь уже используется для формирования растровых изображений. 
    В связи с этим, нам пришлось полностью своими силами разработать парсер и рендер SVG. В итоге мы выполняем обработку SVG файла на стороне Delphi и формируем наш формат, используемый для отрисовки SVG. Далее в рантайме по файлам нашего формата, генерируем изображения.
    Генерация 
    При необходимости вы можете сформировать экземпляр растрового изображения TfgBitmap по SVG изображению любого размера. Для этого вам нужно запросить ресурс у TfgAssetsManager. При этом вы отвечаете за удаление экземпляра TfgBitmap:
    uses FGX.Canvas, FGX.Canvas.Types, FGX.Assets, FGX.Assets.SVG; var Asset: TfgAssetSVG; Bitmap: TfgBitmap; begin if TfgAssetsManager.Current.Find<TfgAssetSVG>('SVG asset name', Asset) then begin Bitmap := Asset.CreateBitmap(TSizeF.Create(100, 20)); try // Works with bitmap. finally Bitmap.Free; end; end; end; Ограничения
    1. Неполноценная поддержка спецификации SVG. Мы проверили наш SVG парсер на иконках разных поставщиков от MaterialDesign, Microsoft Visual Studio Icons и до Icons 8. Однако, стандарт SVG довольно большой и написать за такое короткое время полноценный парсер задача довольно непростая. Несмотря на это, мы хотели бы, чтобы вы делились с нами SVG файлами, которые не могут прочитаться и отобразиться корректно. Это поможет нам оперативнее расширять парсер в тех направлениях, которые нужны для отображения массовых SVG изображений. 
    При загрузке изображения в дизайнере, у иконки появится специальный значок ошибки, если она не поддерживается.
     
    Если файл загрузился и может быть отображен, но при чтении не удалось распознать какие-либо элементы, то он помечается значком-предупреждением:

    Это означает, что теоретически изображение может отобразиться, но оно может отображаться не корректно.
    2. Отображение превью svg иконки в дизайнере ассетов не говорит о поддержке SVG файла. Для отображения SVG изображений в IDE мы используем Skia4Delphi. Однако, практика показала, что иногда SVG иконки, которые мы отображаем успешно на устройствах, не отображаются корректно в Skia4Delphi.
    Например, отображение иконки в Runtime через FGX Native:

    В то же время, Skia4Delphi (дизайнер IDE) просто показывает черный квадрат:

    Поэтому вам необходимо временно проверять корректно отображения SVG иконки именно на основании Runtime. Несмотря на то, что мы можем формировать SVG изображения и в дизайнере тоже нашим средство, мы пока используем Skia4Delphi, чтобы была возможность сравнить, как иконки должны отображаться корректно (парсер SVG должен по идее поддерживать больше функций). Спустя время, как только наш парсер будет поддерживать все ваши иконки, мы заменим в дизайнере рендер SVG иконок в дизайнере на наш.
    3. Временно недоступна возможность динамически добавлять SVG файл в рантайме. Например, вы загрузили SVG файл в рантайме и хотите его отобразить. Несмотря на то, что технически у нас уже есть такая возможность, наш парсер пока не оптимизирован, чтобы выполнять преобразование SVG формата достаточно быстро. Чтобы потенциально не побуждать пользователей к проседанию производительности, данная возможность временно недоступна. При этом мы считаем, что такой сценарий довольно редкий. И по большей части, вы будете использовать именно заранее добавленные SVG изображения.   
  2. Добрый день, уважаемые разработчики.
    В этой статье мы рассмотрим настройку и использование сервиса Firebase Messaging (FCM)для приема push-уведомлений на платформе iOS.
    Начиная с версии FGX Native 1.15.2.0, вы можете использовать Firebase не только на Android, но теперь и на iOS. Тем самым не нужно выполнять дополнительные действия для конвертации токенов устройств из Apple Push Service (APS) в токен Firebase (FCM), сделав ваш код полностью кроссплатформенным.
    Перед тем, как приступить к работе с уведомлениями, необходимо выполнить регистрацию аккаунта Google.
    Регистрация приложения в Firebase для iOS
    1. Откройте Firebase Console и выполните вход в учетную запись Google. 
    2. Нажмите кнопку "Создать проект"

    3. Укажите название вашего проекта и нажмите кнопку "Continue". Вы можете использовать любое название. Например: "FGX Native project". 

    4. На текущей странице вы можете отключить поддержку Google Analytics. Вы можете ее отключить. Однако, рекомендуем ее оставить. Так в будущем вы сможете использовать аналитику для данного проекта. Нажмите кнопку "Continue".

    5. Выберите или создайте аккаунт Google Analytics. Я взял созданные раннее, в который будет добавлена аналитика для нового проекта. Нажмите кнопку "Create Project".

    6. Ожидаем окончания процесса создания проекта в Firebase. По окончании нажимаем "Continue". Когда проект будет создан, вы увидите главную страницу:

    7. Теперь необходимо зарегистрировать ваше FGX Native iOS приложение для этого нажимаете на кнопку с логотипом iOS.
    8. Указываете имя пакета вашего iOS приложения, такое же, как у вашего приложения (если оно есть), или такое, какое оно будет (его можно будет указать)
    Если у вас уже есть приложение, то узнать название пакета можно в настройках проекта: Project -> Options... -> Version Info >  CFBundleIdentifier ".
    Если у вас еще нет приложения, то придумайте название пакета. Например: "ru.fgx.pushnotificationdemo".

    9. Нажмите кнопку "Register app".
    10. Скачиваем конфигурационный файл "GoogleService-Info.plist", нажав на кнопку "Download" и сохраняем файл в папку FGX Native проекта (можно сохранить в любое другое место). Этот файл содержит настройки для инициализации FGX Native приложения на iOS.
    14. Заканчиваем добавление вашего приложения путем нажатия кнопок "Next" -> "Next" -> "Continue to console"
    15. Теперь вы увидите ваше iOS приложение на главной странице.

    Теперь необходимо выполнить настройку FGX Native приложения в IDE.
    Настройка приложения
    1. Откройте существующий проект или создайте новый.
    Если вы создаете новый проект, то в мастере создания проекта обязательно укажите (на основании шага 8 регистрации приложения в Firebase):
    Идентификатор организации. Например: "ru.fgx".
    Имя проекта. Например: "pushnotificationdemo".
    Если открываете существующий, то убедитесь, что название пакета в Project -> Options... -> Version Info >  CFBundleIdentifier " соответствует названию из шага 8.
    2. Откройте: "Главное меню" -> "Project ->  Deployment".
    2.1. В выпадающем списке конфигурации выберите "All Configurations -> iOS-Device 64-bit platform".
    Примечание: Если вы хотите разделять настройки для разных конфигураций, выберете соответствующую конфигурацию.    
    2.2. Добавьте ранее скаченный файл настроек "GoogleService-Info.plist" (на основании шага 10 регистрации приложения в Firebase).

    Примечание: Если этого не сделать, то при старте приложение упадет.
    3. Сохраните изменения.
    4. Откройте главную форму вашего приложения и подключите модуль FGX.PushNotification.FCM. 
    Примечание: FGX Native использует Firebase по умолчанию на Android. Однако, на iOS мы используем Apple Push Service по умолчанию. Поэтому Firebase библиотека не линкуется по умолчанию. По этому важно подключить данный модуль. 
    5. Добавьте на форму компонент TfgPushNotificationService и укажите "ServiceNamne = FCM".
    Минимально необходимая настройка вашего приложения для получения пуш уведомлений выполнена. Если приложение будет свернуто или выгружено из памяти, то при отправке push-уведомление отобразиться в центре уведомлений устройства. Если же приложение активно, то пуш уведомление не будет попадать в центр уведомления устройства.
    Получение токена устройства
    При первом старте приложения, оно выполняет свою регистрацию в облаке Firebase. При этом облако выдает устройству уникальный токен DeviceToken. Перед тем, как отправить тестовое уведомление, необходимо узнать токен устройства. Для получения токена устройства нужно написать обработчик события "TfgPushNotificationService.OnDeviceTokenChanged". Данное событие вызывается каждый раз, когда выдается новый токен устройства. Токен устройства может меняться.
    Получив токен, вам необходимо передать его на ваш сервер, отправляющий Push-уведомления для будущих отправок сообщений. 
    В данном примере, мы не будем его сохранять, а выведем в лог устройства.
    procedure TFormMain.PushServiceDeviceTokenChanged(Sender: TObject; const ADeviceToken: string); begin TfgLog.Info('Device token changed: deviceToken="%s"', [ADeviceToken]); end;Получение push-уведомления
    Для получения токена устройства нужно написать обработчик события "TfgPushNotificationService.OnPushNotificationReceived". Данное событие вызывается, когда устройство принимает push-уведомление.
    Примечание: В зависимости от реализации, событие может вызываться в разные моменты времени. Например, если приложение не в памяти или в фоне, то событие вызовется в момент нажатия пользователем на уведомление в Центре локальных уведомлений.
    Пример вывода в лог полученного push-уведомления:
    procedure TFormMain.PushServicePushNotificationReceived(Sender: TObject; const ANotification: TfgPushNotification); begin TfgLog.Info('Notification received: notification="%s"', [ANotification.ToString]); end;Запустите приложение и запомните токен устройства из консоли. 
    О том, как пользоваться Console для просмотра логов устройства, читайте в статье:
    Отправка тестового сообщения
    Чтобы отправить тестовое сообщение на конкретное устройство, можно воспользоваться Firebase консолью.  
    1. Откройте консоль: https://console.firebase.google.com
    2. Перейдите в меню навигации к разделу: "Engage -> Messaging"
    3. Нажмите кнопку "Create your first campaign".
    4. Выберите тип "Firebase Notification Messages".
    4. Заполните данные уведомления. Например так:

    5. Нажмите кнопку "Send test message". Консоль предложит указать на какие устройства необходимо отправить данное уведомление.
    6. Укажите в поле токен устройства (раздел "Получение токена устройства") и нажмите кнопку "+".
    7. Выполните отправку уведомления, путем нажатия на кнопку "Протестировать" и наблюдайте появление вашего уведомления в центре локального уведомления на устройстве:

    Получение данных уведомления при старте приложения
    Если пользователь нажимает на push-уведомление в центре уведомлений, то система запустит ваше приложение. В любой момент времени можно получить данные стартового уведомления напрямую из локального Firebase сервиса (Раздел "Получение Push-уведомлений").
    var Notifications: TArray<TfgPushNotification>; begin Notifications := fgPushNotificationService1.StartupNotifications; end;ВАЖНО!
    Приложение падает на старте и вы используете компоненты FireDAC. (спасибо @Roman)
  3. Данная статья является полной информацией о темах в FGX Native и актуальным руководством, начиная с 1.19.0.0.
    Введение Виды тем Акцентный цвет Системная тема и тема приложения Системная тема Получение параметров системной темы Механизмы отслеживания системной темы Как управлять системной темой в приложении Запрет автоматической смены системной темы в приложении Темная тема Тема FGX Native Цветовая система Material Design Основной цвет Вторичный цвет Цвета поверхности, фона и ошибок Цвета "На" Альтернативные цвета Прочее Генерация темы в FGX Native Применение темы Приложение Форма Принцип смены темы Использование ресурсов темы Типы значений Приоритет Применение ресурсов темы Фиксация темы Расширение темы Пример разработки приложения с поддержкой темной и светлой тем и разных цветовых оттенков. Создание тем в дизайнере ресурсов Настройки тем в проекте Программная смена тем и акцентированного цвета Советы 1. Введение
    Тема — это совокупность настроек, цветов, звуков, шрифтов, курсоров, иконок, фоновых изображений и других элементов, отвечающих за интерфейс приложения.

    1.1 Виды тем
    В современном мире обычно различают два вида тем:
    Светлая тема - преимущественно использует светлые цвета в UI. Темная тема - преимущественно использует темные цвета в UI. Именно эти два вида распространены в Android и iOS. Далее, в каждом виде могут быть уже темы разных цветовых палитр, с разными акцентными цветами и т.д.
    1.2 Акцентный цвет
    Акцентный цвет - это дополнительный цвет, который контрастирует или дополняет основные цвета, используемые в приложения. По умолчанию, в iOS такой цвет голубой, а в Android - изумрудный.
    Вот некоторые задачи, для которых используют акцентные цвета:
    Привлечение внимания. Яркий акцентный цвет привлекает взгляд пользователей и помогает им ориентироваться на странице. Организация информации. Использование акцентного цвета для заголовков и подзаголовков помогает организовать информацию на странице и делает её более понятной для пользователей. Выделение важных элементов. Акцентный цвет помогает выделить важные элементы, такие как акционные предложения или срочные сообщения, и привлечь внимание пользователей к ним. При выборе акцентного цвета часто используют правило 60-30-10: 60% — основной цвет, 30% — акцентный, 10% — второй акцентный цвет, если он имеется.
    1.3 Системная тема и тема приложения
    В дальнейшем, когда мы будем говорить про тему, то мы будем рассматривать два типа тем:
    Системная тема (Обязательная). Это та, которая поставляется вместе с операционной системой и все приложения используют ее по умолчанию. Тема приложения (Необязательная). Это та, которая поставляется вместе с приложением и предназначена для переопределения системной темы. 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); Допускает три варианта значений:
    Light - приложение использует светлую тему. Dark - приложение использует темную тему. 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) цвета для представления вашего бренда. Затем на основании этих двух цветов строятся все остальные цвета, включая темные и светлые варианты каждого цвета.
    Базовая цветовая тема состоит из следующих цветов:
    Первичный/Основной (Primary) и вторичный (Secondary) цвета. Варианты основных и дополнительных цветов (Primary Varian, Secondary Variant). Эти цвета в FGX Native имеют следующие названия:   "Primary\Dark Primary", "Secondary\Dark Primary" - Темный вариант основного и вторичного цветов "Primary\Light Primary", "Secondary\Light Primary" - Светлый вариант основного и вторичного цветов Дополнительные цвета пользовательского интерфейса, такие как цвета фона, поверхностей, ошибок, типографики и иконок.
    3.1.1. Основной цвет
    Это цвет, который чаще всего отображается на экранах и в компонентах вашего приложения. Он же используется как акцентированный цвет для многих компонентов.

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

    3.1.2 Вторичный цвет
    Вторичный цвет обеспечивает больше возможностей для акцентирования и выделения вашего продукта. Наличие вторичного цвета необязательно и должно применяться умеренно для акцентирования выбранных частей вашего пользовательского интерфейса.
    Если у вас нет вторичного цвета, основной цвет также можно использовать для акцентирования элементов.
    Вторичные цвета лучше всего подходят для:
    Плавающие кнопки действий Элементы управления выбором, такие как ползунки и переключатели Выделение выделенного текста Индикаторы прогресса Ссылки и заголовки Как и основной цвет, ваш вторичный цвет может иметь темные и светлые варианты. Цветовая тема может использовать ваш основной цвет, вторичный цвет и темные и светлые варианты каждого цвета.
    3.1.3 Цвета поверхности / фона и ошибок
    Цвета поверхности, фона и ошибок обычно не представляют бренд и не зависят от основного и вторичного цветов. Однако, именно они и добавляют визуального порядка в пользовательском интерфейсе:
    Цвета поверхности (Surface) влияют на поверхности компонентов, таких как карточки TfgForm / TfgCardPanel / TfgBottomSheetLayout / TfgDrawerLayout, списки TfgCollectionView/TfgListMenu и меню. Цвет фона (Background) отображается за прокручиваемым содержимым. Базовый фон и цвет поверхности — #FFFFFF. Цвет ошибки (Error) указывает на ошибки в компонентах, такие как недопустимый текст в текстовом поле. Базовый цвет ошибки — #B00020.
    Если попробовать упростить эту модель и перенести ее на компоненты FGX Native, то можно выделить основные правила использования:
    Background обычно используется, как самый задний цвет контейнера верхнего уровня. Например, TfgForm. Surface используется, как цвет заднего фона для контейнеров, которые лежат на контейнере с фоном Background. Чаще всего это TfgCardPanel, TfgBottomSheetLayout
    3.1.4 Цвета На/On
    Поверхности приложений используют цвета из определенных категорий в вашей цветовой палитре, например, основной цвет. Всякий раз, когда элементы, такие как текст или иконки, появляются перед этими поверхностями, эти элементы должны использовать цвета, разработанные так, чтобы быть четкими и разборчивыми по сравнению с цветами позади них.
    Эта категория цветов называется «На/On» цветами, ссылаясь на тот факт, что они окрашивают элементы, которые появляются «на» поверх поверхностей и используют следующие цвета: основной цвет, вторичный цвет, цвет поверхности, фоновый цвет или цвет ошибки. Когда цвет появляется «на» поверх основного цвета, он называется «над основным цветом». Они маркируются с использованием исходной цветовой категории (например, основной цвет) с префиксом «On».
    «On» цвета применяются в основном к тексту, иконографии и штрихам. Иногда они применяются к поверхностям.

    Такие цвета есть для всех цветов: основного, вторичного, поверхности, фона и ошибок цветов. В FGX Native такой набор состоит из 6 цветов:
    Text - основной цвет текст.  Secondary Text - цвет дополнительного текста. Используется для выделения второстепенной текстовой информации, как примечание, подзаголовок и тд. Icon - цветовой оттенок иконок, отображаемых на текущем цвете. Dividers - цвет полосок разделителей. Например, полоса-разделитель элементов в списке TfgCollectionView. Hint Text - цвет текста для подсказки ввода текста в поля ввода (TextPrompt) Disabled Text - текст на компонентах, не доступных для взаимодействия. Пример ниже иллюстрирует ручное применение цветов темы для элементов кнопки. Если кнопка использует основной цвет "Primary", как фон. То, соответственно, иконка и текста должны использовать цвета из группы цветов "On Primary"

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

    3.1.6 Прочее
    Об остальных вариантах использования цветов и правил их применения следует обратиться к официальной документации.
    Официальная документация 3.2 Генерация темы FGX Native
    Для того, чтобы добавить тему буквально в один клик, мы предлагаем генератор темы в дизайнере ресурсов (Project -> FGX Assets Manager). Он доступен либо в контекстном меню дерева ресурсов "Сгенерировать тему" , либо через соответствующую иконку на панели инструментов.

    В самом верху окна вам необходимо выбрать тип темы. Здесь все просто: "светлая" или "темная".
    Затем выбираете два базовых цвета: Основной Primary/P и Вторичный Secondary/S цвета. Левой кнопкой мыши выбирается основной цвет P, а правой - вторичный S.
    При выборе основных цветов, генератор автоматически определяет оттенок группы цветов "On" используемой на каждом из двух цветов. При необходимости вы можете откорректировать группы при помощи радиокнопок внизу. Если основной цвет яркий, то для соблюдения контраста, все элемента отображаемые На ярком цвете, должны быть темными и наоборот. После нажатия на кнопку "Сгенерировать", мы получаем наборы цветом согласно системе цветов Material Design.

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

    Обратите внимание, что если вы хотите использовать темы вашем приложении, то вам как минимум надо сгенерировать светлую тем, а максимум, добавить еще и темную.
    3.3 Применение темы
    В FGX Native тема может применяться на двух уровнях:
    Приложение Форма 3.3.1 Приложение
    Тема, применяемая на уровне приложения автоматически применяется ко всем формам и ко всем компонентам. Кроме случаев, о которых будет сказано далее. 
    Тема может быть задана двумя способами.
    1. На уровне настроек проекта (DesignTime) с 1.19.0.0: Этот основной способ и он позволяет применить тему, как в дизайнере, так и автоматически на старте приложения на устройстве.
    Чтобы задать тему на уровне приложения, нужно зайти в настройки проекта Project -> FGX Options... -> Приложение -> Темы

    В поле (1) мы можем указать способ выбора темы при старте приложения. Доступны три варианта:
    Согласно системной теме. Если на устройстве используется светлая тема, то будет использоваться светлая тема в приложении, если же в системе используется темная, то в приложении автоматически будет применена темная тема Светлая - Независимо от системной темы, внутри приложения будет использовать светлая тема.  Темная - Независимо от системной темы, внутри приложения будет использовать темная тема.  В поле (2) указываем название светлой FGX Native темы из дизайнера ресурсов. Если вы использовали нашу рекомендацию по группировке и именованию тем, то это может быть "Themes\Light\Green" (Светлая тема с зеленым основным цветов).
    В поле (3) включаем или отключаем поддержку темной темы в приложении. Возможно, ваш дизайн приложения не предусматривает темную тему или у вас ее нет. В этом случае, необходимо убедиться, что галка с этого поля снята.
    В поле (4) указываем название темной темы из дизайнера ресурсов (если включена поддержка темной темы).
    В момент старта приложения FGX Native применяет тему согласно вашим настройкам. Например, вот так:
     
    В режиме выполнения (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:

    В этом случае все вложенные компоненты будут автоматически использовать тему формы, а не приложения.
    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 дает возможность поменять цвет фона, рамки, текста, перекрасить иконку и т.д.

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

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

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

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

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

    3.4.2 Приоритеты
    Большинство цветовых свойств компонентов FGX Native присутствует в двух вариантах:
    С постфиксом "Name": TintColorName, ColorName Без постфикса "Name": TintColor, Color Если вы видите такие парные свойства, значит они оба отвечают за настройку одной характеристики внешнего вида компонента. Приоритет у таких свойств следующий в порядке убывания и наличия: 
    Указанное вручную название ресурса цвета. Указанное название ресурса цвета из темы по умолчанию. Значение цвета из свойства Color, TintColor и т.д. Значение цвета из системной темы (определяется каждым компонентов самостоятельно реализацией). Данное дублирование появилось с самого начала разработки 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" 
     
    При смене темы формы или приложения, все свойства, которые используют имена ресурсов с указанием темы с ":" будут автоматически обновлены на использование новой темы. 
    3.4.4 Фиксация ресурса цвета
    Возможны ситуации, когда необходимо использовать цвет из темы, но без автоматического обновления. Например, вы сделали несколько тем с разными акцентными цветами, и хотите их отобразить на форме. В таком случае, не нужно использовать ":", как разделитель ресурсов, а использовать "\". Тогда при смене темы такие значения не будут изменены.

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

    В данном проекте нет никакого использования ресурсов, а так же нет никаких тем.
    Перед нами стоят следующие задачи:
    Добавить поддержку темной и светлой тем. Добавить возможность переключать темы вручную. Добавить возможность переключать темы автоматически согласно настройкам системной темы на устройстве. Добавить возможность менять акцентированный цвет. В примере рассмотрим два цвета: зеленый и синий. На практике как цвета, так и их количество может быть любым. 4.1 Создание тем в дизайнере ресурсов
    Добавление поддержки тем начинается с создания темы в дизайнере ресурсов. У нас должно быть два вида тем:
    Светлая Темная А так же два вида акцентированного (Primary) цвета для каждого вида тем:
    Зеленый Синий. В результате у нас должно получиться 4 темы. Для удобства организации тем в дизайнере ресурсов я решил использовать такую группировку:
    Первый уровень - Themes, сюда складываем все виды тем. Второй уровень - Dark/Light - группировка всех тем по виду. Третий уровень - Green/Blue акцентированный цвет. Открываем дизайнер ресурсов Project -> FGX Assets Manager.
    Создаем такую структуру.

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

    4.2 Настройки тем в проекте
    Наши FGX Native темы готовы, теперь сохраняем изменения и переходим к настройке тем в проекте. Для этого открываем настройки проекта Project -> FGX Options...-> Приложение -> Темы.
    Выбираем конфигурацию "All Configurations - All platforms", чтобы наши настройки тем применились для всех платформ и конфигураций. Пусть при старте у нас будет использоваться такая же тема, как и в системе. Для этого в "Используемая тема при старте" (2) выбираем "Согласно системной теме" В поле "название светлой темы" (3) указываем одну из двух наших светлых тем. Будем считать, что зеленый акцентированный цвет будет использоваться по умолчанию. Поэтому указываем соответствующую светлую тему: "Themes\Light\Green" Включаем поддержку темной темы в приложении (4).  В поле "название темной темы" (5) указываем соответствующую темную тему: "Themes\Dark\Green"
    Теперь при старте нашего приложения, приложение автоматически получит тему с зеленым акцентированным цветом соответствующего типа. Запускаем и проверяем. При старте в системе установлена светлая тема, она же и применилась в приложении. Меняем системную тему на темную при помощи панели управления Android или iOS и приложение автоматически меняет ее на темную.
     
    Как вы можете видеть, компоненты уже адаптированы и заточены на использование тем FGX Native, поэтому в данном случае мы не выполняли никакой ручной настройки компонентов.
    Половина дела уже сделана. Добавлена поддержка двух тем с автоматической синхронизацией с системной темой. Теперь необходимо добавить возможность ручного управления темами и акцентированным цветом. 
    4.3 Программная смена тем и акцентированного цвета
    Чтобы пользователь мог менять тему в приложении по своему усмотрению, создадим такую панель управления, выдвигаемую снизу экрана. Для этого используем TfgRadioButton и TfgBottomSheetLayout.

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

    Задаем группы (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. И формируем новое название тем.
    Проверяем. Запускаем наше приложение.
    video_2025-03-28_04-12-07.mp4
    Вот таким незамысловатым способом можно легко добавить поддержку тем в 1.19.0.0.

    5. Советы
    При проектировании интерфейса всегда учитывайте, что у вас должна быть поддержка светлой и темной тем. Лучше сразу добавить в самом начале две базовые темы: светлая и темная с одним из основных цветов. При настройке внешнего вида компонентов, используйте ресурсы из темы, где это необходимо. Это сильно упростит вам дальнейшую настройку внешнего вида приложения и добавление поддержки новых тем.  Вы всегда можете проверить корректность внешнего вида приложения в дизайнере, вручную указав название темы в форме, либо воспользовавшись переключателем вида темы в дизайнере форм. Не используйте зашитые коды цветов прямо в компонентах (свойства Color, TintColor и т.д.), иначе при смене темы, эти цвета останутся без адаптации.  При любом использовании цветов, выносите его в ресурсы. Если вы понимаете, что данный цвет может зависеть от темы, то смело включайте его в состав тем.
  4. Добрый день, 
    В ближайшее время выйдет большой релиз 1.19.0.0, который полностью будет посвящен большим изменения в работе с темами приложения, упростит ваш код и сделает управлением темами удобнее и понятнее.
    Предварительно мы разработали полное руководство по темам:
    Обязательно прочитайте это руководство, потому что в этой теме будет затронута только миграции проектов на 1.19.0.0.
    Внимание: В данном релизе 1.19.0.0 введены изменения, которые ломают совместимость проектов этой версии со старыми версиями. Поэтому переход на 1.19.0.0 является необратимым. Перед тем, как открыть ваш проект необходимо ОБЯЗАТЕЛЬНО сделать резервную копию на случай необходимости временного возврата к предыдущим версиям.
    Новый ресурс - тема
    Не смотря на то, что есть несколько статей о том, как настраивать темы и как их использовать, концепция темы не была до конца закончена. Связано это прежде всего было с тем, что как таковой сущности "тема" в FGX Native не существовало до 1.19.0.0. Это создавало внутренние трудности в реализации FGX Native и требовало использовать не всегда очевидные подходы в определении, что есть тема в FGX Native.
    Вы можете возразить, что понятие темы существует уже много лет. Однако, ответ очень прост. Вы никаким способом не можете определить программно до текущего релиза, названия тем приложения. Именно это и является камнем преткновения.
    Теперь мы ввели полноценное понятие темы. При открытии старого проекта в 1.19.0.0 мигратор автоматически создает сущность темы на основании ваших ресурсов для каждой потенциальной темы.

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

    (1) Сгенерировать тему (по старому способу). Контекстное меню дерева ресурсов -> "Сгенерировать тему".
    (2) Добавить пустую тему. Все ресурсы темы вы должны добавить самостоятельно по вашему усмотрению. Контекстное меню дерева ресурсов -> "Добавить тему".
    В этом случае создается пустая тема без какого-либо ресурса. Все необходимые ресурсы вы должны добавить туда самостоятельно.

    (3) Сконвертировать каталог с ресурсами в тему. Контекстное меню дерева ресурсов -> "Конвертировать в тему".
    Как только тема добавлена в менеджере ресурсов, так сразу вы можете ее использовать ее в вашем приложении. Темы могут располагаться в любом месте, в том числе во вложенных папках.
    Доступ к темам
    На уровне TfgAssetsManager добавлен новый метод, позволяющий получить список тем:
    /// <summary>Возвращает названия всех доступных тем.</summary> function GetThemesNames: TArray<TfgThemeName>;Применение темы
    Теперь тема может быть применена на уровне приложения без необходимости указывать ее на уровне каждой формы. Для этого добавлено новое свойство 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> /// <remarks> /// Если приложение не поддерживает темную тему (Темная тема не включена в настроках проекта), то вид темы /// будет всегда <c>Light</c>. /// </remarks> property ThemeKind: TfgThemeKind read FThemeKind write SetThemeKind;Теперь вы можете указать, чтобы тема автоматически была согласована с системной темой устройства, либо же принудительно применить светлую или темную тему.
    Основным способом указания темы, является появление нового окна настроек Project -> FGX Options... -> Приложение -> Темы

    Помимо задания темы на уровне приложения, вы так же можете указывать ее на уровне формы, если по каким-то причинам, вы хотите использовать другой вариант темы на какой-то форме.
    Использование файла Assets.Consts
    Начиная с 1.19.0.0 изменена логика генерации файла констант с именами ресурсов.
    В этом релизе мы провели унификацию названий полей.
    R.Fonts -> R.Font
    R.Images -> R.Image
    R.LottieAnimations -> R.LottieAnimation
    R.Files -> R.&File
    Так же теперь R.Theme не возвращает ресурсы текущей темы. За это отвечает новое поле R.CurrentTheme, которое возвращает имя ресурса темы в зависимости от теущей темы приложения. Таким образом, вам больше не нужно вручную динамически формировать имя ресурса в зависимости от светлой или темной темы.
    R.Theme теперь выдает доступ ко всем темам приложения.
    TfgCurrentTheme = record /// <summary>Identifiers with current theme colors assets.</summary> class var Color: TfgThemeColors; end; TfgThemes = record class var ThemeDark: TfgThemeThemeDark; class var ThemeLight: TfgThemeThemeLight; end; /// <summary>Identifiers with current theme assets.</summary> class var CurrentTheme: TfgCurrentTheme; /// <summary>Identifiers with themes names.</summary> class var Theme: TfgThemes;Использование ресурсов темы
    Теперь, при использовании ресурсов темы допускается два способа указания имени:
    Адаптированное имя под текущую тему. Если вы хотите, чтобы при смены темы, используемый ресурс так же брался из новой темы, то в качестве разделителя названия темы и ресурса нужно использовать ":".
    Например: "Themes\Light\Green:Background".
    Фиксированное имя. Если вы не хотите изменения названия ресурса темы при смене темы, то используйте старый способ указания имени "Themes\Light\Green\Background".
    Миграция
    Важно: Перед выполнением миграции вашего проекта ОБЯЗАТЕЛЬНО сделать резервную копию проекта, чтобы в случае чего можно было откатиться обратно.
    Чтобы облегчить миграцию ваших проектов для поддержки новых тем, мы разработали мастер, который поможет автоматически выявить все места использования ресурсов тем.
    Мастер:
    Распознает все свойства (из библиотеки), связанные с ресурсами.
    Извлекает текущее значение имени ресурса.
    Для DFM/XFM файлов форм и фреймов проверяет имя ресурса на предмет принадлежности темы - вхождение слова "Theme" (без учета регистра). Если у вас в названии темы не фигурирует слово "Theme", пожалуйста, сообщите в комментариях под этой статьёй.
    Для обнаруженных имен ресурсов (только для XFM) автоматически формирует новое имя с учетом нового синтаксиса и предлагает автоматическую замену . 
    При открытии старого проекта автоматически запускается миграция проекта на новую версию, в рамках чего будет отображен мастер только если в вашем проекте будут найдены потенциальные места использования ресурсов из тем. 

    Важно: Мастер сканирует только файлы добавленные в проект напрямую. Другими словами, все файлы, которые используются в проекте, но не добавлены в него анализироваться не будут.
    Адаптация DFM/XFM файлов
    Если вы не хотите применять предложенное изменение, снимите галку напротив строки с предложенным изменение в левом дереве. Мы применили наш мастер на все демонстрационные проекты, а так же проверили его на наших больших демонстрационных проектах с вебинаров. Ошибок в адаптации найдено не было.
    Допускаем, что какие-то варианты могут быть не учтены, поэтому, важно делать резервные копии. По умолчанию мы создаем копию затрагиваемых оригинальных файлов и добавляем окончание ".backup". Если вы уверены в предложенных изменения, вы можете отключить резервные копии файлов через снятия галки чекбокса в футере окна.
    Адаптация PAS файлов
    Отдельно изучите найденные изменения в PAS файле и выполните адаптацию самостоятельно. Поскольку вариантов формирования имени ресурса из темы большое количество и ограничено только вашей фантазией, мы не можем корректно проанализировать ваш код, но можем предположительно найти только потенциальные места, где идет программное изменение свойств, затрагивающих работу с названием ресурсов.
    Вот несколько советов, которые вам помогут:
    Если вы используете константы из файла Assets.Consts.R, то в этом релизе мы провели унификацию названий полей. Если вы используете программный доступ к этим ресурсам, переименуйте их согласно схеме выше.
    R.Fonts -> R.Font
    R.Images -> R.Image
    R.LottieAnimations -> R.LottieAnimation
    R.Files -> R.&File
    Изменена логика использования R.Theme. Теперь она содержит не ресурсы текущей темы, а все темы приложения, с возможностью получить доступ к ресурсам каждой темы. Если вы используете в проекта R.Theme, вам необходимо его заменить на R.CurrentTheme.
    Важно: Адаптацию pas файлов нужно выполнить самостоятельно.
    TfgControl.UpdateTheme
    В некоторых проектах используется метод TfgControl.UpdateTheme, который был добавлен для временного решения проблемы с применением тем при динамическом встраивании компонентов и фреймов
    В новой версии 1.19.0.0 этого метода больше нет, так как теперь адаптация применения темы выполняется библиотекой самостоятельно. Поэтому вам НЕ ТРЕБУЕТСЯ больше вызывать этот метод. Поэтому удалите использование этого метода из вашего проекта.
    Дизайнер формы
    В этом релизе так же добавлена возможность быстрого переключения тем вашего приложения в дизайнере формы. Таким образом вы можете в одно нажатие посмотреть, как выглядит форма в темной или светлой темах. Для этого воспользуйтесь новыми кнопками переключения темы на панели инструментов в дизайнере формы:

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

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

    Если ресурс применяется из темы, то в его имени используется ":", как разделитель названия темы и ресурса внутри него.
    Помимо этого мы мы добавили ряд небольших изменений в сам дизайнер формы, которые, возможно, вам пригодятся.
    (1) Теперь при выделении компонента, отображается его имя и размер. А при перетаскивании имя теперь не выводится.

    Если вы нехотите, чтобы выводился размер или название. Вы можете отключить это поведение в общих настройках среды: Tools -> Options -> Third Party -> Form Designer

    (2) Добавлена возможность быстрого переключения формы в текстовый режим. Теперь при нажатии на кнопку "Как текст", дизайнер переключиться на режим отображения текста формы.

    (3) Теперь режим отображения сетки, границ компонентов, темы, стиля и тд. синхронизируется между дизайнерами форм. И например отображение сетки в одной форме приводит к отображению сетки на всех формах.
    Заключение
    Если в ходе миграции или проверки ваших приложений на 1.19.0.0 вы столкнулись с трудностями или у вас есть предложения, пожалуйста, дайте нам знать.
  5. Добрый день,
    В скором времени выйдет новое крупное обновление 1.18.14.0, в которое войдет новый функционал, который вам однозначно пригодится. В этой статье рассмотрим новые графические возможности по работе с канвой TfgCanvas.
    Работа с состоянием канвы
    Перед тем, как мы перейдем к новым возможностям, мы обязаны рассмотреть изменения в работе с состоянием канвы. Поскольку эти изменения необходимы для корректной работы с обрезанием изображений по произвольным кривым.
    Напомню, что при работе с канвой TfgCanvas разработчик постоянно меняет ее параметры (настройки кисти, матрицы трансформации и т.д.). Поэтому, очень удобно иметь контрольные точки при отрисовке, к которым можно сбросить состояние канвы, чтобы не устанавливать все настройки заново. Для этих целей используются методы SaveState / RestoreState. Метод SaveState возвращал объект состояния, который в дальнейшем нужно было передавать в парный метод RestoreState для восстановления состояния. В новой версии, объект состояния больше не нужно использовать.
    Было:
    var State: IFGXSaveState; State := ACanvas.SaveState; try // Задаем параметры отрисовки // Выполняем отрисовку finally ACanvas.RestoreState(State); end;Стало:
    ACanvas.SaveState; try // Задаем параметры отрисовки // Выполняем отрисовку finally ACanvas.RestoreState; end;Теперь при вызове SaveState, канва автоматически сохраняет состояние во внутренний стек, а при вызове RestoreState извлекает его из стека и восстанавливает.
    Зачем?
    Первая причина: Раньше мы сохраняли только параметры кистей, параметры шрифта, режим смешивания цветов и матрицу преобразования. Это было обусловленно тем, что мы в любой момент могли самостоятельно задать любые параметры канвы. Однако, в данном релизе добавлена операция накладывания произвольной области отсечения, которая является не обратимой операцией (это значит, что заданную область отсечения нельзя убрать парным методом). Единственный способ, сбросить или откатить заданную область отсечения - это использовать нативный механизм работы с состоянием канвы. В связи с этим, мы перешли от нашей реализации к нативной, которая НЕ предусматривает восстановление к произвольному состоянию.
    Вторая причина: Чаще всего при выполнении последовательной отрисовки, восстановление канвы требуется не на произвольное состояние, а именно на предыдущее состояние.
    { State 1 } ACanvas.SaveState; // Save State 1 { State 2 } try // Задаем параметры отрисовки // Выполняем отрисовку ACanvas.SaveState; // Save State 2 try // Другая вложенная отрисовка finally ACanvas.RestoreState; // Rollback to State 2 end; finally ACanvas.RestoreState; // Rollback to State 1 end;Внимание: Не смотря на то, что старый подход по работе с состоянием сохранился, он может не корректно работать при использовании областей отсечения TfgCanvas.ClipPath.
    Обрезание по пути
    Одна из самых интересных графических возможностей - это ограничение области отрисовки на канве произвольной фигурой или путем. Накладывание ограничения выполняется при помощи нового метода TfgCanvas.ClipPath.
    /// <summary> /// Выполняет накладывание области отсечения будущих команд отрисовки. Чтобы отменить наложенную область ограничения /// необходимо использовать методы <c>SaveState</c> / <c>RestoreState</c>. Перед наложение области сохранить состояние /// канвы, а после завершения работы - восстановить. /// </summary> procedure ClipPath(const APath: TfgPath);Рассмотрим пример, где мы хотим нарисовать два овала красного и синего цветов. Красный обрезать по вписанному овалу в область отрисовки, а синий - не обрезать.

    Тогда код по отрисовке будет выглядить так:
    procedure TFormMain.fgPaintBoxPaint(Sender: TObject; const ACanvas: TfgCanvas); var CirclePath: TfgPath; begin // Сохраняем состояние, чтобы в будущем убрать область отсечения ACanvas.SaveState; CirclePath := TfgPath.Create(nil); try // Формируем область отсечения в виде эллипса, вписанного в область отрисовки. CirclePath.AddArc(fgPaintBox.LocalBounds, 0, 360) .ClosePath; ACanvas.ClipPath(CirclePath); // Рисуем красный круг, он будет обрезан ACanvas.Fill.Kind := TfgBrushKind.Solid; ACanvas.Fill.Color := TAlphaColorRec.Red; ACanvas.FillCircle(TPointF.Create(0, fgPaintBox.Height / 2), fgPaintBox.Height / 2); finally CirclePath.Free; end; // Сбрасываем область отсечения ACanvas.RestoreState; // Рисуем синий круг без ограничений ACanvas.Fill.Color := TAlphaColorRec.Blue; ACanvas.FillCircle(TPointF.Create(fgPaintBox.Width, fgPaintBox.Height / 2), fgPaintBox.Height / 2);Где это может пригодиться? Одной из областей применения может стать динамическая отрисовка изображений, обрезанных по произвольной фигуре. Например, вы хотите вывести фотографии или аватарки пользователей в виде круга или какой-нибудь декоративной рамки. Раньше вы могли использовать для этой цели маски. Для этого вам надо было сформировать изображение маски, и затем выполнить отрисовки битмапа с учетом этой маски. Теперь эта операция может выполняться гораздо проще, быстрее и без использования дополнительной памяти.

    У нас есть изображение, которое мы хотим вывести в круглом варианте и декорировать белым кольцом. Код может выглядить следующим образом. Фотография находится в менеджере ресурсов.
    procedure TFormMain.fgPaintBox1Paint(Sender: TObject; const ACanvas: TfgCanvas); var PhotoBitmap: TfgBitmap; FramePath: TfgPath; FrameBounds: TRectF; begin // Извлекаем изображение if not TfgAssetsManager.Current.TryGetBitmap(R.Bitmap.PHOTO, PhotoBitmap) then Exit; ACanvas.SaveState; try // Формируем круглую форму рамки и рисуем битмап FramePath := TfgPath.Create(nil); try FrameBounds := fgPaintBox1.LocalBounds; FramePath.AddArc(FrameBounds, 0, 360) .ClosePath; ACanvas.ClipPath(FramePath); ACanvas.DrawBitmap(PhotoBitmap, FrameBounds); finally FramePath.Free; end; finally ACanvas.RestoreState; end; // Декорируем белым кольцом ACanvas.Stroke.Thickness := 10; ACanvas.Stroke.Color := TAlphaColorRec.White; ACanvas.DrawCircle(FrameBounds.CenterPoint, FrameBounds.Width / 2 - 10); end;Заполнение пути
    Есть как минимум два способа заливки кривых фигур по пути TfgPath. По умолчанию, в FGX Native использовался способ заливки правой фигуры. Теперь же вы можете выбирать способ заливки и указывать его через свойство TfgCanvas.FillPathRule. Помимо этого, теперь это свойство так же доступно в компоненте TfgSvgPath.

    Детали о двух способах заливки доступны здесь.
    Внимание: Данная настройка пока не поддерживается в дизайнере, так как не поддерживается на уровне FMX, которая используется для реализации в дизайнере.
    Штрихи кисти
    Теперь вы можете использовать свои варианты штрихов при отрисовки кривых. На уровне кисти TfgStrokeBrush доступен новый вид линии - Dash = Custom. Параметры штриха задаются через новый метод TfgStrokeBrush.SetCustomDash.
    procedure TfgStrokeBrush.SetCustomDash(const ADash: TDashArray; const AOffset: Single);ADash - это массив парных значений. Первое - это длина штриха, второе - длина пробела.
    SVG
    В этом релизе расширена поддержка параметров SVG, а именно добавлена поддержка следующих атрибутов: stroke-dasharray, stroke-dashoffset, stroke-linecap, stroke-linejoin, fill-rule.
    Редактор градиента
    Мы добавили дизайнер для управления параметрами градиента. Новое окно доступно через кнопку, встроенную в свойство типа TfgGradient.

    Данный дизайнер позволяет, управлять практически всеми параметрами градиента:
    Добавлять и удалять точки градиента. Чтобы добавить точку, нужно нажать в свободное место на нижнем компоненте с отображением градиента. Чтобы удалить, точку надо утянуть за пределы компонента.
    Менять тип градиента - линейный или радиальный
    Менять направление градиента при помощи точек на правой панели просмотра градиента.
    Сбросить параметры градиента до значений по умолчанию.
    Итог
    В следующей статье нас ждет обзор новой функции перетаскивания компонентов Drag & Drop.
  6. Don't miss it!
    We are happy to share with you our upcoming performances with FGX Native at the large Delphi CodeGear summer camp. We are creating a mobile application with Delphi and FGX Native to control a DIY smart backpack with an LED panel over WiFi. We will show techniques of navigation between the screens of a mobile application. Introducing the concept of LiveData for updating the UI when updating data.
    Title: A smart backpack controlled from a mobile application with FGX Native Presenter: Brovin Yaroslav Scheduled: 22 August: 11:00 AM (CST), 19:00 (MSK) Link: https://www.codegear.com/DevDaysofSummer/
  7. Анонс 1.11.0.0 и TfgPhotoPicker

    В следующем релизе FGX Native 1.11.0.0 будет много новых интересных возможностей, которые безусловно найдут свое место в ваших приложениях. В этой статье поговорим о первой новинке: получение фотографии с камеры или из системной галереи изображений.
    До версии 1.11.0.0 получение фотографии с камеры, было не самой тривиальной задачей. Было два решения, которым обычно пользовались разработчики:
    Использование напрямую камеры и разработка своего решение на базе демонстрационного проекта "Компоненты" -> "TfgCamer" -> "Фотокамера". Несмотря на то, что этот способ рабочий и он дает возможности по кастомизации внешнего вида видеоискателя, зачастую требуется просто получить фотографию от пользователя.  Использование нативного API каждой платформы для отправки запроса на получение фотографии системным приложениям. TfgPhotoPicker
    В этом релизе мы предлагаем кроссплатформенное решение в виде специального типа пикера, используемого для выбора фотографии из системной галереи изображений или снятия фотографии с системной камеры. 
    video_2021-05-12_01-16-46.mp4
    Чтобы отправить запрос на получение фотографии с камеры достаточно написать всего три строчки кода:
    uses FGX.Assets, FGX.Assets.Helpers, FGX.Pickers.Photo; procedure TFormMain.btnTakePhotoFromCameraTap(Sender: TObject); begin TfgPickerPhotoFactory.PickPhotoFromCamera(btnTakePhotoFromCamera, procedure(const AFileName: TFileName) begin TfgAssetsManager.Current.AddBitmapFromFile('Photo', AFileName, True); end); end; Для получения фотографии из галереи:
    procedure TFormMain.btnTakePhotoFromLibraryTap(Sender: TObject); begin TfgPickerPhotoFactory.PickPhotoFromLibrary(btnTakePhotoFromLibrary, procedure(const AFileName: TFileName) begin TfgAssetsManager.Current.AddBitmapFromFile('Photo', AFileName, True); end); end; Запрос отправляет через специальную фабрику FGX.Pickers.TfgPickerPhotoFactory, которая предлагает три метода:
    TfgPickerPhotoFactory = class public /// <summary>Создает и возвращает платформенный пикер получения фотографии для ручной работы.</summary> /// <remarks>Удаление пикера лежит на плечах вызываемого кода.</remarks> class function CreatePicker(const AOwner: TObject): TfgPickerPhoto; /// <summary> /// Иницирует получение фотографии с системного приложения камеры. Фотография возвращается в переданную /// анонимную процедуру <c>AOnDidFinishPickingCallback</c>. /// </summary> /// <remarks> /// Вам не требуется следить за временем жизни возвращаемого пикера. Пикер автоматически удалится после того, /// как он будет закрыт пользователем. /// </remarks> class function PickPhotoFromCamera(const AOwner: TObject; const AOnDidFinishPickingCallback: TfgDidFinishPickingCallback): TfgPickerPhoto; /// <summary> /// Иницирует получение фотографии с системного приложения галереи изображений. Фотография возвращается в /// переданную анонимную процедуру <c>AOnDidFinishPickingCallback</c>. /// </summary> /// <remarks> /// Вам не требуется следить за временем жизни возвращаемого пикера. Пикер автоматически удалится после того, /// как он будет закрыт пользователем. /// </remarks> class function PickPhotoFromLibrary(const AOwner: TObject; const AOnDidFinishPickingCallback: TfgDidFinishPickingCallback): TfgPickerPhoto; end; Второй и третий метод предназначены для быстрого получения фотографии с камеры или из галереи. Первый же метод предназначен для ручной настройки пикера и отлова всех событий (открытие, закрытие, отмена и тд.).
    Внимание! Для корректной работы пикера на платформе Android необходимо в настройках проекта включить опцию:
    Project -> Options... -> Application -> Entitlement List -> Security File Sharing = True. Также мы подготовили демонстрационный проект, который позволит вам попробовать эту возможность самостоятельно: "Компоненты" -> "Пикеры" -> "Получение фотографии".
    Всем хорошей рабочей недели. Следите за будущими анонсами FGX Native 1.11.0.0.
  8. Всем доброго дня!
    Как и обещал ранее, перед релизом 1.4.0.0 выкладываю инструкцию о миграции использования старого Android-Delphi моста на новый в 1.4.0.0. Это руководство актуально тем разработчикам, которые используют Android Api в своих проектах. В этой статье я рассмотрю только те аспекты в работе моста, которые изменились.
    По большей части изменения были необходимы только в свете поддержки RAD Studio 10.4, в которой была полностью удалена поддержка модели памяти ARC.
    1. Создание Java объекта:
    Было:
    var Intent: TJIntent; Intent := TJIntent.Create; Стало: 
    var Intent: JIntent; Intent := TJIntent.Create; Все объявления переменных, атрибутов и тд должны быть теперь именованы без префикса "T". TJActivity -> JActivity.
    2. Передача Java объектов через Java интерфейс:
    Было:
    // Декларация метода. Принимает атрибут интерфейсного типа CharSequence. TJTextView.setError(const AArg0: JCharSequence); // Java cтрока TJString реализует интерфейс JCharSequence. Поэтому передача идет напрямую (в старой версии моста). View.setError(StringToJString(Control.Error)); Стало:
    // Декларация метода. Принимает атрибут интерфейсного типа CharSequence. TJTextView.setError(const AArg0: JCharSequence); // Теперь обертка Java cтроки TJString НЕ реализует явно интерфейс JCharSequence. Поэтому необходима явная конвертация JString -> JCharSequence View.setError(TJCharSequence.Wrap(StringToJString(Control.Error))); // Или можно воспользоваться хелпером из FGX.Helpers.Android.pas View.setError(StringToJCharSequence(Control.Error)); 3. Работа с Java массивами:
    При создании экземпляра Java массива (TJavaArray<T>) вся работа теперь осуществляется через интерфейс IJavaArray<T>.
    Было:
    var Points: TJavaArray<Single>; Points := TJavaArray<Single>.Create(0); FCanvas.drawLines(Points, FStroke); Стало:
    var Points: IJavaArray<Single>; Points := TJavaArray<Single>.Create(0); FCanvas.drawLines(Points, FStroke); 4. Работа с Java-листенерами:
    Если вы реализовывали свои листенеры через наследование класса Java.Bridge.TJavaLocal, то в 1.4.0.0 листенеры теперь поддерживают счетчик ссылок через Delphi IInterface. Это значит, что при создании листенера, его необходимо сохранять в переменную/поле интерфейсного типа, а не объектного.
    Было:
    TfgAndroidCameraStateListener = class(TJavaLocal, JCameraStateListener) private [Weak] FCamera: TfgAndroidCamera; public constructor Create(const ACamera: TfgAndroidCamera); { JCameraStateListener } procedure onClosed(const AArg0: JCameraDevice); procedure onDisconnected(const cameraDevice: JCameraDevice); procedure onError(const cameraDevice: JCameraDevice; const errorCode: Integer); procedure onOpened(const cameraDevice: JCameraDevice); end; var FStateListener: TfgAndroidCameraStateListener FStateListener := TfgAndroidCameraStateListener.Create(Self); FStateCallback.setListener(FStateListener); Стало:
    TfgAndroidCameraStateListener = class(TJavaLocal, JCameraStateListener) private [Weak] FCamera: TfgAndroidCamera; public constructor Create(const ACamera: TfgAndroidCamera); { JCameraStateListener } procedure onClosed(const AArg0: JCameraDevice); procedure onDisconnected(const cameraDevice: JCameraDevice); procedure onError(const cameraDevice: JCameraDevice; const errorCode: Integer); procedure onOpened(const cameraDevice: JCameraDevice); end; var FStateListener: JCameraStateListener FStateListener := TfgAndroidCameraStateListener.Create(Self); FStateCallback.setListener(FStateListener); В противном случае, экземпляр листенера FStateListener будет удален сразу же после вызова 
    FStateCallback.setListener(FStateListener); Что в свою очередь приведет к последующим падения приложения. Так как сработает механизм подсчета ссылок Delphi интерфейсов. 
    5. Конвертация string <-> JString:
    До RAD Studio 10.4 мобильные компиляторы поддерживали добавление операторов неявного преобразования. Это в свою очередь позволило нам реализовать автоматическую конвертацию "на лету" Delphi string <-> Java JString. В 10.4 эту возможность убрали вместе с ARC, так как неявное преобразование реализуется через ARC. Поэтому теперь нужно явно вызывать преобразование строк через StringToJString и JStringToString:
    Было:
    TjUri.parse('tel:+'); Стало:
    uses FGX.Helpers.Android; TJUri.parse(StringToJString('tel:+')) Это все изменения, которые необходимо сделать.
  9. Black Friday 2024 sales up to 30%

    Hello Delphi developers,
    Black Friday is very soon and we want to please you with a good discount on new FGX Native licenses, which will be valid between 11-15 November 2024.
    Discount for English version - 150$. When placing an order, use the promo code BLACKFRIDAY2024 here. Discount for Russian version - 2000₽. When placing an order, use the promo code BLACKFRIDAY2024 here. Thank you and have a good shopping,
    FGX Native team
  10. Улучшения TfgToast

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

    В FGX Native данное уведомление представлено классом FGX.Toasts.TfgToast, позволяющим его отобразить на экране. В релизе 1.9.2.0 мы реализовали тосты для iOS, а так же выполнили ряд улучшений в архитектуре управления TfgToast, сделав ее такой же единообразной, как и в диалогах, пикерах и других сервисах.
    Новая архитектура
    Теперь вся работа по созданию TfgToast отведена фабрике TfgToastFactory. Через нее можно, как создать экземпляр уведомления для ручной настройки, так и просто отобразить уведомление.
    Быстро отобразить уведомление можно теперь так:
    TfgToastFactory.Show('Hello world!'); Было:
    TfgToast.Show('Hello world!'); Если вы хотите по какой-то причине вручную управлять уведомлением, вы можете его создать через метод:
    Toast := TfgToastFactory.CreateToast; Было:
    Toast := TfgToast.Create('Hello world!'); Однако, в этом случае, уничтожение уведомление лежит на ваших плечах.
    Обратная совместимость
    Мы временно оставили старые методы по отображению тостов. Однако, рекомендуем вам, по возможности перейти на новый вариант использования тостов через TfgToastFactory. Поскольку старый способы могли вводить разработчиков в заблуждение, так как метод TfgToast.Create совпадает по смыслу с конструктором, однако, им не является.
  11. Добрый день, уважаемые разработчики. 
    FGX Native содержит большое количество разнообразных компонентов: начиная от визуальных компонентов, составляющих основу для создания UI вашего приложения, продолжая невизуальными компонентами, облегчающими отслеживание состояния вашего приложения  и заканчивая компонентами-интеграциями с различными сервисами. И если использование первых двух - не зависит от внешних сервисов, то третья - как раз часто требует настройки и более точной интеграции на стороне приложения.
    Так, например, при желании подключить Push-уведомления, вам нужно выбрать провайдера, выполнить первичную настройку на стороне сервиса и затем выполнить настройку клиента (FGX Native приложения). А при использовании Facebook аутентификации уже требуется гораздо больше действия, включая ручное подключение Android библиотек, добавление в деплой новых файлов, правку манифеста и тд.
    Отдельно стоит упомянуть про необходимость настроить приложение в целом: поменять заставку, настроить иконки и базовые цвета и так далее. Все это требует не столько кодирования, сколько внесения и размещения нужных значений параметров в манифесты и файлы настроек. К сожалению, эта часть настроек осуществляется при помощи штатного окна настройки проекта Project -> Options. И поскольку мы не имеем возможности его как-то модифицировать, то мы не можем добавлять туда новые настройки и адаптировать логику. 
    Именно по этой причине в этом релизе 1.18.0.0 нас ждет новое окно настроек проекта.

    Однако стоит обратить внимание, что просто новое окно настроек не имеет смысла без интеграции процесса сборки MSBuild. Так как введенные параметры и настройки нужно передавать и упаковывать в собираемого приложение.  В течении несколько месяцев мы разрабатывали базовый механизм для создания расширяемого окна настроек. Основная идея - это добавление любых страниц настроек и внедрение в систему сборки MSBuild для любых сторонних сервисов. В рамках разработки мы написали несколько расширений для MSBuild, чтобы в будущем проект можно было собрать полностью с командной строки. Процесс перевода в пользу сборки целиком с помощью MSBuild еще не завершен полностью, но мы движемся в этом направлении.
    В этой статье мы не будем разбирать API для сторонних разработчиков, которое они могут использовать для регистрации своих настроек, а сосредоточимся на утилитарном использовании.
    Анимированная заставка Android
    Первым главным нововведением нового окна настроек являются анимированные заставки для Android 12+. 
    https://developer.android.com/develop/ui/views/launch/splash-screen Начиная с Android 12+ структура заставок изменилась и теперь появилась возможность использовать современные анимированные заставки. Раньше была статья, которая описывала детально ручные правки, которые можно было внести 
    Сейчас достаточно включить опцию и настроить внешний вид заставки. Описание параметров смотрите в официальной документации Андроида.

    Eсли ваше приложение запускается на устройствах с Android 12+ будет использоваться анимированная заставка, на старых версиях Android, будет использоваться статическая заставка.

    Добавлен новый пример: "Android Api" -> "Анимированная заставка"
    Примечание: Настройки статической версии заставки пока находятся в старом окне настроек. По мере возможности мы будем переносить значимые для нас настройки из старого окна настроек проекта в новое.
    Google Maps
     
    Было: Раньше ключ карты указывался в стандартном окне настроек проекта в разделе VersionInfo. Помимо этого необходимо было включить поддержку карт в разделе "Entitlements List" -> "Maps Service".
    Стало: Теперь включение сервиса карт и API ключ указываются в разделе "Сервисы" -> "Google Maps".
    Что нужно сделать: Дополнительных действий не требуется. При открытии проекта в этой версии ключ будет автоматически перенесен. Однако, после этого ключ надо менять только в новом окне настроек.
    Facebook Login

    Было: Раньше при использовании "Facebook Login" необходимо было вручную вносить настройки Facebook Login в файлы "strings.xml" и "info.plist.TemplateiOS.xml". Так же требовалось вручную добавлять зависимость на Android библиотеку и править Android манифест.
    Стало: Достаточно включить сервис в новых настройках "Сервисы" -> "Аутентификация" -> "Facebook Login" и указать требуемые параметры.
    Что нужно сделать: Если вы уже используете Facebook Login, то вы либо можете оставить все, как есть. Либо же перейти на новую настройку. Для этого нужно откатить все изменения сделанные в статьях:
    Сервисы аутентификации. Аутентификация с помощью Facebook Login (Android) Сервисы аутентификации. Аутентификация с помощью Facebook Login (iOS). И выполнить включение и ввод настроек в новом окне.
    VK Login

    Было: Раньше при использовании "VK Login" необходимо было вручную вносить настройки в файл "info.plist.TemplateiOS.xml".
    Стало: Достаточно включить сервис в новых настройках "Сервисы" -> "Аутентификация" -> "VK Login" и указать требуемые параметры.
    Что нужно сделать: Если вы уже используете VK Login, то вы либо можете оставить все, как есть, либо же перейти на новую настройку. Для этого нужно откатить все изменения сделанные в статьях:
    Сервисы аутентификации. Аутентификация с помощью VK Login (iOS) И выполнить включение и ввод настроек в новом окне.
    Заключение
    В следующих релизах мы будем переносить значимые параметры - такие как настройки Push-уведомлений, реклама, аналитика и тд.
  12. Christmas sales up to 25%

    Hello Delphi developers,
    In honor of the New Year and Christmas, we are pleased to offer our future customers discounts on the purchase of FGX Native licenses, which will be valid until 15 January 2023.
    Discount for English version - 100$. When placing an order, use the promo code HAPPY2023 here. Discount for Russian version - 1500₽. Also we are anounncing 6 and 12 months subscriptions for Russian version. You can read the rates here. Thank you and happy holidays
  13. Black Friday sales up to 30%

    Hello Delphi developers,
    Black Friday is very soon and we want to please you with a good discount on new FGX Native licenses, which will be valid between 11-15 November 2023.
    Discount for English version - 150$. When placing an order, use the promo code BLACKFRIDAY2023 here. Discount for Russian version - 2000₽. Thank you and have a good shopping,
    FGX Native team
  14. Добрый день, уважаемые разработчики. 
    Скоро выйдет новое крупное обновление 1.16.0.0, которое содержит ряд новых компонентов, серию улучшений и исправление ошибок. Одним из новых компонентов станет интерактивный выбор прямоугольной области, который может использоваться для обрезания изображения. 
    Компонент представляет собой слой, который можно наложить поверх редактируемого объекта. Например, TfgImage.  Для удобства расположения, можно воспользоваться якорями FlexBox - свойство RelativePosition.

    При помощи точек выделения можно интерактивным путем расширить регион. А получить или указать его координаты можно при помощи свойства TfgRegionPicker.Region. При интерактивном изменении области вызывается событие OnChanged. 
    При первом отображении компонента можно отцентрировать регион при помощи свойства RegionOptions.DefaultPlacement. 
    Настройки внешнего вида
    Компонент предлагает набор настроек, позволяющие настроить отображение отдельных элементов компонента, таких как:
    Точки выделения (Appearance.Grip). Здесь можно поменять размер точек и параметры кистей заливки и контура.
    Регион (Appearance.Region). Здесь можно поменять параметры отрисовки пунктирной рамки области выделения. Затемнение вне региона (ContentShading). По умолчанию все, что вне области выделения затемняется. Это настраивается этим свойством. Можно указать базовый цвет затемнения и ее прозрачность.
    Кадрирование
    В релизе 1.16.0.0 добавлены новые метод, позволяющие легко выполнить базовые преобразования. К одному из таких методов относится кадрирование битмапа по области TfgBitmap.CreateCropped (Чтобы воспользоваться методом нужно подключить модуль FGX.Bitmap.Helpers). Ниже представлен пример кода, выполняющий кадрирование изображения на основании координат региона, полученных от TfgRegionPicker. Пример доступен в разделе "Компоненты" -> "TfgRegionPicker" -> "Обрезание фотографии":
    procedure TFormMain.btnCropTap(Sender: TObject); var Region: TRectF; AssetBitmap: TfgAssetBitmapSet; Bitmap: TfgBitmap; CroppedBitmap: TfgBitmap; CroppedRect: TRectF; Scale: Single; DestRect: TRectF; begin Region := rpCropRegion.Region.ToRectF; if TfgAssetsManager.Current.Find<TfgAssetBitmapSet>(R.Bitmap.PHOTO, AssetBitmap) and AssetBitmap.FindBitmap(Bitmap) then begin // Вычисляем область вывода битмапа в контроле. DestRect := TRectF.Create(FBitmap.Bounds).FitInto(pbOriginal.Bounds, Scale); // Корректируем положение региона. Region.Offset(-DestRect.TopLeft); // Масштабируем область согласно физическому размеру битмапа. CroppedRect.TopLeft := Region.TopLeft * Scale; CroppedRect.BottomRight := Region.BottomRight * Scale; // Кадрируем исходный битмап CroppedBitmap := Bitmap.CreateCropped(CroppedRect.Truncate); TfgAssetsManager.Current.AddBitmap('Cropped Image', CroppedBitmap); end; end; Результат работы представлен на видео ниже:
    TfgRegionPicker-demo.mp4
    Спасибо за внимание.
  15. Добрый день, уважаемые разработчики. 
    Продолжаем обзор новых возможностей 1.16.0.0 и в этой статье поговорим об улучшениях связанных с изображениями.
    В этом релизе мы добавили вспомогательные методы для решения часто встречаемых задач: таких как кадрирование, превью, изменение размера, повороты и перекрашивание. 
    Для того, чтобы воспользоваться методами необходимо подключить модуль "FGX.Bitmap.Helpers" в секцию uses. 
    Кадрирование - Crop
    Данные методы позволяют вырезать из исходного битмапа указанную область.
    Предлагается два метода:
    CreateCropped - создает новый экземпляр битмапа, не изменяя исходный Crop - модифицирует исходный экземпляр битмапа. /// <summary> /// Создает новое изображение сформированное из указанной области. <c>ARegion</c> - физические координаты области. /// </summary> function CreateCropped(const ARegion: TRect): TfgBitmap; /// <summary>Выполняет вырезание указанной области изображения. <c>ARegion</c> - физические координаты области.</summary> /// <remarks> /// <para> /// Если координаты области <c>ARegion</c> выходят за пределы физического размера изоюбражения, то они отсекаются /// по размеру изображения. /// </para> /// <para> /// Если результирующая область имеет нулевой размер, то текущий битмап принимает нулевой размер. /// </para> /// </remarks> procedure Crop(const ARegion: TRect); Повороты - Rotate
    Методы поворота позволяют повернуть изображение на углы (90 - 180 - 270) градусов.
    Предлагается два метода:
    CreateRotated - создает новый экземпляр битмапа, не изменяя исходный Rotate - модифицирует исходный экземпляр битмапа и выполняет поворот. /// <summary>Созадет новое изоюражение и поворачивает его на указанный угол.</summary> function CreateRotated(const AAngle: TfgRotation): TfgBitmap; /// <summary>Поворачивает изображение на указанный угол.</summary> procedure Rotate(const AAngle: TfgRotation); Отражение - Flip
    Два метода по симметричному отражению исходного экземпляра битмапа относительно вертикальной и горизонтальной осей.
    /// <summary>Симметричное отражение изображения по горизонтальной оси.</summary> procedure FlipHorizontal; /// <summary>Симметричное отражение изображения по вертикальной оси.</summary> procedure FlipVertical; Создание превью - Thumbnail
    Очень часто требуется получить из исходного битмапа большого размера превью ограниченного размера. Для этого мы предлагаем метод:
    /// <summary> /// Создает миниатюрное изображение, которое может использовать в виде превью. Изображение вписывается в /// указанный размер с сохранение пропорций и центрируется. /// </summary> /// <remarks>Если передается нулевой размер, то метод поднимает исключение.</remarks> function CreateThumbnail(const ASize: TSize): TfgBitmap; Перекрашивание - Tint
    Методы по перекрашиванию исходного экземпляра изображения в указанный цвет.
    Предлагается два метода:
    CreateTinted - создает новый экземпляр битмапа, не изменяя исходный ApplyTintColor - модифицирует исходный экземпляр битмапа и выполняет поворот. /// <summary>Создает новое изображение и применяет указанный оттенок.</summary> function CreateTinted(const ATintColor: TAlphaColor): TfgBitmap; /// <summary>Задает оттенок изображения. Операция не отменяемая.</summary> procedure ApplyTintColor(const ATintColor: TAlphaColor); Мета информация EXIF
    Помимо вспомогательных методов по трансформации битмапов зачастую требуется выполнить нормализацию угла поворота изображения. Когда пользователь делает снимок с камеры, то камера сохраняет файл в ориентации фото сенсора, который не обязательно совпадает с текущей ориентаций экрана. Дополнительно, камера используя мета информацию EXIF помещает в нее ориентацию съемки фотографии. Поэтому при попытке загрузить такое изображение в FGX Native битмап будет отображаться в ориентации съемки с сенсора. Для того, чтобы выполнить коррекцию угла поворота для отображения мы предлагаем новое API для извлечения EXIF информации из файла. Типовой пример использования может выглядеть так:
    uses FGX.Exif; var Properties: TfgExifProperties; if TfgExif.TryLoad(AFileName, Properties) then begin // Properties.Rotation; // Properties.Rotation.ToRotation - возвращает TfgRotation, который можно передать в метод TfgBitmap.Rotate. end; На текущий момент мы извлекаем только ориентацию. Но если вам требуются получать дополнительную EXIF информацию, дайте знать, мы добавим.
    Уверены данные нововведения позволят вам сократить ваш код.
    Спасибо за внимание
  16. Добрый день, уважаемые пользователи FGX Native!
    Вот мы и подошли к главной ключевой новинке версии FGX Native 1.15.0.0, а именно речь пойдет о новой системе сборки для Android приложений 🔥. Долгое время мы шли к этому решению и уверены, что данная система сборки является ключевым нововведением для всех будущих релизов FGX Native. Это огромный шаг и потенциал для мобильной разработки на Delphi.
    Перед тем, как окунуться в детали новинки, настоятельно рекомендуем ознакомиться с нашей статьей о миграции на AndroidX, в которой мы частично описали текущие проблемы, которые стоят за штатной системой сборки Delphi.
    Что не так со стандартной системой сборки Delphi для Android приложений?
    Для начала нужно понять, почему в чём проблемы стандартной системы сборки.
    1. Поддержка сторонних Android-библиотек
    Это самая важная часть для FGX Native. Мы используем различные сторонние Android библиотеки - Firebase, AdMob, Visio и прочие. Все эти библиотеки в свою очередь используют другие библиотеки, и тд т тп. Каждая библиотека - это не только код, но и ресурсы, изменения необходимые для Android манифеста и тд. Соотвественно, для полноценной поддержки сторонних Android-библиотек требуется не только внедрить исполняемый код, но и так же поставить все ресурсы и слить правки в Android манифесте.
    Стандартная система сборки Delphi ограничена только внедрением кода. А это значит, что выдрав из Андроид-библиотеки только код и проигнорировав ресурсы, манифесты и нативный код, мы получаем нестабильное решение, которое может не работать, падать и тд. Поэтому в Delphi сообществе очень много проблем с использованием сторонних Android решений. И все они зачастую упираются в ограничение стандартной системы сборки.
    Более подробно проблема поддержки Android-библиотек описана в статье про миграцию на AndroidX. 2. Скорость
    Не секрет, что скорость сборки Android приложений из Delphi, по сравнению с нативными средствами разработки, оставляет желать лучшего.  И если во время сборки простого приложения проблема не так заметна, то ситуация кардинально менятся, когда мы имеем дело с приложениями готовыми для продакшена и содержащими большое количество кода, ресурсов и тд.
    Повторный запуск приложения (после сборки без изменений) может занимать минуты(!) (в зависимости от используемых ресурсов). А после внесения любых, даже самых незначительных изменений в проект, требуется потратить почти столько же времени, как на сборку проекта с нуля.
    Мы собрали немного статистики от наших клиентов по сборке существующих продакшен-приложений с большим количеством экранов и ресурсов. Данные показатели зависят от многих факторов: сложность проекта, характеристики  компьютера, на котором осуществляется сборка и тд. Но для нас важно относительные значения времени в рамках одного проекта и одного компьютера. Поэтому следует иметь ввиду, что в каждом конкретном случае числа будут другими.

    Первый столбец содержит время старта (без отладки) проекта с нуля. До этого проект не собирался и нет никаких промежуточных результатов сборки. Второй столбец указывает время старта (без отладки) проекта после внесения изменения в проект: изменили исходный код и тд. Третий столбец отвечает за повторный старт (без отладки) приложения без внесения изменений .     Из этой таблицы хорошо видно, что в среднем на сборку с запуском уходит ~1 минута. Обычный сценарий использования: внес изменений в коде, собрал, запустил, поймал ошибку, опять внес изменений и тд. Грубо говоря, в среднем 60 запусков в день приложения (без отладки) может занимать 1 час рабочего времени! С отладкой цифры становятся еще более угрожающими. Тратится драгоценное время на ожидание, вместо того, чтобы потратить его с пользой.
    3. Технологическое отставание от требований Google
    Стоит отметить, что Google активно развивает сборку Android приложений, каждый раз выдвигая всё новые и новые требования к полученному приложению:
    Был APK, на его смену пришел более умный AAB. Новые требования к версии используемых библиотек. Если используемая библиотека старая, то приложение не может быть загружено в маркет или же просто не работать на свежих версиях Android. Поскольку Delphi самостоятельно реализует систему сборки, то получается состояние вечной гонки, в которой Delphi, к сожалению, всегда в роли догоняющего. Поэтому, как только Google/Apple меняют структуру пакета приложения, вам приходится ждать обновлений Delphi, которые изменят встроенную систему сборки в соответствии с новыми требованиями. С учётом частоты выхода новых версий Delphi это может вылиться в длительное ожидание, а иногда и финансовые затраты, необходимые для приобретения новой версии.
    Что нам дает новая система сборки
    Учитывая все перечисленные выше минусы встроенной сборки Android приложений, мы пошли по единственному верному на наш взгляд пути, а именно, мы внедрили родную систему сборки, которая используется в Android Studio и которую рекомендует сам Google.
    1. Поддержка Android-библиотек
    Полноценная поддержка всех Android-библиотек. Теперь перед Delphi разработчиком не будет практических никаких ограничений для использования сторонних библиотек. Мы предлагаем полный цикл интеграции любого стороннего решения в FGX Native приложения под Android:
    Вы находите интересуемое решение на Java для Android Вы добавляете Java библиотеку в FGX Native проект Вы генерируете заголовочные файлы для Java библиотеки на языке Delphi при помощи нашей утилиты Java2Delphi. В будущем появится автоматическое скачивания всех зависимостей. Так что вам даже не придется искать файл библиотеки, достаточно будет указать имя библиотеки и её версию. Остальное на себя возьмет FGX Native.
    2. Скорость
    После внедрения новой системы сборки, мы попросили наших клиентов, повторно протестировать сборку их проектов. Все результаты сведены в таблицу ниже. Из нее наглядно видно, что в целом сборка и запуск  проектов стал быстрее от 2 до 5 раз 🔥(кроме старта с нуля, что обуславливается долгой сборкой главной so-библиотеки приложения, которая целиком и полностью зависит от компилятора и линкера).

    Давайте разберем результаты подробнее.
    Старт после изменений
    Данный замер является самым часто используемым. Вы вносите изменения в проект и запускаете приложение для тестирования и отладки. Практически - это основной сценарий работы разработчика. В целом прирост скорости составляет от 2 до 5 раз на тестируемой выборке проектов 🚀. Важно отметить, что при этом новая система сборки проделывает гораздо большую работу по сравнению со стандартной, даже если брать в расчёт только внедрение дополнительных ресурсов от используемых библиотеки. Количество ресурсов может исчисляться сотнями, и, если добавлять их все через Deployment Manager, то разница в результатах будет еще больше (не в пользу стандартной системы сборки). 

    Повторный старт
    Данный вариант используется реже, когда вы пытаетесь воспроизвести какую-то ситуацию без изменений кода и у вас не получается ее поймать с первого раза. В этом случае вы просто запускаете приложение из IDE повторно. 
    В этом случае показатели скорости просто ошеломительные. Прирост составляет в ~5 раз на текущей выборке и практически он является постоянной. Если в стандартной системе сборке повторный запуск зависит от количества ресурсов и размера приложения, то для FGX Native это постоянная величина.

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

    3. Технологическое отставание от требований Google
    Мы не "изобретаем велосипед" в сборке Android приложений, а берем проверенное официальное решение от Google, которое поддерживается Google. А это значит:
    Соответствование всем новым требованиям со стороны Google Легкое/моментальное обновление системы сборки до последней версии, без необходимости обновления Delphi Использование
    Первая сборка
    При первом открытии FGX Native проекта, начиная с 1.15.0.0 автоматически будет выполнена миграция настроек проекта, в рамках которой будет предложено обновить шаблон манифеста Android приложения и файл стилей styles.xml. Если вы не вносили никаких правок, просто подтвердите замену. Если же вы вносили правки, то необходимо перенести их  вручную в правую часть редактора.
    При обновлении в корень проекта автоматически сохраняется старый файл шаблона. Данное поведение можно отключить при помощи чекбокса, расположенного в левом нижнем углу.

    При первой сборке FGX Native проекта начиная с 1.15.0.0 в корне проекта автоматически будет создана директория ".android-build". Этот каталог содержит всё необходимое для сборки вашего проекта. Его не нужно добавлять в систему контроля версии, он может быть большого размера, так как там сохраняются промежуточные результаты сборки, при необходимости его можно удалять. Все файлы внутри данной директории являются автогенерируемыми, поэтому не пытайтесь вносить ручные правки, они будут проигнорированы. 
    Первая сборка может занять длительное время, так как при ней загружаются с интернета (требуется наличие активного интернет соединения!) все необходимые компоненты сборки. Однако последующие сборки будут проходить намного быстрее. Во время первой сборки среда может визуально "подвисать", это связано с тем, что интеграция с msbuild в IDE не умеет выполняться полностью параллельно.
    Ошибки сборки
    Если в результате сборки появляется ошибка, то подробную информацию можно найти на нижней вкладке "Output", а не в "Build", как раньше.
    Например, все ошибки упаковки на панели "Build" будут сводиться к такой.

    Подробности можно найти на вкладке "Output". По тексту ошибки становится ясно, что в проекте используется TargetApiVersion ниже 33.

    Требования
    Для успешной сборки требуется свежая версия Java JDK (не ниже 18). Можно использовать ту, что идет в поставке с Delphi. Требуется наличие интернета для первой сборки приложения, так как при ней скачиваются необходимые компоненты сборки. Теперь все FGX Native под Android используют TargetAPILevel = 33. Мы полностью перешли на использование последней версии Android. Поэтому понижать версию теперь нельзя. Когда планируется релиз?
    Поскольку релиз 1.15.0.0 является очень крупным и затрагивает критические важные моменты, мы хотим быть уверены, что он не испортит ваши проекты. Поэтому внедрение будет происходить постепенно. На первом этапе мы отдали некоторым нашим клиентам сборку на предварительное тестирования на больших проектах, получили обратную связь и устраняем найденные недочеты.  Далее на этой неделе мы планируем выпустить экспериментальную версию 1.15.0.0 для широкого круга пользователей. По сути - это полноценная версия и вы сможете опробовать её для перехода на Android 13, сравнить скорость сборки и тд. Однако, если вы столкнетесь с какими-то серьезными проблемами для вашего проекта, вы всегда сможете откатиться на стабильную версию 1.14.6.0. На текущий момент, практически все большие собранные проекты на 1.15.0.0 успешно запускаются и работают.
     
    Если при тестировании вы столкнетесь с проблемами, просьба сообщить нам о них, и мы постараемся их оперативно поправить.
    Всем спасибо за внимание и хорошей продуктивной недели!
  17. Добрый вечер,
    Начиная с FGX Native 1.15.3.0, появится новый компонент для сборка аналитики использования вашего приложения TfgFirebaseAnalytics.

    Данный компонент позволяет собрать информацию об использовании вашего приложения пользователями. Например, вы можете определить:
    Какую форму пользователи открывают чаще всего. Какие версии вашего приложения успешно запускаются. Сколько пользователей первый раз запустили приложение. Какие покупки чаще всего делают в вашем приложении. С какими компонентами чаще всего взаимодействуют.  И многое другое. Подробности о Firebase Analytics: https://firebase.google.com/docs/analytics?authuser=0
    Настройка использования
    Чтобы использовать новый компонент, необходимо выполнить общую регистрацию FGX Native приложения в Firebase консоли (Шаги такие же, как регистрация приложения для использования Push-уведомлений): 
    Настройка Firebase для iOS. Настройка Firebase для Android. Дополнительно для Android нужно вручную добавить зависимость на библиотеку "com.google.firebase:firebase-analytics:21.2.0"
    https://forum.fgx-native.com/blogs/entry/56-интеграция-android-библиотек-просто-и-быстро-с-11520/

    Если вы не выполните корректную настройку приложения, то на iOS запуск приложения закончится ошибкой старта, а в Android ни одна метрика не будет отправлена в облако Firebase. 
    Отправка событий
    Чтобы начать отправку событий необходимо разместить новый компонент TfgFirebaseAnalytics. Рекомендуем разместить его на общем дата модуле, чтобы вы могли пользоваться одним экземпляром компонента в любом месте. Однако, вы можете использовать и несколько экземпляров данного компонента.
    Как только вы размещаете его в приложении, так сразу компонент начинает автоматический сбор базовых событий в вашем iOS/Android приложении, такие как:
    Определение первого запуска приложения Статистику использования разных версий вашего приложения. Сбор сессий использования.  И тд. Такие события доступны в консоли Firebase в разделе Analytics -> Realtime.

    Помимо автоматического сбора событий, вы можете выполнять отправку своих событий.
    Каждое событие, происходящее в вашем приложении, характеризуется:
    Name - имя. Строковый код события. Firebase предлагает готовые коды событий. С ними можно познакомиться на этой странице. Вы можете использовать, как готовые коды, так и свои собственные.
    Например: событие select_content предназначено для информирования о том, что пользователь выбрал важный для вас контент (нажал на кнопку, открыл форму и тд). Parameters - параметры в формате - название параметра - значение. Каждое событие может сопровождаться соответствующими параметрами. Firebase описывает связанные с событиями параметрами, которые вы можете отправить.
    Например, событие select_content сопровождается двумя параметрами: content_type и item_id (документация) Для отправки события в компоненте есть два метода, позволяющие это сделать:
    /// <summary> /// Отправляет на сервер Firebase событие с именем <c>AName</c>, параметрами c именами <c>AKeys</c> и значениями /// <c>AValues</c>. /// </summary> procedure LogEvent(const AName: string; const AKeys: TArray<string>; const AValues: array of const); overload; /// <summary>Отправляет на сервер Firebase событие с именем <c>AName</c>.</summary> procedure LogEvent(const AName: string); overload; Чтобы узнать, что пользователь нажал на кнопку покупки в вашем приложении, необходимо добавить в обработчик вызов метода LogEvent:
    procedure TFormMain.fgButtonBuyTap(Sender: TObject); begin fbAnalytics.LogEvent('select_content', ['content_type', 'item_id'], ['Button', 'Buy subscription']); end; Определение открытых экранов/форм
    Помимо отправки любых событий, компонент TfgFirebaseAnalytics позволяет отправлять информацию о том, какие формы/экраны открывает пользователь. Чтобы воспользоваться данной возможностью, необходимо в момент отображения формы передавать на сервер Firebase информацию о текущей форме.
    /// <summary> /// Задает текущее название экрана, которое определяет текущий визуальный контекст в вашем приложении. /// Это помогает определить области в вашем приложении, где пользователи проводят свое время и как они /// взаимодействуют с вашим приложением. /// </summary> procedure SetCurrentScreen(const AScreenName: string; const AScreenClassName: string); Для удобства отслеживания, когда форма появляется на переднем плане, в FGX Native 1.15.3.0 для формы TfgForm добавлены два новых события:
    /// <summary>Вызывается, когда форма выходит на передний план на экране.</summary> /// <remarks>Не вызывается для встроенных форм-фреймов.</remarks> property OnActivate: TNotifyEvent read FOnActivate write FOnActivate; /// <summary>Вызывается, когда форма уходит с переднего плана на экране.</summary> /// <remarks>Не вызывается для встроенных форм-фреймов.</remarks> property OnDeactivate: TNotifyEvent read FOnDeactivate write FOnDeactivate; Именно их мы рекомендуем использовать для указания текущего экрана в Firebase Analytics.
    Например, код по отображению главной формы может выглядеть так:
    procedure TFormMain.fgFormActivate(Sender: TObject); begin Shared.fbAnalytics.SetCurrentScreen('Main form', ClassName); end; Первым параметром указывание название экрана, вторым - класс. 
    Общие настройки
    Помимо главной задачи отправления статистики в Firebase Analyitcs, вы можете выполнять базовые настройки компонента:
    /// <summary> /// Удаляет все аналитические данные для этого приложения с устройства и сбрасывает идентификатор экземпляра приложения. /// </summary> procedure ResetAnalyticsData; /// <summary> /// Включен ли сбор аналитики для этого приложения на данном устройстве. Этот параметр сохраняется во всех сеансах /// приложения. По умолчанию он включен. /// </summary> property Enabled: Boolean read FEnabled write SetEnabled default DefaultEnabled; /// <summary>Уникальный идентификатор текущего пользователя.</summary> property UserId: string read FUserId write SetUserId; /// <summary>Задает продолжительность бездействия, которая завершает текущий сеанс.</summary> property SessionTimeoutDuration: Integer read FSessionTimeoutDuration write SetSessionTimeoutDuration default DefaultSessionTimeoutDuration; С остальными подробности использования вы можете ознакомиться в официальной документации Firebase:  https://firebase.google.com/docs/analytics?authuser=0
    Спасибо
  18. Добрый день, уважаемые разработчики.
    В этой статье мы поговорим о поддержке темной темы в FGX Native приложении, о том, как ее добавить, как сделать автоматическое переключение и о том, что добавлено в 1.15.3.0 в этой области.

    Введение
    Тема - это набор цветов и способов отрисовки компонентов. В светлой теме метка использует черный цвет текста и светлый фон, а в темной теме - наоборот, белый текст на темном фоне. Используя это правило, несложно настроить параметры отображения компонентов так, чтобы добавить темную тему.
     
    Для того, чтобы добавить темную тему буквально в один клик, мы предлагаем генератор темной темы в дизайнере ресурсов (Project -> FGX Assets Manager).

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

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

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

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

    Если у кнопок и у меток вы можете поменять цвет шрифта, то с самим барабаном возникают вопросы, так как iOS не дает возможности для изменения цвета.  А значит вы не можете его корректно отобразить только при помощи цветов в FGX Native. И даже если вы примените темную тему FGX Native барабан у вас будет или с темным текстом или же он будет светлый для светлой темы, в результате чего стилизация будет некорректной.
    Темная тема на уровне системы
    Темная тема появилась в операционных системах довольно недавно, а значит возникает вопрос, а что делать с поддержкой темной темы в старых приложениях, которые не обновляются? И тут в iOS/Android поступают немного по разному.
    iOS
    Все новые приложения для iOS, которые нацелены на свежие версии iOS, где была уже добавлена тема, автоматически получают поддержку темной темы. Это значит, что система при старте приложения автоматически рисует нативный компонент согласно текущей системной темы приложения и также выбирает соответствующие системные цвета.
    Если разработчик не готов или не хочет использовать темную тему, то он явно указывает в настройках проекта UIUserInterfaceStyle = light. В этом случае, iOS рисует родные компоненты в светлой теме и игнорирует темную тему.  Мы используем этот режим в FGX Native, так как у нас не было полноценной поддержки темной темы. Поэтому все приложения FGX Native содержат этот флаг:

    Android
    Поддержка темной темы в Android более сложная. Она чем-то похожа на iOS, за исключением того, что некоторые производители Android устройств добавляют "свою" поддержку темной темы для старых версий. Например MIUI. В этом случае, производитель автоматом принудительно пытается применить темную тему и вычислить цвета на основании текущих (сделать их автоматический реверс). В результате кто-то из вас мог столкнуться с некорректным отображением приложения. Чтобы избежать этого мы принудительно отключаем все подобные попытки при помощи специального атрибута в стиле андроид приложения  
    <!-- MIUI automatically recolors UI in dark mode, it uses emulation mode. --> <item name="android:forceDarkAllowed">false</item> Выбор же темной темы в Android приложения строится на основании используемой темы приложения в файле styles.xml. По причинам отсутствия полноценной поддержки темной темы, мы так же используем строго светлую тему для Android приложения
    <!-- Basic theme for all Android versions --> <style name="BaseAppTheme" parent="Theme.AppCompat.Light"> Как добавить темную тему в FGX Native?
    Добавление темной темы состоит из нескольких шагов:
    1. Разрешаем FGX Native приложению автоматически использовать темную системную тему (Важно! FGX Native приложения не включают темную тему по умолчанию, поэтому требуется делать этот шаг).
    iOS: Удаляем ключ UIUserInterfaceStyle из настроек проекта: Project -> Options -> Version Info (для iOS конфигураций) Android: Меняем базовую тему в файле styles.xml (расположен в корне вашего приложения) cо значения "Theme.AppCompat.Light" на "Theme.MaterialComponents.DayNight"    <style name="BaseAppTheme" parent="Theme.MaterialComponents.DayNight"> Эти правки позволят приложению автоматически менять отрисовки нативных компонентов при смене системной темы.
    2. Добавляем светлую/темную темы в FGX Native через дизайнер ресурсов при помощи генератора тем:

    3. Отлавливаем изменение системной темы и применяем к форме тему из ресурсов. Для этого используем новое событие TfgForm.OnSystemAppearanceChanged, которое содержит параметры текущей системной темы и которое вызывается каждый раз при смене системной темы. 
    procedure TFormMain.fgFormSystemThemeChanged(Sender: TObject; const AAppearance: TfgSystemAppearance); begin case AAppearance.ThemeKind of TfgSystemThemeKind.Dark: ThemeName := 'Theme Dark'; TfgSystemThemeKind.Light: ThemeName := 'Theme Light'; end; end; Для того, чтобы при старте не накатывать тему из ресурсов еще раз, мы автоматически вызываем это событие каждый раз при открытии формы. Это позволяет ограничиться заданием темы только в данном обработчике.
    Если по каким-то соображениям, вы хотите узнать параметры системной темы, вы можете это сделать при помощи нового свойства FGX.SystemInfo.TfgSystemInfo.Appearance.
    Результат работы представлен ниже:
    video_2023-02-08_00-03-12.mp4 video_2023-02-09_22-47-34.mp4
    Планы на будущее
    В будущем мы будем стараться упростить этот процесс, чтобы темная тема на стороне FGX Native создавалась автоматически, если разработчик не использует темы в своем приложении, и она автоматически переключалась при смене системной темы.
  19. Продолжаем анонсировать интересные возможности новой версии FGX Native 1.11.0.0. И в этот раз - это компонент локализации TfgTranslator.
    В этой версии мы поставляем отдельный bpl-пакет с компонентом локализации TfgTranslator, который мы сами уже давно и успешно используем в реализации FGX Native дизайнера. Однако, мы не рекомендуем его использовать в мобильных приложениях, поскольку все словари с переводами всегда загружаются при создании формы, а так же, поскольку у нас есть иное видение того, как должен осуществляться перевод в мобильных приложениях.
    Несмотря на сказанное - это рабочее решение, которое может помочь вам с локализацией ваших проектов. Мы поставляем этот компонент по правилу "as-is", то есть нет никаких гарантий (в том числе и поддержки) с нашей стороны по его работе. Этот пакет не является постоянным и может быть в будущем исключен из поставки при появлении рекомендованного решения.
    Как установить?
    Чтобы установить компонент локализации нужно выполнить регистрацию нового пакета компонента в среде. Для этого:
    Открываем менеджер пакетов: Main menu -> Component -> Install Packages. Нажимаем кнопку "Add..." Открываем каталог, где установлен FGX Native и открываем каталог, соответствующий версии вашей IDE. Если вы не меняли место установки библиотеки, то: "C:\Users\Yaroslav\AppData\Local\FGX Native\Libs\<версия IDE>\Win32\Release" Выбираем "FGXTranslatorD.<версия IDE>.bpl": Для 10.3 - 260 Для 10.4 - 270 Закрываем окно нажатием на кнопку OK. Теперь компонент TfgTranslator доступен для использования на панели "Pallette": FGX: Translator -> TfgTranslator.
    Как использовать?
    Компонент TfgTranslator выполняет перевод всех строковых свойств в рамках одной формы. Чтобы им воспользоваться, нужно бросить компонент на форму. Чтобы выполнить первичную настройку, необходимо создать список поддерживаемых языков и, по желанию, выполнить перевод текущих строк. 
    По двойному нажатию на компонент открывается редактор:

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

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

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

    Ручные строковые ресурсы
    Вы можете указать свои строковые ресурсы для использования их в рантайме. Для этого надо нажать на кнопку "T+" и указать код строки и ее переводы.


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

    Смена языка
    Смена языка осуществляется при помощи свойства TfgTranslator.LangId, где нужно указать нужный язык. При смене кода языка, компонент автоматически выполнит перевод указанных свойств.
    Русский (по умолчанию):

    Английский:

  20. Добрый день пользователи FGX Native.
    Сегодня мы хотим рассказать про переход Android части библиотеки FGX Native на AndroidX. О том, что это, зачем это нужно и как это влияет на разработчиков мы поговорим в этой статье.
    Что такое AndroidX?

    Среди всех проблем Android - наверное, главной для разработчика является проблема адаптации мобильного приложения под все версии Android. Очень часто, в старых версиях Android просто невозможно реализовать тот или иной функционал, потому что операционная система не предоставляет для этого API. С выпуском новых версий, постепенно Google добавляет пропущенное API. Однако, при использовании такового, вы не можете запустить такое приложение на старых версиях Android, потому что оно просто упадет из-за отсутствия нужного API. Поэтому разработчикам нужно иногда писать по две реализации одного и того же функционала на разном API.
    Для того, чтобы это решить, Google стала выпускать набор библиотек, которые содержат универсальное API, работающее на всех версиях Android. Такая библиотека раньше называлась Android Google Support Library, а затем Google объявила ее устаревшей и заменил ее на новую AndroidX.
    AndroidX - Это набор библиотек от Google, в которых они расширяют стандартные скудные возможности Android и дают широкий набор нового функционала, доступный среди всех версий Android. Она включает в себя большое число разных библиотеки, начиная от реализации базовых компонентов Android OS, продолжая облегченной работой с камерой и заканчивая продвинутыми компонентами Material Design. 
    До версии FGX Native 1.15.0.0 используется "Android Google Support Library".
    Зачем переходить на AndroidX?
    Главная необходимость заключается в том, что многие другие современные сторонние библиотеки Android уже используют AndroidX. Например, Firebase, AdMob, Google Maps и тд. А это значит, что если мы хотим добавить новый функционал в TfgMap из свежих версий GoogleMap или добавить возможность отправки push-уведомления с картинкой из Firebase, то мы не сможем это сделать, пока не перейдем на AndroidX.
    Помимо внутренних потребностей для развития FGX Native на Android платформе нужно не забывать, что разработчик с FGX Native может использовать сторонние jar библиотеки, сгенерировать для них заголовочные файлы при помощи Java2Delphi утилиты (входит в поставку FGX Native) и использовать в вашем приложении вами любимый язык Delphi. Будь-то "Яндекс.AppMetrica" или WebRTC компоненты или UI компоненты, рисующие графики, FGX Native позволяет это сделать. Однако, опять же многие новые свежие версии сторонних Android библиотек уже используют AndroidX. А это значит, что их нельзя использовать, пока нет поддержки AndroidX.
    Почему переход на AndroidX не был выполнен ранее?
    Как уже было сказано ранее FGX Native до 1.15.0.0 использует "Android Google Support Library". И эта библиотека считается официально устаревшей с Июля 2017. Так почему же, мы до сих пор используем устаревшую версию?
    Перед тем, как ответить на этот вопрос, познакомимся, что технически означает "добавление Android библиотеки в приложение". Упрощенно, FGX Native Android приложение состоит из четырех частей:
    "SO-Библиотека" с нативным кодом вашего приложения. Это именно то, что получается в результате компиляции ваших форм, модулей и тд. "classes.dex" - Это байт код, который является стартовым для любого Android приложения. Именно эта часть загружает делфи библиотеку и передает ей управление. "Набор ресурсов" - иконки приложения, заставки, графические ресурсы, ассеты, шрифты, ресурсы локализации и тд, все то, что доступно для вашего приложения. "Манифест приложения" - это по сути описание содержимого вашего приложения, что оно может делать, а что нет. Именно он является определяющим файлом на предмет выдачи прав доступа, запуска других приложений и тд. Все это упаковывается и на выходе вы получаете пакет приложения APK или более сложный формат AAB.
    Android библиотека по сути имеет практически такое же содержание, как и Android приложение. Оно так же может иметь в своем составе нативные библиотеки, наборы ресурсов, манифест или же байт-код в jar-библиотеке.
    Поэтому чтобы добавить Android-библиотеку в приложение, необходимо все, что есть в библиотеке добавить в приложение. И выполнить хитрые манипуляции по совмещению данных из разных библиотеки (сливание манифестов, компиляция ресурсов, слияние байт кода в один classes.dex.
    Ресурсы, манифесты
    Так вот причина задержки в переходе на AndroidX кроется в механизме поддержки Android библиотек на уровне RAD Studio/Delphi. Добавление сторонних jar библиотек всегда было частью системы сборки Delphi, в которой мы увы не можем менять со стороны. Поддержка Android библиотек в Delphi ограничивается только добавлением байт кода в итоговый classes.dex. А это значит, что Delphi не умела и до сих пор не умеет сливать манифесты, добавлять  и компилировать ресурсы, внедрять so-библиотеки автоматически и тд. Поэтому круг использования сторонних Android библиотек в Delphi довольно узкий - это библиотеки, которые не используют ресурсы и по части не работают с UI. Как вы понимаете, таких библиотек в мире Android довольно мало. Потому что даже обычная не UI библиотека выделяет строковые ресурсы в "набор ресурсов" для возможности локализации разработчиком.
    Поэтому, чтобы выполнить миграцию на AndroidX нужно вначале реализовать полноценную поддержку Android-библиотек в Delphi. Поскольку это часть системы сборки Delphi, у нас нет возможностей для внесения изменений в не наш код. Осложняется еще и тем, что Delphi Deployment Manager заточен только на FMX и не любит никаких отклонений от "нормы" FireMonkey приложения. Поэтому IDE всячески пытается удалить, изменить, обновить элементы "Deployment Manager" и сводит практически на нет любые кастомизации.
    AndroidX является набором огромного количества маленьких библиотек, каждая из которых содержит свой набор ресурсов (изображения, стили, локализации, файлы настроек и тд). И именно по этому на нее не возможно перейти даже обходными путями.
    К сожалению, за прошедшие 5 лет выпуска Delphi больших изменений в области деплоя и сборки для Android не было. Главным изменением можно считать добавление поддержки MultiDex в Delphi 11.
    MultiDex и Delphi 11
    Если на пальцах объяснить, что такое MultiDex, то когда байт код из разных Android библиотек сливается в classes.dex, то может возникнуть ситуация, что все не влезает в один файл (ограничение накладывается на общее количество типов, методов и т.п., которое может поместиться в одном файле. Это связано с архитектурой выполнения байт кода в Android). Когда все не помещается в один файл, то остальное помещается в следующий файл classes2.dex и так далее, пока все не будет раскинуто по файлам. В этом случае apk содержит ни один classes.dex, а не сколько. И именно поддержка этого добавлена в Delphi 11. 
    По умолчанию, и FireMonkey и FGX Native приложение помещается в один classes.dex. Другими словами, прямой необходимости в поддержки MultiDex не требуется. Однако, чем больше сторонних Android библиотек вы используете, тем быстрее растет classes.dex и тем проще выйти за пределы SingleDex и перейти в MultiDex. 
    AndroidX вводит большое число зависимых библиотек, поэтому добавление AndroidX также автоматически добавляет необходимость использовать MultiDex. И если в Delphi 11, такая поддержка есть. То пользователям старых версий Delphi делать в этом случае уже нечего. Поскольку мы считаем, что разработчики не должны быть сильно привязаны к версии IDE при использовании нашего продукта, мы не могли и не можем отказаться от поддержки старых Delphi до 11 версии.
    Delphi 11 и FireMonkey поддерживает же AndroidX, в чем секрет?
    "Delphi 11 официально же использует AndroidX" - значит ли это, что проблем никаких нет? На самом деле, поддержка заканчивается только на уровне интеграции байт-кода в приложение. О чем я упомянул в предыдущем разделе. Это значит, что Delphi просто внедряет исполняемый байт код в приложение и так же не поставляет никакие ресурсы в FMX приложение. Как это отражается на приложении. Как только выполнение вашего приложения попробует обратиться к несуществующим ресурсам, то в этот момент оно может либо упасть, либо работать некорректно. Так же FMX содержит не весь AndroidX, а только минимально-необходимый набор библиотек. По большей части FMX минимально использует Android API, поэтому вы можете не наблюдать проблем с отсутствующими ресурсами. Однако, как только вы сделаете шаг в сторону и захотите расширить возможности добавлением Android-библиотеки, то вы поймете, что все использование ограничено и приложение не будет работать.
    Почему теперь переход на AndroidX стал возможен?
    Возможно, Embarcadero в будущем добавит полноценную поддержку Android-библиотек. Но пока ее нет, нам ничего не остается, как заменить систему сборки Android приложений на другую и добавить полноценную поддержку использования Android-библиотек. Последнее время мы плотно занимались этой работой. В результате чего мы полностью перешли с системы сборки Android приложения в Delphi на другую с полноценной поддержкой Android-библиотек. Данную поддержку вы увидите в обновлении 1.15.0.0. Подробности перехода на новую систему сборки будут рассказаны в следующей статье. Однако, новая сборка помимо полноценной поддержки Android-библиотек так же значительно ускоряет запуск приложения на устройстве (даже при условии деплоя ресурсов) и дает эти возможности на любой версии Delphi. Это значит, что клиенты любых поддерживаемых версий Delphi, не зависимо от IDE получат все возможности по сборке приложений, включая MultiDex и добавление Android-библиотеки.  
    Что дает нам AndroidX?
    Android 13 и новее
    Переход на последнюю версию AndroidX дает нам полноценную поддержки последних версий Android. Начиная с версии FGX Native 1.15.0.0 все приложения будут нацелены на Android 13 (Api Level = 33). Все заголовочные файлы так же будут обновлены до Android 13. Старые заголовочные с классами "Support Library" будут удалены.
    Material Components
    Помимо этого, теперь мы можем полноценно использовать компоненты из Material Design. И в будущем теперь нас ничто не сдерживает от добавления продвинутых различных реализаций вкладок, chips и т.д.
    Firebase
    Поддержка последней версии Firebase, работающая на всех поддерживаемых версиях Андроида без проблем. Возможность передавать изображение в push-сообщениях.

    Сканер штрихкодов
    Обновленная реализация сканера штрихкодов, которая работает быстрее, стабильнее и лучше.
    Карты GoogleMap
    Поддержка свежих версий карт.
    Реклама AdMob
    Использование последних версий площадки по размещению рекламы.
    Прочее
    Обновление Yandex.AppMetrica, Google SignIn, Billing, InAppPurchase и тд.
    Что делать, если я не все понял в этой статье?
    Не расстраиваться! FGX Native команда делает все, чтобы вам не нужно было знать обо всем этом и вы могли сконцентрироваться на решении своих задач. Однако, нам приятно поделиться с вами действительно важными изменениями в FGX Native, которые позволят нашему продукту стать еще шире и добавить еще больше новых возможностей. У нас большой опыт в этой области, который позволяет нам реализовывать практически любые идеи. 
    Всем спасибо за внимание!
  21. Анонс 1.14.4.0

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

    Система разметки FlexBox - универсальный инструмент, предлагающий довольно большой ряд редактируемых параметров, разобраться с которыми при первом приближении довольно сложно. В этом релизе мы разработали визуальный редактор параметров для контейнеров FlexBox, наглядно отображающий разные режимы выравнивания. Редактор доступен у свойства TfgLayout.AlignmentChildren, достаточно нажать на кнопку "..." у значения свойства AlignmentChildren любого компонента-контейнера. Он не просто показывает работу опций, но так же и адаптирует их при смене ориентации и тд.
    FlexBoxDesigner.mp4.fa3fd3bd9129367f28613c726623cc0b.mp4
    Переработанный дизайнер ресурсов
    В этом релизе мы полностью переработали дизайнер ресурсов, как внутри, так и снаружи. Добавили новые возможности и улучшили старые. Но обо всем по порядку.
    Автоматическое удаление "лишних" ресурсов
    В старой версии дизайнера при добавлении ресурса цвета создавалось 5 одинаковых ресурсов цвета для каждого типа устройств (Universal, Phone, NormalTablet, LargeTablet, ExtraLargeTablet). Однако, как показала практика,  пользователи используют на всех устройствах один и тот же цвет. Поэтому генерация одинаковых цветов нецелесообразна и с точки зрения дублирования, и с точки зрения скорости загрузки приложения и поиска ресурсов. В связи с этим, теперь дизайнер автоматически определяет дубликаты и удаляет их.
    Было:

    Стало:

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


    Яркость изображения
    Улучшен алгоритм определения яркости изображений. Теперь более корректно определяется контрастный цвет фона для предварительного просмотра. Напомним, если иконка/изображение использует белые оттенки цветов (светлая), то для предварительного просмотра подбирается темный фон и наоборот.


    Импорт изображений
    Теперь можно перетащить папку с изображениями на дерево ресурсов и импортировать все вложенные изображения.
    Стандартизация редактирования ресурсов.
    Теперь все ресурсы выглядят в дизайнере одинаково, а все операции редактирования перенесены в выпадающее окно, которое открывается при нажатии на предварительное отображение ресурса.


    Умное отображение цвета
    Если ресурс цвета содержит известный код цвета, то вместо кода отображается название цвета. При наведении курсора мыши на превью цвета, отображается ARGB раскладка цвета.

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

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

    20220904_174816.mp4
    Многопоточный режим TfgPickerPhoto
    При использование в пикере выбора фотографий устройства множественного выбора, процесс извлечения фотографий в вашем приложении мог занимать много времени (в зависимости от количества изображений и их размера). При этом приложение зависало до конца обработки всех фотографий. В этом релизе мы добавили многопоточную загрузки изображений и ускорили их обработку. Чтобы пользователь понимал, что процесс может занимать длительное время, мы добавили анонимную функцию для возможности контроля процесса обработки.
    TfgPickerPhotoFactory.PickPhotosFromLibrary(btnTakePhotoFromLibrary, procedure(const AFileNames: TfgPhotoFiles) begin LoadImages(AFileNames); end, procedure(const AProgress: Single) begin ShowProgress(AProgress); end); Поддержка Android 12
    Добавлена поддержка Android 12. Для корректной публикации приложений в "Google Play Market", необходимо обновить манифест Android приложения. При открытии старого приложения, IDE предложит обновить манифест автоматически. Если вы вносили ручные правки в шаблон манифеста приложения, то перед обновлением манифеста сделайте его копию и затем заново внесите ваши правки. 
    Если по каким-то причинам среда не предложила обновить манифест (если вы ранее отказались от обновления шаблона), то вы можете это сделать вручную. Для этого необходимо добавить атрибут `android:exported="true"` в узел `activity`.

    Delphi 11 Update 2
    Добавлена поддержка Delphi 11 Update 2. Из-за критических изменений на стороне IDE, перестали собираться приложения FGX Native из-за нарушения целостности в Deployment Manager. Данный релиз устраняет эту проблему.
    Надеемся, что новый функционал придется вам по душе и облегчит процесс разработки. Через релиз мы выпустим поддержку стилей, которые значительно упростят процесс верстки интерфейса вашего приложения в дизайнере.
  22. FGX Native на Italian Delphi Day 2022

    Добрый день!
    Рады с вами поделиться будущим выступлением по FGX Native на крупнейшей Итальянской конференции по Delphi в 2022 году. Конференция пройдет 21-23 июня 2022 года. Позже будет детальная информация о выступлении.
    https://www.delphiday.it/
     
  23. В этот вторник совместно с компанией Embarcadero проводим вебинар посвященный разработке мобильного приложения с использованием FGX Native. На вебинаре разберем приемы верстки экранов мобильного приложения и одну из возможных примеров системы навигации между экранами.
    В качестве примера создаем прототип мобильного приложения, позволяющего выработать полезные привычки.
    Когда: 31 мая 2022 в 12:00 МСК Язык: русский Заголовок: Создание популярного мобильного приложения с FGX Native Ссылка на регистрацию: https://lp.embarcadero.com/fgx-native  
  24. Анонс 1.14.0.0

    Здравствуйте, уважаемые разработчики.
    В этом анонсе мы хотим познакомить вас с теми нововведениями, которые появятся в версии 1.14.0.0.
    Лицензии и коды активации
    Начиная с версии 1.14.0.0 библиотека будет содержать систему защиты, которая построена на кодах активации и файлах лицензий. Каждому клиенту с активной подпиской был выслан индивидуальный код активации на email, привязанный к его учетной записи. Если по какой-то причине вы не получили свой код активации - свяжитесь с нами любым удобным для вас способом.
    При старте Delphi с неактивированной версией библиотеки вам будет предложено ввести индивидуальный код активации.

    После ввода кода активации на сервере происходит привязка вашей лицензии к текущему компьютеру (необходимо наличие активного подключения к сети Интернет), библиотека получает индивидуальный лицензионный файл, который сохраняется на компьютере и однозначно подтверждает ваше право на использование библиотеки. После активации вы можете продолжать пользоваться продуктом как обычно. Информацию о статусе активации и сроке бесплатных обновлений вы можете найти в окне о Delphi: "Help" -> "About Embarcadero RAD Studio".

    Важные сведения, связанные с активацией библиотеки:
    Допускается 3 (три) активации библиотеки на разных физических машинах, исходя из усредненной схемы использования: домашний, рабочий компьютеры и одна активация на случай смены физических комплектующих вашего компьютера. Однако, если по каким-то объективным причинам у вас будет потребность в дополнительных активациях, вы всегда можете связаться с нами любым удобным для вас способом. Не используйте активацию на чужих/ненужных компьютерах. Активацию необходимо производить каждый раз после установки новой версии библиотеки. При этом каждая активация библиотеки на одной и той же машине не считается за отдельную активацию. При обновлении продукта или приобретении новой подписки, вам будет выслан новый код активации, который действует на новый срок. При этом старый код продолжает действовать для старых версий библиотеки, как и ранее. Увеличенные сроки действия подписки 
    В ближайшее время мы планируем расширить тарифные планы путем добавления подписок на 6 месяцев и 1 год. Детали о тарифах будут опубликованы позднее.
    Идентификация через сервис Google Sign in
    Мы продолжаем пополнять поддержку новых сервисов идентификации клиентов. В версии 1.14.0.0 предлагаем новый компонент TfgGoogleSignInAuthenticationClient для идентификации клиента через сервис "Google Sign in". На текущий момент компонент реализован для Android платформы.
    TfgCollectionView и ручное выделение 
    TfgCollectionView поддерживает разные режимы выделения элементов. Ранее при выделении элемента происходило визуальное отображение заднего фона всего элемента, согласно настройкам цвета SelectionColorName/SelectionColor. Однако, если вы используете в качестве элементов TfgCardPanel или другие виды контейнеров, то часто нужно выполнять изменение цвета не всего элемента, а только вложенного контейнера:
    Advanced_animation.mp4.1f5461e85ffcf2d14b43e8518ef918c3.mp4
    В версии 1.14.0.0 мы добавили возможность управлять внешним видом выделения элементов в ручном режиме, что открывает практически безграничные возможности по кастомизации. Новое свойство TfgCollectionView.SelectionOptions.DisplayingMode позволяет указать каким способом нужно отображать выделение. Доступно два способа отображения:
    Auto - обычный (старый) режим. Компонент берет на себя ответственность по изменению внешнего вида выделенных элементов путем изменения цвета заднего фона элемента. (по умолчанию) Manual - ручной режим. В этом режиме компонент делегирует разработчику работу по изменению внешнего вида выделенных элементов. О необходимости выделить/сбросить элемент компонент сообщает с помощью нового события OnUpdateItemSelectionAppearance. В ручном режиме вам необходимо выполнить визуальное выделение или сброс выделения у переданного элемента в событии OnUpdateItemSelectionAppearance. Это событие вызывается каждый раз, когда списку необходимо обновить состояние элемента. Среди аргументов события передается информация о:
    AItem - обертка для работы с элементом. AIsSelected - признак состояния выделения элемента. AInitiator - Кто инициатор обновления выделения элемента. Если вы хотите добавить анимации в процесс выделения элемента, то ориентируйтесь на этот флаг. Если пользователь нажимает на элемент, то в этом параметре будет значение "User", в противном случае "Control". Типичный код ручного выделения может выглядеть так:
    procedure TFormMain.fgCollectionView1UpdateItemSelectionAppearance(Sender: TObject; const AItem: TfgItemWrapper; const AIsSelected: Boolean; const AInitiator: TfgItemSelectionInitiator); var BackgroundPanel: TfgCardPanel; PrimaryLabel: TfgLabel; begin // Извлекаем ссылку на фон и текстовую метку в элементе BackgroundPanel := AItem.GetControlByLookupName<TfgCardPanel>('background'); PrimaryLabel := AItem.GetControlByLookupName<TfgLabel>('primary'); // Определяем параметры цвета выделения фона панели и цвета текста. if AIsSelected then begin BackgroundPanel.BackgroundColorName := R.Theme.Color.PRIMARY_LIGHT_PRIMARY; PrimaryLabel.ColorName := R.Theme.Color.ON_PRIMARY_TEXT; end else begin BackgroundPanel.BackgroundColorName := ''; PrimaryLabel.ColorName := ''; end; // Опционально, можно выполнить любую анимацию if AInitiator = TfgItemSelectionInitiator.User then BackgroundPanel.Shake; end; Добавлен новый демонстрационный пример: "Компоненты" -> "TfgCollectionView" -> "Ручное отображение выделения".
    TfgControlEnumerators
    Теперь доступны два энумератора по обходу дерева компонентов с возможностью управлять обходом. Оба энумератора доступы в классе TfgControlEnumerators.
    TfgControlEnumerators.Enum - Корень -> First..Last child TfgControlEnumerators.ReverseEnum - Корень -> Last..First child Например, обход по всем TfgEdit может выглядеть так:
    TfgControlEnumerators.Enum(Form,   procedure (const AChild: TfgControl; var AAction: TfgEnumControlsAction)   begin     if AChild is TfgEdit then       TfgLog.Debug(AChild.ToString);   end); Помимо обычного обхода есть возможность делать контролируемый обход. Например, поиск поля ввода:
    TfgControlEnumerators.Enum(Form,   procedure (const AChild: TfgControl; var AAction: TfgEnumControlsAction)   begin     if AChild is TfgEdit then     begin       TfgLog.Debug('Edit: ' + AChild.ToString);       AAction := TfgEnumControlsAction.Stop;     end     else       AAction := TfgEnumControlsAction.Continue;   end); Через параметр AAction анонимной функции можно передать дальнейшее направление действия по обходу компонентов:
    Continue - Перейти к следующему компоненту; Discard - Перейти к соседнему компоненту; Stop - Остановить обход. Маленькие приятности
    Теперь компоненты из групп "FGX: Standard" и "FGX: Layout" имеют свои оригинальные иконки, которые позволяют проще находить нужные компоненты в палитре компонентов.

     

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.