Jump to content

Yaroslav Brovin

Administrators
  • Posts

    2,584
  • Joined

  • Last visited

  • Days Won

    652

Blog Entries posted by Yaroslav Brovin

  1. Yaroslav Brovin
    Рады поделиться новинками будущего релиза 1.12.0.0. 
    Очень часто при разработке мобильных приложений разработчики сталкиваются с одними и теми же задачами. Большинство решений, которые есть в интернете, ориентированы под FMX. Однако, зачастую из-за зависимостей в RTL на FMX Java код, эти решения нельзя просто добавить в FGX Native как есть и использовать.
    Поэтому мы решили по мере возможностей предлагать вам решения этих задач в виде расширений для FGX Native. Расширение будет включать необходимую обвязку/компоненты для FGX Native для сторонних OpenSource проектов. Первым таким расширением будет реализация нового компонента генерации штрихкода TfgBarcode на основе библиотеки Zint (https://www.zint.org.uk/).
    Отображение штрихкодов
    Новый пакет расширения FMXNative.Extension.Zint включен в поставку 1.11.8.0. Пакет содержит новый компонент TfgBarcode, поддерживающий отображение огромного числа типов штрихкодов. 

    Свойство Symbology позволяет выбрать тип отображаемого штрихкода. Через свойство Data указываются кодируемые данные. А через группу свойств Appearance вы можете настроить визуальное отображение штрихкода.
    Новое правило именования пакетов FGX Native
    Мы пересмотрели правила именований пакетов библиотеки FGX Native. Поэтому, если вы создаете свои пакеты расширений на основе FGX Native, вам необходимо переименовать зависимости на пакеты.
    FGXNative.Core <- fgx FGXNative.Design <- fgx_design FGXNative.Registration <-fgx_reg FGXNative.Extension.Translator <- FGXTranslatorD FGXNative.Externals <- fgx_externals Так же, если вы используется наш компонент локализации, необходимо:
    После установки новой версии библиотеки запустить среду Среда отобразит ошибку при загрузке пакета FGXTranslatorD. Необходимо отвечать Yes во всех диалогах про этот пакет. Затем открыть список компонентов среды: "Components" -> "Install Packages..." В списке найти строчку, соответствующую FGXTranslatorD и удалить ее при помощи кнопки "Remove". Данный компонент мы теперь регистрируем автоматически при установке FGX Native. Календарь под iOS
    В новой версии так же появится реализация компонента TfgCalendar для iOS. iOS не имеет родной реализации календаря. Поэтому мы с нуля реализуем данный компонент.
    Заключение
    Если у вас есть потребность в миграции некоторых невизуальных компонентов из FMX, пожалуйста, отпишитесь здесь в комментариях:
    Ссылку на стороннюю библиотеку с наличием исходных кодов/OpenSource. Без доступа к исходным кодам мы не сможем выполнить адаптацию под FGX Native. Описание для чего данный компонент нужен. Если кто-то из участников уже озвучил в комментариях нужный вам компонент, просьба отметить такое сообщение реакцией (лайком).
  2. Yaroslav Brovin
    Всем хорошей рабочей недели!
    Год назад мы поделились руководством по подключению популярного сервиса платформы для аналитики и маркетинга приложения Yandex AppMetrica для Android. В этой статье с мы рассмотрим, как начать использовать этот же сервис для iOS платформы. 
    Подключение FGX Native приложения для Android платформы рассмотрено в другой статье: 
    Для того, чтобы начать использовать AppMetrica в вашем приложении нужно выполнить два шага:
    Зарегистрировать ваше приложение на стороне Yandex Подключить библиотеку Yandex AppMetrika и выполнить инициализацию ключом API.   Регистрация приложения в Yandex AppMetrika
    1. Создаем новый проект в учетной записи AppMetrika и даем ему название:

    Затем далее и добавить. По окончании добавления сервис отобразит ваш API ключ, который нужно запомнить. Он будет использовать для взаимодействия вашего приложения и сервиса Yandex AppMetrika.

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

    Теперь нам необходимо связать наш проект с iOS приложением. Среди большого числа настроек нас интересует вкладка "Основное" -> "Universal Link". Нам необходимо заполнить поля Bundle ID и App Prefix на основании данных вашего iOS приложения, зарегистрированного в портале Apple Developer.

    AppPrefix - это уникальный префикс, выданный Apple при участии в программе iOS разработчиков. Он же добавляется к названию пакета iOS приложения, тем самым формируя уникальное название приложения. Его можно найти в личном кабинете Apple на вкладке Membership:
    Bundle ID - это идентификатор пакета вашего FGX Native приложения. Если приложение уже зарегистрировано, то вы можете найти название пакета на сайте Apple в разделе Identifiers. 
    После того, как вы указали все данные, необходимо включить "Использовать Universal Link" - это специальная технология, которая призвана обезопасить передачу статики с устройств пользователя на сервера Yandex.

    Чтобы закончить настройку, необходимо включить поддержку Universal Link на стороне профиля разработчика Apple. Для этого необходимо открыть настройки приложения в консоли Apple и включить поддержку "Associated Domains".

    Теперь ваш профиль приложения сконфигурирован для приема статистики с вашего приложения. Переходим к подключению Yandex AppMetrica к FGX Native приложению. 
    Подключение и инициализация Yandex AppMetrica в FGX Native приложении
    1. Скачиваем статическую версию AppMetrica SDK.
    Yandex SDK 3.17.0.zip
    2. Скачиваем заголовочные файлы для Delphi. 
    Yandex.Api.MobileMetrica.iOS.pas
    3. Скачиваем модуль регистрации и инициализации AppMetrica. Этот модуль содержит код по регистрации вашего приложения в сервисе Yandex для iOS и Android.
    Yandex.AppMetrica.pas
    4. Добавляем модуль в ваш проект и в проектном файле вызываем метод инициализации InitYandexMetrika указанием API ключа, выданном на этапе регистрации проекта в Yandex.
    program YandexMetrika; uses FGX.Application, FGX.Forms, Form.Main in 'Form.Main.pas' {Form.Main: TfgForm}, Yandex.AppMetrica in 'Yandex.AppMetrica.pas'; {$R *.res} begin InitYandexMetrika('Ваш API ключ'); Application.Initialize; Application.CreateForm(TFormMain, FormMain); Application.Run; end. 5. Настраиваем линковку проекта с Yandex AppMetrica SDK.
    5.1. Добавляем в настройках среды переменную окружения "YandexMetrica": "Tools" -> "Options" -> "IDE" -> "Environment Variables". Указываем путь к месту, где у вас распакован AppMetrica SDK.
     
    5.2 В настройках проекта указываем пути для линковки. "Project" -> "Options..." -> "Building" -> "Delphi Compiler" -> "Search Path".
    Выбираем конфигурацию "All Configuration -> iOS Deice 64-bit platform" и указываем следующие пути в "Search Path":
    $(YandexMetrica)\YandexMobileMetrica.framework; $(YandexMetrica)\YandexMobileMetricaCrashes.framework 5.3 В настройках линковки передаем дополнительный ключ "-ObjC" линковки: "Project" -> "Options..." -> "Building" -> "Linking" -> "Options passed to the LD linker".
    6. Все. Теперь выполняем сборку приложения и запуск на устройстве. В результате ваше приложение должно успешно стартовать, а через некоторое время вы увидите статистику в личном кабинете AppMetrica.

     
  3. Yaroslav Brovin
    В эту среду совместно с компанией Embarcadero проводим вебинар посвященный разработке мобильного приложения с использованием FGX Native. На вебинаре разберем одну из возможных архитектур мобильного приложения, применим шаблон MVVM для построения экранов. И познакомимся с приемами создания мобильных интерфейсов с FGX Native. 
    Когда: 23 июня 2021 в 12:00 МСК Язык: русский Заголовок: Примеры использования библиотеки FGX Native для создания макетов реальных мобильных приложений. Ссылка на регистрацию: https://lp.embarcadero.com/fgx-native Анонс: 
  4. Yaroslav Brovin
    Доброго дня!
    В ближайшем релизе 1.11.2.0 всех нас ждет появление поддержки выпадающих окон TfgPopup. Если вам необходимо отобразить содержимое в виде выпадающего окна, то эта возможность непременно вам пригодится.
    Создание
    В качестве содержимого выпадающего окна можно использовать как любой визуальный компонент так и форму. Удобнее всего использовать форму, поскольку она позволяет создать содержимое выпадающего окна прямо в дизайнере. При создании формы важно указать:
    Отключить полноэкранный режим формы TfgForm.FullScreen = False. Опционально сделать фон прозрачным через TfgForm.Transparent = True . В качестве начинки окна, я сделал форму с TfgCollectionView, используемым для отображения содержимого 

    Чтобы создать выпадающее окно нужно обязательно иметь содержимое, которое вы планируете показать в этом выпадающем окне. Создание выполняется через фабрику FGX.Popup.TfgPopupFactory, как и тосты, пикеры, диалоги и тд.
    var FPopup: TfgPopup; FPopupContent: TFrameList; FPopupContent := TFrameList.Create(nil); FPopup := TfgPopupFactory.CreatePopup(FPopupContent); После создания TfgPopup становится владельцем вашего содержимого. Это значит, что содержимое будет уничтожено, как только TfgPopup будет удален. Если вы хотите сами контролировать время жизни содержимого, вы можете передать вторым параметром значение False. В этом случае, после уничтожения TfgPopup, ваше содержимое останется жить.
    FPopup := TfgPopupFactory.CreatePopup(FPopupContent, False); После создания необходимо указать размер выпадающего окна при помощи свойства TfgPopup.Size. Например, если выпадающее окно прикреплено к кнопке. то имеет смысл в качестве ширины брать ширину кнопки:
    FPopup.Size := TSizeF.Create(fgButton1.Width, 200); Отображение
    Для отображения выпадающего окна существует два одноименных метода TfgPopup.DropDown, оба которых привязывают отображение окна к указанному компоненту.
    /// <summary> /// Открывает выпадающее окно, прикрепленное к указанному компоненту <c>AAnchor</c> со смещением <c>AOffset</c>. /// </summary> procedure DropDown(const AAnchor: TfgControl; const AOffset: TPointF); overload; virtual; abstract; /// <summary>Открывает выпадающее окно, прикрепленное к указанному компоненту <c>AAnchor</c>.</summary> procedure DropDown(const AAnchor: TfgControl); overload; FPopup.DropDown(fgButton1); Если вам необходимо выполнить отображение выпадающего окна со смещением, то вы можете передать это смещение вторым параметром:
    FPopup.DropDown(fgButton1, TPointF.Create(0, 8)); Эта версия метода удобна в случаях, когда вы самостоятельно делаете внешний вид выпадающего окна и хотите добавить отступы между выпадающим окном и компонентом, вызывающим это окно.
    Для закрытия окна используйте метод Close.
    /// <summary>Закрывает выпадающее окно.</summary> procedure Close; virtual; abstract; Настройка внешнего вида
    По умолчанию TfgPopup выглядит, как TfgCardPanel с тенью и рамкой. Однако, если вы хотите сделать свой внешний вид окна, то вы можете отключить  отображение по умолчанию через свойство TfgPopup.IsTransparent. В этом случае содержимое будет отображено прямо под привязанным компонентом.
    /// <summary>Прозрачное выпадающее окно или нет?</summary> property IsTransparent: Boolean read FIsTransparent write SetIsTransparent; Если вы используете в своих приложениях темы, то вы можете использовать темы и для содержимого выпадающего окна. Для этого необходимо указать название темы в свойстве TfgPopup.ThemeName. Таким образом можно добавить поддержку темной темы и детальнее настроить внешний вид попапов.
    /// <summary>Название темы, используемой для содержимого выпадающего окна.</summary> property ThemeName: TfgThemeName read FThemeName write SetThemeName; ios.mp4 android.mp4  
    События
    В TfgPopup поддерживается два типа событий, OnOpened и OnClosed, вызываемые при открытии и закрытии выпадающего окна соответственно. Так же мы предлагаем две версии каждого события для использования совместно с анонимными функциями и событиями.
    /// <summary>Вызывается, когда выпадающее окно отображается на экране.</summary> property OnOpened: TNotifyEvent read FOnOpened write FOnOpened; /// <summary>Вызывается, когда выпадающее окно отображается на экране.</summary> property OnOpenedCallback: TfgCallback read FOnOpenedCallback write FOnOpenedCallback; /// <summary>Вызывается, когда выпадающее окно скрывается с экрана.</summary> property OnClosed: TNotifyEvent read FOnClosed write FOnClosed; /// <summary>Вызывается, когда выпадающее окно скрывается с экрана.</summary> property OnClosedCallback: TfgCallback read FOnClosedCallback write FOnClosedCallback;  
  5. Yaroslav Brovin
    Нам очень приятно поделиться с вами этой новостью. Одно из приложений, написанных на FGX Native, победило в ежемесячном конкурсе Delphi приложений от Embarcadero. Это приложение -  аудио-гид по достопримечательностям разных городов с поддержкой нескольких языков.
    Поздравляем Романа с успехом и желаем ему не останавливаться на достигнутом!
    Приложение в Play Market: https://play.google.com/store/apps/details?id=ru.wc2.welcome&hl=ru&gl=US Ссылка на конкурс Embarcadero: https://delphi.embarcadero.com/delphi26th-welcome-a-spectacular-mobile-app-for-travelers-made-in-delphi/ Автор: @Roman
  6. Yaroslav Brovin
    Продолжаем анонсировать интересные возможности новой версии 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, где нужно указать нужный язык. При смене кода языка, компонент автоматически выполнит перевод указанных свойств.
    Русский (по умолчанию):

    Английский:

  7. Yaroslav Brovin
    Продолжаем серию статей, посвященных новинкам релиза FGX Native 1.11.0.0. И в этой статье поговорим о самой главной и ожидаемой новинке - поддержка полноценных анимаций 🔥🔥🔥.
     
    TfgAnimationManager - центр управления анимациями
    Главным центром управления анимации любого компонента является менеджер анимаций, доступ к которому можно получить через свойство TfgControl.AnimationManager. Именно он отвечает за создание, добавление и удаление аниматоров.
    Создание аниматора
    Чтобы создать нужный аниматор нужно воспользоваться одним из следующих методов TfgAnimationManager:
    function AddOpacityAnimation(const AStartOpacity, AFinishOpacity: Single; const ADuration: Integer = TfgAnimation.DurationPlatformValue): TfgAnimation; function AddBoundsAnimation(const AStartBounds, AFinishBounds: TRectF; const ADuration: Integer = TfgAnimation.DurationPlatformValue): TfgAnimation; function AddScaleAnimation(const AStartScaleX, AFinishScaleX, AStartScaleY, AFinishScaleY: Single; const ADuration: Integer = TfgAnimation.DurationPlatformValue): TfgAnimation; function AddRotationAnimation(const AStartAngle, ASweepAngle: Single; const ADuration: Integer = TfgAnimation.DurationPlatformValue): TfgAnimation; function AddTranslationAnimation(const AStartPoint, AFinishPoint: TPointF; const ADuration: Integer = TfgAnimation.DurationPlatformValue): TfgAnimation; function AddGroupAnimation: TfgAnimationGroup; Каждый метод создает соответствующий своему названию тип аниматора с указанными стартовыми и конечными значениями. Например, если вы хотите плавно показать кнопку в течении 1 секунды, достаточно выполнить следующий код.
    uses FGX.Animation; var Animation := Button.AnimationManager.AddOpacityAnimation(0 {start opacity}, 1 {finish opacity}, 1000 {msec}); Animation.Start; Обратите внимание, что в данном случае, созданный аниматор "Animation" останется у компонента и не будет удален, пока вы не сделаете это сами или компонент не будет уничтожен. Если вы планируете часто использовать один и тот же вид анимации на конкретном компоненте, то предпочтительным способом будет являться именование анимации. Например:
    uses FGX.Animaton.Helpers; // Создаем аниматор один раз Button.AnimationManager.AddOpacityAnimation(0 {start opacity}, 1 {finish opacity}, 1000 {msec}) .SetName('fade-in'); // Будущие запуски анимации Button.AnimationManager['fade-in'].Start; Если же вам достаточно выполнить анимацию всего лишь один раз, то имеет смысл пометить ее для автоматического удаления опцией TfgAnimationOption.ReleaseOnFinish: 
    uses FGX.Animation.Types, FGX.Animation.Helpers; Button.AnimationManager.AddOpacityAnimation(0 {start opacity}, 1 {finish opacity}, 1000 {msec}) .AddOption(TfgAnimationOption.ReleaseAnimationOnFinish) .Start; Хелпер анимации
    Для удобного создания аниматоров мы предлагаем вам готовый хелпер FGX.Animation.Helpers, который позволяет использовать цепочку вызовов методов аниматора и облегчить визуальное восприятие готового кода.
    Без хелпера:
    uses FGX.Animation; var OpacityAnimation: TfgAnimation; OpacityAnimation := Button.AnimationManager.AddOpacityAnimation(0 {start opacity}, 1 {finish opacity}); OpacityAnimation.Duration := 1000 {msec}; OpacityAnimation.AutoReverse := True; OpacityAnimation.Delay := 500 {msec}; OpacityAnimation.Options := OpacityAnimation.Options + [TfgAnimationOption.ReleaseAnimationOnFinish]; OpacityAnimation.Start; С хелпером:
    uses FGX.Animation.Types, FGX.Animation.Helpers; Button.AnimationManager.AddOpacityAnimation(0 {start opacity}) .SetDuration(1000 {msec}) .SetDelay(500 {msec}) .SetAutoReverse .SetReleaseAnimationOnFinish .Start; Чтобы воспользоваться хелперами, необходимо подключить модуль FGX.Animation.Helpers.
    Обзор базовых аниматоров
    Поддерживается 5 базовых типов анимаций:
    Opacity. Изменение прозрачности (TfgControl.Opacity). Bounds. Изменение положения и размера (TfgControl.Position + TfgControl.Size).  Scale. Изменение масштаба отображения компонента. Rotation. Изменение угла поворота компонента. Translate. Выполнение смещения компонента относительно его текущей позиции (TfgControl.Position). Анимация прозрачности (TfgAnimationManager.AddOpacityAnimation)
    Чтобы выполнить анимацию прозрачности нужно создать аниматор через метод TfgAnimationManager.AddOpacityAnimation и указать стартовое и конечное значение свойства TfgControl.Opacity. 
    Image.AnimationManager.AddOpacityAnimation(0 {start opacity}, 1 {finish opacity}, 2000 {msec}) .Start; opacity.mp4
    Анимация перемещения и изменения размера (TfgAnimationManager.AddBoundsAnimation)
    Чтобы выполнить анимацию изменения размера и позиции нужно создать аниматор через метод TfgAnimationManager.AddBoundsAnimation и указать стартовый и конечный прямоугольник. Пример ниже демонстрирует интересный прием акцентирования внимания на компоненте через визуальное расширение и сжатие компонента.
    var StartRect: TRectF; StopRect: TRectF; begin StopRect := imgPhoto.Bounds; StartRect := imgPhoto.Bounds; StartRect.Inflate(16, 16); Image.AnimationManager.AddBoundsAnimation(StartRect, StopRect) .Start; bounds.mp4
    Анимация изменения масштаба (TfgAnimationManager.AddScaleAnimation)
    Чтобы выполнить анимацию изменения масштаба нужно создать аниматор через метод TfgAnimationManager.AddScaleAnimation и указать стартовые и конечные значения коэффициентов масштабирования по горизонтали и вертикали.
    Image.AnimationManager.AddScaleAnimation(0.5, 1, 0.5, 1, 1000) .Start; scale.mp4
    Анимация поворота компонента (TfgAnimationManager.AddRotationAnimation)
    Чтобы выполнить анимацию поворота компонента нужно создать аниматор через метод TfgAnimationManager.AddRotationAnimation и указать стартовое значение угла и на сколько градусов нужно совершить поворот (в градусах). При этом, если угол поворота положительный, то поворот осуществляется по часовой стрелки, а если отрицательный, то против часовой стрелки.
    Image.AnimationManager.AddRotationAnimation(0 {start}, 360 {Sweep}, 1000) .Start; rotate.mp4
    Анимация смещения (TfgAnimationManager.AddTranslationAnimation)
    Чтобы выполнить анимацию смещения компонента нужно создать аниматор через метод TfgAnimationManager.AddTranslationAnimation и указать стартовое и конечное смещения значения позиции компонента.
    Image.AnimationManager.AddTranslationAnimation(TPointF.Create(-16, 0), TPointF.Create(16, 0), 1000) .Start; translate.mp4
    TfgAnimation - основа анимации
    После того, как мы посмотрели несколько примеров создания аниматоров вживую, пришло время рассмотреть их настройки детальнее.
    Длительность анимации (TfgAnimation.Duration)
    Общая длительность выполнения текущей анимации в миллисекундах в одну сторону (от стартового значения до конечного).
    Задержка перед запуском (TfgAnimation.Delay)
    Если вам необходимо выполнить анимацию с задержкой, то вы можете это сделать указав значение задержки в миллисекундах в свойстве TfgAnimation.Delay.
    Количество повторений (TfgAnimation.RepeatCount)
    Если вам необходимо повторить анимацию несколько раз или сделать ее бесконечной, то вы можете это сделать при помощи этого свойства, где
    RepeatCount = 0 - повторение анимации бесконечное число раз. RepeatCount > 0 - повторение анимации ровно "RepeatCount" раз. Например при помощи этого свойства легко сделать анимацию тряски: повторим 4 раза движение компонента по горизонтальной оси.
    shake+repeatCount.mp4
    Интерполяция (TfgAnimation.CurveKind)
    Это свойство отвечает за формулу интерполяции значений анимируемых свойств. Пока поддерживается 4 самых распространенных типов интерполяции.
    TfgAnimationCurveKind = (Linear, EaseIn, EaseOut, EaseInOut);
    Краткое описание стратегии изменения анимируемого значения на протяжении всей длительности анимации в зависимости от типа интерполяции:
    Linear - равномерное изменение. Варианты типичного применения: короткие анимации, изменение цвета. EaseIn - медленное начало с постепенным нарастанием скорости к концу анимации. Варианты типичного применения: исчезновения объекта. EaseOut - быстрое начало с постепенным замедлением скорости к концу анимации. Варианты типичного применения: появления объекта. EaseInOut - медленное начало с нарастанием скорости посередине и постепенным замедлением скорости к концу анимации. Варианты типичного применения: перемещение объекта, изменение масштаба. Порядок запуска (TfgAnimation.RunOrder)
    Это свойство актуально только в контексте групповых аниматоров и позволяет указывать порядок запуска текущей анимации в группе. Подробнее это будет рассмотрено в разделе "Групповые анимации".
    TfgAnimationRunOrder.Immediately - запуск анимации в момент старта родительского группового аниматора, либо вместо с предыдущим одноуровневым аниматором. TfgAnimationRunOrder.AfterPrevious - запуск анимации после окончания предыдущей анимации в рамках группового аниматора. Дополнительные настройки (TfgAnimation.Options)
    TfgAnimationOption.StartFromCurrent - Начинать анимацию с текущего значения свойства компонента, а не указанного стартового значения. TfgAnimationOption.AlwaysSetFinalValue - При остановке анимации, эта опция позволяет указать сразу конечное значение свойства компоненту, иначе конечное значение останется таким, какое оно было на момент остановки. TfgAnimationOption.AutoReverse - Нужно ли автоматически выполнить анимацию в обратном порядке после окончания прямой анимации. Актуально для RepeatCount > 0. TfgAnimationOption.ReleaseControlOnFinish - позволяет автоматически удалить компонент по окончании анимации. TfgAnimationOption.ReleaseAnimationOnFinish - позволяет автоматически удалить аниматор по окончании анимации. Название (TfgAnimation.Name)
    Вы можете присвоить уникальное название аниматору, чтобы в последствии обращаться к нему напрямую по его имени.
    Например:
    var FadeAnimation: TfgAnimation; FadeInAnimation := Button.AnimationManager['fade-in']; Групповые анимации
    Для создания сложных анимаций мы предлагаем использовать групповые аниматоры, задача которых сгруппировать несколько анимаций и задать правила их запуска. По умолчанию групповой аниматор запускает все вложенные анимации одновременно. Например, такой аниматор ниже позволяет реализовать анимацию модального открытия формы на Android:
    var AnimationGroup: TfgAnimationGroup; AnimationGroup := LForm.AnimationManager.AddGroupAnimation .Add(LForm.AnimationManager.CreateScaleAnimation(1.125, 1, 1.125, 1)) .Add(LForm.AnimationManager.CreateOpacityAnimation(0, 1)); Мы создаем два аниматора, объединенные в группу, один из которых масштабирует форму, а второй меняет ее прозрачность.
    Групповой аниматор TfgAnimationGroup по сути так же является аниматором TfgAnimation. А это значит, что вы можете их вкладывать друг в друга добиваясь анимации любой сложности.
    Пример ниже показывает последовательно выполнение анимаций: вначале смещение компонента, а затем поворот:
    Image.AnimationManager.AddGroupAnimation .Add(Image.AnimationManager.AddTranslationAnimation(TPointF.Create(-16, 0), TPointF.Create(16, 0), 1000)) .Add(Image.AnimationManager.AddRotationAnimation(0, 360, 1000) .SetRunOrder(TfgAnimationRunOrder.AfterPrevious)) .Start; group-animation-1.mp4
    Вы можете выделить создание подобной анимации в отдельный метод и затем применять к любому компоненту. 
    Шаблоны анимаций
    Это приятный бонус для наших пользователей. Мы предлагаем базовый набор уже готовых анимаций, которые вы можете использовать в своих проектах всего лишь одной строчкой кода. Для того, чтобы воспользоваться шаблонами, нужно подключить модуль FGX.Animation.Templates.
    Чтобы просто потрясти компонент, достаточно просто написать:
    Image.Shake; А если требуется настроить параметры на свой вкус и цвет, можно воспользоваться перегруженной версией:
    Image.Shake(TfgShakeAnimationParams.Default .SetDuration(2000) .SetRepeatCount(10)); Видео ниже демонстрирует все текущие доступные для использования шаблоны:
    templates.mp4
    Среди шаблонов так же доступны различные варианты появления и скрытия компонентов с переносами и без. Вы можете ознакомиться с текущим набором в демо проекте: "Анимация" -> "Шаблоны анимаций".
    Ограничения
    Несмотря на то, что анимации уже работают, у них есть ряд ограничений, часть из которых мы будем постепенно убирать в будущих версиях.
    Нельзя менять стартовые и конечные значения уже созданных анимаций. Это можно делать только путем удаление старого и создания нового аниматора. Изменение свойств анимации во время ее выполнения не приведет их к применению. Все свойства применяются в момент старта анимации. Изменение размера компонента-контейнера через анимацию не приводит к выравниванию дочерних компонентов. Если вам нужно выполнить выравнивание содержимого, то надо добавлять дополнительные аниматоры для перемещения и изменения размеров вложенных компонентов отдельно.  Устаревшее API
    Из-за создания полноценной анимации и выделения старых хелперов анимации TfgAnimationHelper в шаблоны анимации FGX.Animation.Templates, мы помечаем существующие методы анимации FadeIn, FadeOut, как устаревшие. Через несколько релизов мы удалим эти методы из TfgAnimationHelper, чтобы вы пользовались более удобными средствами анимации.
    На текущий момент методы анимации формы остаются как есть. В ближайших релизах эту анимацию мы встроим прямо в TfgForm, в результате чего анимация открытия/закрытия форм будет осуществляться автоматически и не будет требовать от вас лишних строчек кода.
    Итог
    Мы продолжим развивать и совершенствовать реализацию анимаций. Поэтому нам очень важно получить от вам обратную связь о том, что удобно, что нет и чего не хватает. Эта информация поможет нам сделать анимацию лучше и удобнее для всех.
  8. Yaroslav Brovin
    В следующем релизе 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.
  9. Yaroslav Brovin

    Общая
    Скоро выйдет релиз 1.9.4.0 с интересными и полезными нововведениями для наших пользователей. Обо все по порядку.
    Push-уведомления
    Если вы уже использовали push-уведомления в своих приложениях, то, возможно, вы обратили внимание, что архитектура сервисов push-уведомлений в RTL с одной стороны довольно гибкая, с другой стороны требует написание определенного количество лишнего кода, которого можно было бы избежать. По этой причине мы разработали новый компонент для работы с push-уведомлениями TfgPushNotificationService. Это высокоуровневая обертка на абстракциями push-сервисов в RTL, которая облегчает работу с уведомлениями в приложении FGX Native.
       
    Для того, чтобы начать принимать push-уведомления в вашем приложении достаточно:
    Выполнить первичную настройку сервисов (Firebase для Android или Apple Push Notification Service для iOS). Бросить компонент на форму и написать обработчик для события OnPushNotificationReceived, которое вызывается при приеме уведомления. Это минимальный набор шагов, который для этого требуется. Если вам необходимо добавить диагностическую информацию, получить токен устройства и тд, то вы можете воспользоваться остальными событиями этого компонента.
    ServiceName - это название сервиса push-уведомлений, которые реализован в библиотеке.  "fcm" - сервис по приему уведомлений через Firebase (Android) "aps" - сервис по приему уведомлений через Apple Push Notification Service (iOS). "Default" - автоматический выбор сервиса в зависимости от текущей платформы. Для Android - "fcm", для iOS - "aps".  Мы обновили демо проект по использованию push-уведомлений: "Push-уведомления" -> "Получение Push-уведомления".
    Помимо этого мы полностью отладили реализацию Push-уведомлений для iOS и теперь вы можете использовать ее в своих приложениях.
     
    TfgPageControl (важно!)
    В этом обновлении мы пересмотрели работу событий OnChanged и OnPageSelected. Теперь эти события вызываются только при смене вкладок пользователем интерактивным путем. События не срабатывают при любом программном изменении вкладок (добавление, удаление, очистка, переключение и тд). Поэтому, если у вас есть логика, которая основывается на постоянном вызове этих событий при любых изменения (интерактивных и программных), то во всех местах, где вы выполняете программное изменение вкладок, вам необходимо вызвать вручную новый метод TfgPageControl.Changed, это приведет к немедленному срабатыванию данных событий. 
    В таком подходе есть много достоинств:
    Защита от рекурсивных вызовов. Если при переключении вкладок, вы выполняете добавление/удаление или изменение вкладок, то такие изменения могли приводить к рекурсивному срабатыванию этих событий, что в конечном итоге обычно решается введением дополнительного флаг на для отслеживания таких изменений. Сокращение числа вызовов этих событий на любые изменения вкладок. Раньше любое добавлении/удалении вкладки, могло приводить к срабатыванию этих событий, даже когда это реально не нужно. TfgCollectionView и TfgListMenu
    Очень часто вы задавали вопросы о том, как детальнее настроить работу компонента TfgListMenu. В релизе 1.9.0.0 мы добавили ряд настроек для управления цветовой схемой данного компонента. А для тех, кому и этого не хватает, мы специально мигрировать все шаблоны стилей пунктов меню из TfgListMenu в TfgCollectionView. Новые шаблоны доступны в контекстном меню компонента TfgCollectionView -> Add Style -> Menu.

    Все стили приведены на скриншоте ниже:

    TfgVideoControl
    В этом релизе мы добавили реализацию данного компонента для iOS и добавили возможность регулировать громкость видео через новое свойство TfgVideoControl.Volume.
    TfgPhoneDialer
    Мы так же реализовали TfgPhoneDialer для iOS.
    Всем спасибо за внимание и хороших выходных .
  10. Yaroslav Brovin
    В ближайшие дни выйдет новый релиз библиотеки FGX Native 1.9.3.0, главной новинкой которой будет утилита командной строки для генерации заголовочных файлов Delphi для использования Java API /Android API. 
    Утилита располагается в каталоге "$(FGX)\Tools\Java2Delphi" и в ее состав входят:
    Java2Delphi.exe - утилита. config.template.json - Шаблон конфигурационного файла, в котором указаны правила формирования итоговых Delphi-модулей. api-versions.android-28.xml - Файл с информацией об Android API 28 версии. UsedGUID.txt - набор использованных GUID значений для Delphi интерфейсов. run.bat - пакетный файл для запуска утилиты в любом месте. Перед первым применением необходимо выполнить настройку утилиты.
    Настройка
    Управление утилитой идет при помощи конфигурационного json-файла, передаваемого через аргументы командной строки. Перед первым применением, необходимо:
    1. Создать каталог в любом месте, где будут размещены все результаты генерации.
    2. Скопировать файл "run.bat" в каталог (1).
    3. Скопировать конфигурационный шаблон "config.template.json" в каталог (1) и назвать его "config.json" (название может быть любым).
    4. Отредактировать базовые настройки Java окружения:
    "javap": "$(JAVA_HOME)\\bin\\javap.exe", "jar": "$(JAVA_HOME)\\bin\\jar.exe", Java2Delphi использует две утилиты командной строки из Java SDK: "javap.exe" и "jar.exe". По умолчанию она использует переменную окружения $(JAVA_HOME). Если она у вас указана в Windows, то этот шаг можно пропустить. Если нет, то либо необходимо добавить ее с указанием местоположения Java JDK:

    или напрямую указать пути к требуемым утилитам.
    5. Указываем пути, куда будут помещены результаты генерации (опционально).
    "outputDir": ".\\Headers", "signatureOutputDir": ".\\Signatures", outputDir - каталог, куда будут помещены pas файлы с необходимыми обертками Java/Android Api. signatureOutputDir - вспомогательный каталог, куда будут помещены вспомогательные файлы с сигнатурами Java классов. После выполнения первичной настройки файла конфигурации, приступим теперь к указанию, какие Java классы надо транслировать.
    Правила генерации файлов
    Для того, чтобы сгенерировать заголовочные файлы необходимо указать:
    Jar-библиотеки, которые содержат необходимые Java классы. Указать требуемые для перевода Java классы. Указать, в какие Delphi модули разместить результирующие обертки. 1. Указываем нужные jar библиотеки.
    Библиотеки указываются в секции jars:
    "jars": [ "E:\\Development\\Android\\platforms\\android-28\\android.jar" ], По умолчанию, мы всегда подключаем jar библиотеку Android (по-этому не удаляйте ее, если хотите совместимости с Android API).
    Вам необходимо откорректировать расположение данного файла с учетом вашей системы. 
    2. Указываем требуемые для перевода Java классы.
    Теперь мы должны сказать утилите в секции "classes", какие классы нас интересуют в этих библиотеках. Здесь необходимо использовать полное название Java типов с учетом названия пакета:
    "classes": [ "java.lang.Object", "java.lang.CharSequence", "java.lang.String", "java.lang.Class", "java.lang.Boolean", "java.lang.Number", // Можно использовать * на конце пакета, чтобы выбрать все классы в данном пакете "android.provider.*", "android.view.animation.Animation", "android.view.animation.Animation.AnimationListener", "android.view.animation.Animation.Description", // и тд По умолчанию шаблон включает в себя все классы из Android API, которые используются в FGX Native. Поэтому не удаляйте эти классы, если вы хотите получить заголовочные файлы, совместимые с уже существующими хедерами в FGX Native.
    Добавьте сюда те, которые вас интересуют.
    Поскольку в некоторых библиотеках могут быть 1000 классов. То обработка такого количества классов займет много времени. Помимо этого, вы получите гигантских размеров заголовочные файлы. Поэтому лучше добавлять только те классы, которые вам реально нужны для вызовов, а не все.
    3. Указываем правила генерации Delphi модулей.
    После того, как мы перечислили интересуемые нас Java классы, нам остается только указать, в какие Delphi модули их следует поместить. Это делается через "output":
    "output": [ { "name": "Android.Api.Text", // Название Делфи модуля Android.Api.Text.pas "uses": [ // Подключаемые Делфи модули в Android.Api.Text.pas "Android.Api.JavaTypes", "Android.Api.ActivityAndView" ], "classes": [ // Java классы, обертки над которыми будут добавлены в Android.Api.Text.pas "android.text.*" ], "exclude": [ // Опционально, можно исключить некоторые классы "android.text.method.*", "android.text.util.*", "android.text.ClipboardManager*" ] } ] Генерация
    Поздравляю, теперь вы можете запустить утилиту и наблюдать, как она трудится формируя заголовочные файлы по вашим правилам.

    Обратите внимание, что первый запуск занимает много времени, так как утилита генерирует сигнатуры Java классов (именно они используются для анализа структуры Java классов) и помещает их в каталог "signatureOutputDir". Однако, последующие запуски будут выполняться моментально, за счет того, что утилита не выполняет повторную генерацию сигнатур, если она уже есть. 
    Не удаляйте файлы сигнатур, они помогут ускорить повторную генерацию заголовочных файлов.
    Разбор пропущенных классы/методов/полей
    В процессе генерации утилита выполняет много сложной работы с анализом зависимостей, доступных типов и тд. Если какой-то из Java типов не указан в секции "classes", то утилита пропустит все его использования. При этом она сообщит об этом через лог.
    Например: При генерации класса android.text.HTML были пропущены два метода fromHTML (они не попали в pas файлы), потому что не был указан тип android.text.Html$ImageGetter.
    Skipped members of the Java type: android.text.Html Methods: - fromHtml(const AArg0: JString; const AArg1: Integer; const AArg2: JHtml_ImageGetter; const AArg3: JHtml_TagHandler): JSpanned; [android.text.Html$ImageGetter] - fromHtml(const AArg0: JString; const AArg1: JHtml_ImageGetter; const AArg2: JHtml_TagHandler): JSpanned; [android.text.Html$ImageGetter] Если вам нужны эти методы, то необходимо в секцию classes добавить этот тип:
    "classes": [ "android.text.Html.ImageGetter", Обратите внимание, что в Java "$" - это разделитель для вложенных классов. Однако в конфигурационном файле вместо него надо использовать ".".
  11. Yaroslav Brovin
    Добрый день,
    Мы выложили запись прошедшего 18 февраля вебинара по теме "Пробная сессия вопросов и ответов по FGX Native". Видео доступно на нашем YouTube канале.
    На вебинаре обсуждались следующие темы:
     Android SDK/NDK; Сервисы локации; Асинхронная загрузка изображений в списках; Планы на ближайшие релизы.  
     
  12. Yaroslav Brovin
    Мы постоянно работаем над расширением возможностей библиотеки FGX Native. Чтобы разнообразие деталей в конструкторе росло, а создание приложений становилось все проще и быстрее. 
    В новом релизе 1.9.2.0 мы добавили два новых компонента: TfgVirtualListPicker и TfgNumberListPicker. Эти компоненты позволяют выбрать одно значение из списка при помощи крутящегося барабана. В основном такие компоненты использовались при выборе даты и времени:
     
    TfgVirtualListPicker
    Этот компонент не хранит у себя элементы списка и работает подобно TfgCollectionView. А именно запрашивает все необходимые данные у разработчика через специальные события: OnGetItemsCount и OnGetItemText.
    Допустим у нас есть список городов. Для упрощения названия городов мы поместим в константный массив. У вас он может находится в базе данных или в любой другой модели данных:
    const Titles: array [0..6] of string = ('Saint-Petersburg', 'Moscow', 'Chelyabinsk', 'Sochi', 'Krasnodar', 'Voronej', 'Rostov-on-don'); Для полноценной работы компонента ему необходимо знать только:
    Количество элементов в списке. Оно указывается в событии OnGetItemsCount. procedure TFormMain.fgVirtualListPicker1GetItemCount(Sender: TObject; var ACount: Integer); begin ACount := Length(Titles); end; Текстовое название элемента, отображаемое в компоненте. Оно указывается в событии OnGetItemText. Если вы не указываете обработчик для этого события, то компонент по умолчанию использует надпись следующего формата "Item %d". Каждый элемент списка имеет свой индекс, по которому компонент получает текст элемента. procedure TFormMain.fgVirtualListPicker1GetItemText(Sender: TObject; const AItemIndex: Integer; var AText: string); begin AText := Titles[AItemIndex]; end; Это минимально необходимые действия для отображения списка:

    У компонента нет ограничения на максимально допустимое количество элементов в списке. Оно может быть абсолютно любым. Значит его можно использовать для списков любого размера.
    Когда пользователь выбирает элемент, срабатывают события OnChanged, OnItemSelected, через которые вы можете узнать индекс выделенного элемента.
    Внешний вид
    На текущий момент у компонента есть только одна настройка - это цвет текста элементов TextColor / TextColorName, которая по умолчанию завязана на цвет темы "Text\Text".
    Расширяемость
    Компонент TfgVirtualListPicker разработан для возможности создания своих расширений на его базе. Это значит, что вам не нужно реализовывать этот компонент для IDE, Android и iOS. Именно на его основе сделан следующий компонент TfgNumberListPicker.
    TfgNumberListPicker
    Этот компонент является кроссплатформенным расширением TfgVirtualListPicker и предлагает возможность выбрать вещественное число из указанного диапазона.
    Диапазон задается при помощи трех свойств: границы диапазона Min, Max и шага изменения сетки чисел Step.

    По умолчанию каждый элемент отображается в виде вещественного числа с двумя знаками после запятой. Однако, вы можете это поменять одним из любых способов:
    Указать стандартный формат через FormatKind = Integer. Указать свой произвольный форма через FormatKind = Custom и Format = 'Item %f' Указать свой обработчик события OnGetItemText. В остальном компонент позволяет использовать все возможности TfgVirtualListPicker.
  13. Yaroslav Brovin

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

    В 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 совпадает по смыслу с конструктором, однако, им не является.
  14. Yaroslav Brovin

    Общая
    В ближайшие дни мы выпустим новый релиз FGX Native 1.9.0.0, в который будет включено большое количество разнообразных улучшений, новых возможностей и исправлений ошибок.
    TfgBottomSheetLayout
    Новый компонент, добавленный в 1.8.0.0, имел среди своих возможностей модальный режим отображения страницы.
    У текущей реализации модального режима есть одно ограничение, которое делает его не очень удобным для использования, а именно: у модального режима нет промежуточной стадии Collapsed (когда панель свернута в корешок, но при этом еще не блокирует основное содержимое).
    Мы решили разбить модальный режим на группу новых настроек:
    Настройки затемнения основной области содержимого TfgBottomSheetContent (TfgBottomSheetLayout.ContentShadingSettings). Теперь вы можете включать или отключать затемнение в любой момент времени, а также указать цвет, используемый для затемнения. Эта настройка особенно нужна при поддержке темной темы в вашем приложении.
    Настройка блокирования взаимодействия с основным содержимым компонента TfgBottomSheetLayout.BlockContentMode. /// <summary> /// <para> /// Режим блокирования получения любых событий основного содержимого <с>TfgBottomSheetContent</c>: /// </para> /// <list> /// <item><b>Never</b> - Никогда.</item> /// <item><b>WhenCollapsedOrExpanded</b> - Когда страница свернута или развернута.</item> /// <item><b>WhenExpanded</b> - Только когда страница разворачивается или развернута.</item> /// </list> /// </summary> TfgBlockContentMode = (Never, WhenCollapsedOrExpanded, WhenExpanded); Теперь при помощи этих двух настроек вы сможете гибко настроить модальный режим. Мы удалили старый метод ShowModal. Чтобы сделать его в 1.9.0.0 достаточно в дизайнере указать две настройки TfgBottomSheetLayout:
    BlockContentMode = WhenCollapsedOrExpanded ContentShadingSettings.Enabled = True. Буфер обмена
    Реализован новый кроссплатформенный сервис по работе с системным буфером обмена FGX.Clipboard.TfgClipboardService для Android и iOS. На текущий момент сервис позволяет работать только с текстом. Для ознакомления с работой сервиса доступен пример "Системные сервисы" -> "Текстовый буфер обмена".
    Темы
    Несмотря на то, что темы поддерживаются уже давно, с ними был ряд сложностей, связанных с использованием своих названий ресурсов. Смена темы автоматически работала отлично для всех компонентов, у которых разработчик не указывал свой ресурс. Однако, как только указывался любой ресурс (не по умолчанию), то такой ресурс считался независимым от темы и при переключении темы не менялся. Мы исправили эту ситуацию, и теперь ресурс привязывается к текущей теме формы, если ресурс указывается из текущей формы. Это позволяет сделать полноценное переключение темы для всех свойств. Если же ресурс не привязан к теме, то такой ресурс не будет меняться при смене темы у формы.
    Например, мы хотим кастомизировать оттенок панели навигации и хотим использовать "Dark Primary" цвет вместо "Light Primary". На скриншоте снизу мы указываем ресурс из текущей темы "Theme Light":

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

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

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

    Данная группа настроек не позволяет раскрасить в разные цвета все пункты меню. Это связано с тем, что компонент следует концепции Material Design, где используется общая цветовая схема. Однако теперь, вы можете указать базовые цвета схемы и цвета для разделителя для обычного режима отображения пункта меню и выделенного, чего нельзя было делать ранее.
    Помимо этого, довольно часто, используемые иконки в пунктах меню, необходимо перекрашивать. Это можно было решить на уровне дизайнера ресурсов, просто указав для иконки нужный оттенок. Однако, используемые в меню иконки могут быть использованы в других местах на практике. В такой ситуации приходилось иметь два дубликата одной и той же иконки, но с разными оттенками, что безусловно увеличивает размер приложения и усложняет дальнейшую правку ресурсов. Ситуация осложняется, когда цвет иконки при выделении отличается от цвета иконки без выделения.
    Решение данной проблемы теперь лаконично сделано через новую группу настроек Appearance.Icon, работающей по такому же принципу, как и аналогичное свойство у TfgButton. Здесь вы можете указать цвет иконки без и с выделением. В результате вам достаточно иметь всего лишь одну иконку в ресурсах данного базового размера для всех остальных мест.

    Замер размера текста
    Еще одной из самых часто запрашиваемых возможностей с вашей стороны был функционал по программному замеру размера текста. В 1.9.0.0 появится набор методов у TfgCanvas предназначенных для получения размера текста:
    function MeasureText(const AText: string; const AMaxWidth: Single; const AIsWordWrap: Boolean): TSizeF; И многое другое...
    В релиз 1.9.0.0 включено большое количество правок iOS части в части управления формами, выравниванием и тд. 
  15. Yaroslav Brovin
    В ближайшее время выйдет новый релиз 1.7.0.0, главной новинкой которого станет новый компонент TfgBottomSheetLayout. Это специальный компонент для организации отображения дочернего содержимого через выдвигаемую панель с нижней части экрана. 
    Обо всех деталях использования компонента ниже.
    Структура
    Новый компонент доступен на вкладке "FGX: Layouts" -> "TfgBottomSheetLayout" и представляет собой композицию из трех частей, аналогичную структуре компонента TfgDrawerLayout:

    TfgBottomSheet - выдвигаемая снизу страница. TfgBottomSheetContent - контейнер для основного содержимого экрана.  TfgBottomSheetLayout - координатор, отвечающий за управление отображением страницы. Состояния и управление TfgBottomSheet
    Страница может находиться в одном из трех конечных состояний:
    Страница полностью открыта - TfgBottomSheetState.Expanded; Страница свернута, но видна ее часть - TfgBottomSheetState.Collapsed;  Страница полностью скрыта - TfgBottomSheetState.Hidden.    
    В любой момент времени текущее состояние страницы можно получить через TfgBottomSheet.State. А чтобы программно управлять страницей, можно воспользоваться следующими методами TfgBottomSheet:
    /// <summary> /// Полностью модально разворачивает панель с анимацией. Основное содержимое <c>TfgBottomSheetLayout.Content</c> /// недоступно.</summary> /// <remarks>Если панель открыта, то ничего не делает.</remarks> procedure ShowModal; /// <summary>Полностью разворачивает панель с анимацией.</summary> /// <remarks>Если панель открыта, то ничего не делает.</remarks> procedure Expand; /// <summary>Сворачивает панель до заголовка с анимацией. </summary> /// <remarks> /// Если у панели нет заголовка, то полностью скрывает панель с экрана. Если панель закрыта, то ничего не делает. /// </remarks> procedure Collapse; /// <summary>Полностью скрывает панель с экрана с анимацией.</summary> /// <remarks>Если панель уже полностью скрыта, то ничего не делает.</remarks> procedure Hide; Настройка скрытия
    Если вы хотите запретить полное скрытие страницы с экрана, вы можете это сделать при помощи свойства TfgBottomSheet.IsHideable. 
    /// <summary>Может ли пользователь полностью скрыть панель?</summary> property IsHideable: Boolean read FIsHideable write SetIsHideable default DefaultIsHideable; Настройка внешнего вида
    За высоту видимой части страницы в свернутом режиме отвечает свойство TfgBottomSheet.PeekHeight:
    /// <summary>Высота части панели, которая не задвигается целиком.</summary> /// <remarks>Работает в связке со свойством<c>Hideable</c>.</remarks> property PeekHeight: Single read FPeekHeight write SetPeekHeight stored IsPeekHeightStored nodefault; По умолчанию страница имеет непрозрачный фон. Однако, в определенных случаях, удобно использовать прозрачный фон. Таким образом можно добиться любой разметки вашего содержимого и добавить любые вложенные контейнеры. За прозрачный режим отвечает свойство TfgBottomSheet.IsTransparent.

    Модальный режим
    По умолчанию панель открывается и не блокирует основное содержимое. Вы можете продолжать взаимодействовать с контентом TfgBottomSheetContent. Таким способом обычно делают панели для отображения сопутствующей детальной информации https://material.io/components/sheets-bottom. Например:
        
    Однако, гораздо чаще используется модальный режим для организации контекстного меню или же открытия нового экрана:

    В этом случае, вам необходимо открыть страницу используя метод TfgBottomSheet.ShowModal.
    Демонстрационные проекты
    В 1.7.0.0 включены два демо-проекты, которые показывают использование модального и обычного режимов использования. Их вы можете найти в ветке "Компоненты" -> "TfgBottomSheetLayout".
  16. Yaroslav Brovin
    На этой неделе всех нас ждет большой релиз библиотеки FGX Native 1.6.0.0, в который войдет много новых вещей и самое главное - Альфа версия iOS! 
    Вкратце обо всех нововведениях по порядку:
    FGX Native for iOS (Alpha)
    Это свершилось! Релиз 1.6.0.0 будет содержать Альфа версию FGX Native for iOS.
    Важно. Поскольку это альфа версия, то не стоит ожидать от нее полноценной работоспособности. Данный релиз содержит частично реализованный функционал: часть компонентов пока не реализованы, часть функционала компонентов может не работать. Однако, при этом, часть компонентов уже полностью готова.
    Теперь все проекты автоматически получают новый таргет iOS Device 64-bit. При открытии старого проекта, происходит автоматическая миграция проекта, в ходе которой:
    Добавляется платформа iOS Device 64-bit для сборки Добавляется конфигурация для деплоя iOS приложения. Добавляются настройки проекта, связанные с iOS (иконки, название пакетов и тд) Добавляются ассеты для iOS.  
    В дизайнере пока нет возможности переключиться на стиль iOS. Это будет добавлено уже ближе к полноценному релизу iOS части. 
    На текущий момент:
    Минимальная поддерживая версия iOS 11.  Не реализованы следующие компоненты : TfgCalendar, TfgAutoCompleteEdit, TfgSearchBox, TfgWebBrowser, TfgVideoControl, TfgCamera, TfgCameraPreview, TfgBarcodeScanner. Не реализована анимация. Не реализованы жесты. и тд Важно. Для сборки проекта необходимо использовать SDK не выше 13.5. С более старшими версиями SDK вы получите ошибку при линковке приложения. Мы уже занимаемся этим вопросом.
    За время разработки iOS версии у нас накопилось большое количество изменений, которые затрагивают не только iOS реализацию, но и некоторые аспекты работы библиотеки в целом.

    В процессе приходят новые идеи по улучшению уже существующего API компонентов.  Чтобы не копить все изменения отдельно от текущей версии библиотеки, мы решили соединить все изменения по iOS с текущим релизом. Так что теперь вы всегда будете в курсе текущего состояния iOS части.
    Мы ценим терпение и поддержку наших клиентов. Поэтому, поскольку релиз FGX Native for iOS немного задерживается, мы приняли решения, что не будем увеличивать цену за продление подписки в момент релиза полноценной iOS для клиентов, которые на момент релиза будут иметь активную подписку.  
    Т.е. если на момент полноценного релиза iOS у вас есть активная подписка, то стоимость продления для вас останется прежней. Для всех остальных стоимость первоначальной подписки и продления будет увеличена.
    Начиная с 1.6.0.0 мы будем включать в каждый релиз список доработок по iOS, чтобы вы всегда были в курсе.
    Обо всех найденных ошибках вы сможете сообщить нам в новой ветке форума https://forum.fgx-native.com/forum/102-ios-alpha-тестирование/. Так же в ней вы можете высказать свои пожелания по приоритету разработки того или иного функционала. Это поможет нам составить список первоочередных задач и сфокусироваться на действительно важных для вас задачах.
    Полностью переработанная кнопка TfgButton
    В дополнение к статье необходимо упомянуть, что у кнопки есть еще один важный стиль, о котором не говорилось ранее - Default. В этом стиле кнопка выглядит так, как это принято на целевой платформе. На Android - это закрашенная кнопка, в iOS - это текст без фона. Используйте этот стиль, если хотите придерживаться системного стиля отображения кнопки.  
      
    Ранее у кнопки вы могли наблюдать внутренние отступы между ее границей и фоном. Это в свою очередь немного усложняло позиционирование кнопки по отношению к другим компонентам. Поэтому в этом релизе мы убрали у Android кнопки все отступы между границей компонента и фоном. Если вы использовали эти отступы при выравнивании компонентов вашей формы, вам следует задать эти отступы напрямую через TfgButton.Margins.
    Небольшие улучшения в дизайнере
    В дизайнер добавлен ряд косметических улучшений, чтобы нашим пользователям было приятнее работать и ничто не отвлекало их от решения задач. Среди улучшений темная тема для дизайнера форм.

    А так же вспомогательная подсказка, отображающая имя выделенного компонента. Подсказка появляется при нажатии на компонент.

    Правила обрезки текста (TfgTextTrimming)
    В первоначальной версии библиотеки мы закладывали несколько способов обрезки текста: по символам, по словам и без обрезания. Однако, в результате реализации iOS и Android оказалось, что обрезка текста по словам не используется и не поддерживается ни на одной из платформ. Поэтому в данном релизе мы решили убрать значение TfgTextTrimming.Word, так как оно не работало и не имеет смысла. Если вы использовали в своих проектах TfgTextTrimming.Word, то вам необходимо переоткрыть формы, проигнорировав ошибку, и сохранить формы заново. 
    Канва TfgCanvas
    Мы добавили два важных метода, которые теперь НЕОБХОДИМО использовать при выполнении любой отрисовки на TfgBitmap - это TfgCanvas.BeginPaint и TfgCanvas.EndPaint. При вызове этих методов происходят определенные действия по переносу данных битмапа между буферами для ускорения работы с изображениями в целом. Если в уже существующем коде вы не расставите эти методы, то на iOS платформе вы не увидите результат отрисовки.
    Небольшой пример по использованию новых методов BeginPaint/EndPaint для отрисовки иконки: 
    Scale := TfgScreenManager.Main.Scale; IconSize := Ceil(DefaultIconSize * Scale); FMoreIcon := TfgBitmap.Create(IconSize, IconSize); FMoreIcon.Scale := Scale; with FMoreIcon.Canvas do begin BeginPaint; try Fill.Kind := TfgBrushKind.Solid; Fill.Color := TAlphaColorRec.Black; FillCircle(TPointF.Create(6, 12), 2); FillCircle(TPointF.Create(12, 12), 2); FillCircle(TPointF.Create(18, 12), 2); finally EndPaint; end; end; Помимо этого, добавлены упрощенные методы для отрисовки скругленных прямоугольников:  TfgCanvas.DrawRoundRect/FillRoundRect.
    Basic Аутентификация в TfgWebBrowser
    Для браузера по запросу добавлена поддержка Basic аутентификация. Чтобы выполнить аутентификация, достаточно задать свой обработчик на новое событие OnBasicAuthentificationRequest, в которое передается специальный AHandler, отвечающий за процесс аутентификации. Процесс аутентификация может выглядеть так:
    procedure TFormMain.fgWebBrowser1BasicAuthentificationRequest(Sender: TObject; const AUrl: string; const AHandler: IFGXBasicAuthentificationHandler); begin TfgDialogs.InputQuery('Input credentional data', ['User name', 'Password'], ['', ''], procedure (const AResult: TModalResult; const AValues: TArray<string>) begin if AResult = mrOk then AHandler.Proceed(AValues[0], AValues[1]) else AHandler.Cancel; end); end; Если аутентификация не прошла, то браузер будет пытаться пройти ее повторно, повторно вызывая OnBasicAuthentificationRequest. 
    Новые параметры экрана TfgScreen
    Для TfgScreen добавлен новый параметр SafeAreaPadding, который позволяет узнать, какие области на экране заняты системными элементами. Если раньше эти отступы можно было получить только в событии формы TfgForm.OnSafeAreaChanged, то теперь их можно получить в любой момент с помощью TfgScreenManager.Main.SafeAreaPadding.
    Tip: Не забывайте, что коэффициент масштабирования экрана всегда можно получить кроссплатформенным способом через TfgScreenManager.Main.Scale.
    Другие улучшения
    В этом релизе также содержится большое количество исправлений ошибок. 
    Всем спасибо за внимание!
  17. Yaroslav Brovin
    В процессе реализации уже существующих компонентов библиотеки FGX Native для iOS мы иногда сталкиваемся с тем, что для полноценной кроссплатформенной разработки приложений текущего функционала компонентов уже не хватает. Например, в панели TfgNavigationBar (iOS) для кнопки навигации часто иконку дополняют текстом, в то время, как в андроиде текст никто не добавляет. Однако, речь в этой новости пойдет не об этом компоненте, а об обычной кнопке TfgButton.
    С виду кнопка - один из самых простых компонентов. Однако, на практике, это довольно сложный компонент, если брать во внимание большое разнообразие в мире кнопок разных стилей и видов. Было много причин, почему кнопка TfgButton в библиотеке довольно ограничена в своих возможностях. Главная из них - это как сделать действительно удобный набор настроек, который угодил бы большинству и при этом был бы прост и гибок в настройке. 
    Рад поделиться, что в процессе реализации iOS и изучения Material Design,  мы пришли к удобному на наш взгляд набору настроек кнопки. 
    Стили
    Теперь кнопка может иметь один из трёх базовых стилей:

    Text - обычная текстовая кнопка, без рамки, с возможностью привязать иконку. Этот тип предназначен для третьестепенных действий. Outlined - это плоская Text кнопка с окантовкой. Этот же тип используется для второстепенных действий. Contained - это Outlined кнопка + заливка области. Естественно, каждый вид кнопки должен иметь свой индивидуальный набор настроек. И желательно, чтобы инспектор объектов отображал только актуальные для данного стиля настройки. Так, например, если используется Text кнопка, то для нее должны быть доступны настройки рамки и заполнения.
    Поэтому теперь каждый стиль кнопки динамически подгружает свой набор настроек. Выбор стиля выполняется в инспекторе объектов в новом свойстве Appearance:

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

    Настройки элементов
    Стоит отметить, что теперь можно отдельно управлять отображением каждого элемента кнопки:
    Текст Иконка Рамка Наполнение Таким образом, теперь для иконки можно отдельно указать оттенок прямо на уровне компонента. Это особенно удобно в случаях, когда вы используете одну и ту же иконку в разных местах с разными оттенками. Если ранее для решения подобной задачи было необходимо делать копии одной и той же иконки и менять ей оттенок в дизайнере ресурсов, то сейчас достаточно установить свойство Appearance.Icon.TintColorName равным "Theme\Text\Icon" (к примеру).

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

    При этом, кнопка с Contained стилем умеет автоматически подбирать цвета текста и иконки на основании цвета фона (если вы не указали свои цветовые предпочтения явно?

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

    Для рамки кнопки мы предусмотрели возможность изменить значение радиуса скругления и толщину рамки.

    Изменения API
    Переименованы свойства ImageName -> IconName, ImageLocation -> Appearnace.Icon.Location, так как на наш взгляд иконка - это небольшой графический элемент, который преимущественно отображается на кнопке. При этом мы оставили обратную совместимость, так что при запуске старого проекта, старое значение из свойства ImageName и ImageLocation будет автоматически прочитано. Свойства TextSettings и TextShadow теперь находятся в группе настроек Appearance.Text. Они так же будут успешно восстановлены для старых проектов. Старые типы кнопок TfgButonKind.Raised и Flat теперь не будут поддерживаться и при открытии проекта автоматически будут сконвертированы в Contained и Text стили. P.S. Всем хороших выходных и успешного кодирования ?
  18. Yaroslav Brovin

    Общая
    В ближайшем релизе 1.5.0.0 мы добавили пару небольших улучшений, которые немного помогут вам проще разрабатывать ваши мобильные приложения.
    1. Отступы для TfgLabel
    В разработке пользовательского интерфейса довольно часто встречается задача визуального выделения текстовых меток/тегов. Обычно для визуального выделения используется фон в виде скругленного прямоугольника.
     
    Раньше такая задача решалась при помощи двух компонентов:
    Контейнер TfgLayout с требуемыми отступами для текста и с фоном BackgroundName в виде 9-path изображения. Метка TfgLabel, куда непосредственно выводится текст. Теперь же у TfgLabel есть специальное свойство ContentPadding, позволяющее добавить внутренние отступы, используемые при отображении текста. В результате метка легко получается на базе одного компонента TfgLabel с фоном BackgroundName  и требуемыми отступами.

    2. Оттенок для кнопки TfgButton
    Теперь для кнопки TfgButton добавлены новые свойства TintColor и TintColorName, позволяющие перекрасить системный цвет кнопки.

    3. Android AlarmManager
    Мы добавили небольшой пример по использованию Java кода из  FGX Native приложения. Новый демонстрационный пример показывает, как сделать на языке Java свой BroadcastReceiver и использовать его в связке с FGX Native приложением. Данный пример пригодится разработчикам, которым необходимо более тесная интеграция с Android API.
    4. Автосайз
    iOS
    Так же мы с нуля реализовали TfgDrawerLayout для iOS
    drawer-iOS.mp4.648b868510783b05479fa65efce46878.mp4
  19. Yaroslav Brovin
    Всем доброго дня,
    При разработке кросс-платформенного приложения важной базовой составляющей является определение размеров компонентов. С одной стороны нет ничего проще, чем задать желаемый размер любому компоненту библиотеки FGX Native или задать правило выравнивания компонентов при помощи FlexBox. Однако, кросс-платформенная разработка накладывает определенные трудности в этом подходе. А именно зачастую размер компонентов зависит не только от других компонентов, но и от содержимого. И если с первым отлично справляется FlexBox, то со вторым в FGX Native нужно использовать метод для расчета размеров компонентов TfgControl.MeasureSize, и будем честны, это было временное решение.
    Мы всегда стараемся сделать библиотеку FGX Native удобной для использования, чтобы разработчик мог концентрироваться в коде на бизнес логике своего приложения, а не программной "настройке" UI. Одним из грядущих улучшений будет поддержка автоматического расчета размеров компонентов. Мы внедрили на нижнем уровне поддержку Autosize. Теперь на уровне появится новое свойство TfgControl.Autosize, которое отвечает за то, что именно нужно автоматически посчитать: ширину, высоту или обе величины. Если в ходе выравнивания компонента система понимает, что компонент имеет фиксированный размер, то в этом случае компонент может автоматически его рассчитать. Так например задание Autosize = [Height] для TfgTraсkBar автоматически посчитает нужную высоту компонента, а вот указание Autosize = [Width] для этого компонента ни на что не повлияет. 

    Не смотря на то, что сам механизм внедрен на нижнем уровне, реально это свойство в ближайшем релизе будет доступно только для нескольких компонентов: TfgSwitch, TfgTrackBar, TfgNavigationBar и возможно TfgLabel. Если с TfgSwitch и TfgTrackBar в целом понятно,  то вот на счет TfgNavigationBar  стоит отдельно отметить, что теперь этот компонент умеет в автоматическом режиме расчета высоты учитывать отступы у формы SafeArea и наличие заголовка и подзаголовка. И если раньше необходимо было программно отслеживать изменения отступов области SafeArea в TfgForm.OnSafeAreaChanged и на основании значений отступов вычислять руками высоту панели навигации, то сейчас все это будет происходить автоматически.



    Данное нововведение особенно актуально в свете предстоящего появления iOS. Так как в iOS используются другие шрифты, размеры текста и размеры компонентов. И чтобы сделать действительно универсальное приложение без этой функциональности будет очень сложно.
    Всем хорошей рабочей недели!
  20. Yaroslav Brovin
    Всем доброго дня!
    У нас есть много хороших новостей на конец уходящего лета ?.
    Во-первых. Мы практически полностью разработали новые компоненты под iOS TfgNavigationBar, TfgListMenu, TfgDatePicker, TfgTimePicker, TfgTimeEdit, TfgDateEdit, TfgCheckBox, TfgRadioButton, TfgPageControl, TfgTrackBar, TfgRectangle, TfgLine, TfgSvgPath и тд. Закончили с TfgCollectionView и реализовали полноценную поддержку стилей, "Drag & Drop" и "Pull To Refresh".
    reordering.mp4.1e0e3a9268a4c8a4cb40e3a8b75d6b03.mp4 pull-to-refresh.mp4.87c902179beda7dacf55c9f028c06423.mp4
    Во-вторых. Мы реализовали полноценную TfgCanvas для iOS с поддержкой градиентов, разных кистей и отрисовкой на битмапах.
    В-третьих. Мы улучшили поддержку TfgPath. И теперь мы полностью поддерживаем весь стандарт доступных path команд w3c.
    В-четвертых. Реализовали диалоги и пикеры для выбора даты и времени.
    В-пятых. Реализовали TfgForm.OnSafeAreaChanged и добавили возможность получать состояние приложение напрямую у TfgApplication.State.
    В-шестых. Запустили FGX Native Global Demo и большая часть экранов уже открывается и успешно работает.
     
    Всем хорошего окончания этих выходных!
  21. Yaroslav Brovin
    Всем хорошей пятницы,
    Немного новостей с полей разработки iOS ?. Мы продолжаем активно работать над реализацией iOS части библиотеки FGX Native и хотим поделиться с вами текущим статусом ?.
    1. Полностью реализованы новые компоненты
    TfgScrollBox, TfgVerticalScrollBox, TfgHorizontalScrollBox, TfgCardPanel, TfgSwitch, TfgTimer
    CardPanel-Demo.mp4.c88e1292626fcdf90ba849929b1bc238.mp4
    2. Частично реализована поддержка TfgBitmap
    Реализованы базовые операции с TfgBitmap: 
    Создание. Работа со скейлом Чтение из разных источников. Сохранение. 3. Добавлена поддержка ресурсов
    Научили iOS приложение работать с нашими ресурсами. Теперь app пакет содержит ресурсы FGX Native приложения.
    4. Реализованы вспомогательные сервисы
    Реализована часть служебных сервисов (IFGXLocaleService, IFGXApplicationInfoService, IFGXScreenService) используемых, в том или ином виде в существующих компонентах и вспомогательных классах.
    5. Частично реализован TfgCollectionView
    Реализована базовая функциональность списка. Создание элементов. Поддержка стилей. Связывание данных. 
    collectionView-3.mp4.3594030bf632722305b29ae89b970b55.mp4 CollectionView.mp4.83702aa8066d5e7d28cb2594fa9c56a9.mp4
    6. Частичная реализация TfgImage
    Реализованы все методы отображения изображений, кроме маски.
    7. Реализация диалогов
    Реализованы диалоговые окна TfgDialogs для отображения сообщений и диалогов с кнопками.
    8. Добавлены новые хедеры для iOS 13.
    Транслированы и добавлены свои собственные хедеры для iOS API.
  22. Yaroslav Brovin
    Всем доброго дня!
    Как и обещал ранее, перед релизом 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:+')) Это все изменения, которые необходимо сделать.
  23. Yaroslav Brovin
    Всем доброго дня,
    Немного полезной технической информации о следующем релизе 1.4.0.0:
    Поддержка RAD Studio 10.4
    Новый релиз будет посвящен поддержке RAD Studio 10.4 с одной стороны и прекращению поддержки RAD Studio 10.2 с другой стороны. Основные причины:
    Отсутствие жизненно важной поддержки Android 64-bit Нет поддержки push-уведомлений на уровне IDE Новый Java-Delphi мост
    В версии 1.4.0.0 будет полностью обновленный Android-Delphi мост. Он будет основан на нашей текущей реализации моста. Однако он не будет совместимость со старыми заголовочными файлами.
    Это значит, что если вы используете нативное Android API в ваших приложениях, то в версии 1.4.0.0 нужно будет выполнить миграцию. Миграция будет простой. Инструкция будет детально дана ближе к релизу.
    Причина обновления моста связана с удалением поддержки ARC в 10.4. Это приводит к нерациональному и неоправданному использованию делфи классов, как обертки над Java классами. Так как, используя такой подход, необходимо удалять руками все объекты моста. При этом код становится очень тяжелым для восприятия и неудобным для использования. 
    Обновленная версия моста будет улучшенным синтезом нашей текущей реализации и подхода с использованием делфи интерфейсов. Он сохранит все принципы работы с классовыми членами (поля, методы) и способом создания Java объектов. Однако теперь работа с созданным объектом будет осуществлять через интерфейс, а не класс, как было ранее.
    Всем спасибо за внимание и хорошего рабочего дня!
  24. Yaroslav Brovin
    и 
    Что связывает итальянскую конференцию DelphiDay по Delphi и FGX Native?
    Правильно! В ближайшие дни FGX Native будет представлена на одной из крупнейших Delphi конференций Европы в Италии, на родине Марко Канту. Это очень важный шаг в истории развития проекта, потому как библиотека постепенно выходит на международный уровень. Возможностью рассказать о себе широкому кругу иностранных разработчиков мы обязаны нашему клиенту из Италии @claudio.piffer, который сам проявил инициативу и подготовил интереснейшую презентацию о  FGX Native. В данной презентации  Клаудио расскажет о главных возможностях библиотеки и поделится своими впечатлениями об её использовании. 
    От всего сердца желаем Клаудио удачи и с нетерпением ждём его выступления.
    Ниже опубликована вся информация о конференции.
    P.S. Выступление будет на итальянском.
    Когда: 11 июня 12:30 (по московскому времени) Программа конференции: https://www.delphiday.it/ Язык: итальянский Заголовок: FGX Native: мобильная альтернатива FMX Спикер: @claudio.piffer  Анонс:
  25. Yaroslav Brovin
    Мы стараемся делать так, чтобы FGX Native стала эффективным инструментом ? для разработчиков, приносила результаты и доставляла удовольствие от работы ?.
    Мы постоянно работаем над расширением возможностей и предоставляем новый функционал. Однако, с учетом молодости проекта FGX Native по нему не так много информации.
    Эффективность использования зависит от ваших умений и навыков. А для развития этих умений и навыков нужны обучающие материалы ?‍?, примеры правильного использования.
    Мы решили провести небольшой пробный эксперимент и для начала записать пару обучающих видео уроков по использованию FGX Native.
    Рад представить вам первый, самый базовый урок для начинающих о начале разработки мобильных приложений с FGX Native и Delphi. В уроке рассматривается:
    Настройка рабочего окружения; Создание Hello World мобильного приложения; Запись и чтение логов в FGX Native. Следующий урок будет о системе выравнивания Flex в FGX Native. Рассмотрим типовые задачи и их решения. Сверстаем сложный макет приложения. Чтобы не пропустить, подписывайся на новый официальный канал FGX Native: https://www.youtube.com/channel/UCd818Et5Fi0Iy53YouBce3w 
    Приятного обучения:
     
×
×
  • Create New...