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.14.5.0 посвящен полноценной поддержке RAD Studio 11.2 и новой платформе iOS Simulator ARM 64-bit. Помимо этого, мы немного улучшили средства просмотра Андроид логов и компонент TfgButton.
    iOS Simulator ARM 64-bit
    В этой версии добавлена поддержка iOS Simulator ARM 64-bit. Теперь вы можете запускать ваши FGX Native приложения на симуляторе. Однако, помните, что данный симулятор работает только на процессорах Apple. Так же компоненты авторизации через Facebook Login не поддерживаются в данный момент на симуляторе.
    Улучшения Android Log Viewer
    В этой версии, мы почерпнули несколько интересных идей у Android Studio и реализовали продвинутую раскраску сообщений. Теперь сообщения одного одного процесса визуально выделяются одним и тем же цветом. Это улучшает визуальное разделение сообщений разных процессов.

    Внутренние отступы TfgButton
    Помимо поддержки 11.2 добавлена возможность менять стандартные внутренние отступы у кнопки TfgButton. Иногда требуется убрать отступы, чтобы расширить область отображения надписи и иконки. Теперь это можно сделать при помощи свойства TfgButton.Appearance.ContentPadding.

    RAD Studio 11.2 
    Новая версия RAD Studio 11.2 сломала обратную совместимость некоторых пакетов дизайнера с 11.0 и 11.1. В результате чего версия 1.14.4.0 не работает на 11.2, а 1.14.4.1 не работает на 11.1. В этом релизе мы поставляем две версии дизайнера: отдельно для 11.0-11.1 и 11.2. При установке необходимо выбрать интересующую вас версию.
    Спасибо за внимание, 
    Ваша команда FGX Native
  2. Yaroslav Brovin
    Продолжаем освещать новинки обновления 1.15.0.0. И в этот раз речь пойдет про оптимизации старта приложения и новые возможности нашей утилиты Java2Delphi.
    Ускорение запуска FGX Native приложения на Android
    Одним из важных изменений в области работы Java-Delphi мосту - является ускорение запуска FGX Native приложения на Android. До 1.15.0.0 холодный старт пустого приложения мог занимать пару секунд. В 1.15.0.0 мы реализовали отложенную инициализацию Java оберток, в результате чего это позволило нам ускорить старт пустого приложения до ~2-х раз.
    Улучшения в Java2Delphi
    Поддержка AAR
    В новой версии Java2Delphi теперь можно использовать AAR библиотеки. Для этого их нужно указать в конфигурационном файле в ветке "aars".
    "aars": [ "$(FGX)\\Libs\\Android\\fgx.admob.aar" ], Deprecated/Introduced для полей
    Android API меняется от версии к версии. Какие-то типы объявляются устаревшими, какие-то удаленными, а какие-то новыми. Глядя на заголовочный файл тяжело понять, какой метод в какой версии Android доступен. Ранее мы вносили специальные пометки в заголовочные файлы для методов. В этом релизе мы  генерируем аналогичные пометки их и для полей. Так что, теперь можно открыв заголовочный файл, сразу понять в какой версии был добавлен тот или иной элемент, а когда он помечен, как устаревший.
    function isConvex: Boolean; deprecated 'Deprecated in 30'; function addWhitelistedRestrictedPermission(const AArg0: JString; const AArg1: JString; const AArg2: Integer): Boolean; // Introduced in 29'; { constants } property colorMode: Integer read _GetColorMode write _SetColorMode; // Introduced in 26'; Умная генерация параметров при зависимостях
    Одним из главных отличий Java от Delphi является разная реализация пространств имен и доступов к типам. В Delphi по умолчанию два модуля не могут использовать друг друга в интерфейсной части. Появляется так называется циклическая зависимость. В то же время в Java в рамках одного пакета все классы могут использовать друг друга. Получается, что заголовочные обертки для всех классов одного пакета в Java должны были быть объявлены в одном Delphi модуле. Это в свою очередь приводило к значительному росту заголовочного файла. Так как нельзя размещать взаимно используемые классы в разных модулях.
    В этом релизе мы так же улучшили это. Теперь вы можете раскидывать классы по разным модулям, даже если они взаимно используют друг друга. Чтобы избежать циклической зависимости, класс в одном из модулей заменяется на общий JObject. 
    Например:
    Мы выделяем все типы, связанные с анимацией в модуль Android.Api.Animations. Эти типы используют JView, который объявлен в  "Android.Api.ActivityAndView". Часть типов анимации используются в классе Android.Api.ActivityAndView.JView. Так геттер getAnimation должен вернуть объект JAnimation. Однако, данный тип, объявлен в Android.Api.Animations.
    JView = interface(JObject) // function getAnimation: JAnimation; // end; Получается циклическая зависимость. И раньше такой код не мог быть скомпилирован. Сейчас же такая зависимость заменяется генератором на такой код с указанием оригинального класса в фигурных скобках:
    JView = interface(JObject) // function getAnimation: JObject {JAnimation}; // end; Чтобы при использовании получить объект JAnimation, достаточно написать такой код:
    var Animation: JAnimation; Animation := TJAnimation.Wrap(View.getAnimation);
  3. 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
  4. 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.
    Другие улучшения
    В этом релизе также содержится большое количество исправлений ошибок. 
    Всем спасибо за внимание!
  5. 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".
  6. 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 части в части управления формами, выравниванием и тд. 
  7. 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.
    Всем спасибо за внимание и хороших выходных .
  8. 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.
  9. Yaroslav Brovin
    Добрый день,
    Мы выложили запись прошедшего 18 февраля вебинара по теме "Пробная сессия вопросов и ответов по FGX Native". Видео доступно на нашем YouTube канале.
    На вебинаре обсуждались следующие темы:
     Android SDK/NDK; Сервисы локации; Асинхронная загрузка изображений в списках; Планы на ближайшие релизы.  
     
  10. 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 
    Приятного обучения:
     
  11. 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;  
  12. Yaroslav Brovin
    Добрый вечер, уважаемые Delphi разработчики.
    Не секрет, что в Java/Kotlin мире огромное количество готовых и бесплатных к использованию Android библиотек, чего нельзя сказать о Delphi. Более того, если речь идет про внешние устройства для устройств на базе Android, то производитель всегда поставляет SDK в виде Android библиотеки.  Будь то софт для работы с устройством по USB, промышленный сканер, медицинское оборудование или что-либо другое, все обычно имеет готовый SDK. Если же вы хотите воспользоваться облачными сервисами аналитики от Google или Yandex, то опять же самым удобным вариантом будет использование готового поставляемого SDK.
    К сожалению, надо отметить, что крайне редко производитель поставляет SDK для языка Delphi. Что в итоге делает процесс интеграции SDK на другом языке в Delphi не самой тривиальной задаче и требует специальных интеграции со стороны разработчиков. В этой статье мы рассмотрим о новых возможностях по интеграции библиотек для Android приложения на базе FGX Naitve.   
    С радостью хотим с вами поделиться новыми возможностями в FGX Native в области интеграции сторонних Android библиотек в ваше приложение. Долгое время Delphi не позволяла и до сих пор не позволяет с легкостью добавлять существующие Android-библиотеки. Это значит, что весь мир использования существующих Java библиотек под Android для Delphi был практически недоступен.  Почему это так, и в чем трудности, я затронул в статье в главе "Почему переход на AndroidX не был выполнен ранее?":
    И о чем я рассказал в статье (раздел "Поддержка сторонних Android-библиотек")
    Раньше вы могли добавлять только JAR библиотеки (стандартная возможность RAD Studio IDE). Чуть позже, мы добавили поддержку AAR библиотеки (FGX Native 1.15.0.0). А начиная с FGX Native 1.15.2.0 мы расширили эту поддержку и теперь вы можете просто указать название публичной библиотеки, без необходимости искать JAR/AAR и всех зависимостей.
    Андроид библиотека
    Андроид библиотека идентифицируется тремя параметрами:
    Группа - Уникальное название группы, в рамках которой могут находиться разные библиотеки. Обычно название группы отражает название компании и направление библиотек.
    Например: "com.yandex.android" Артефакт - короткое название библиотеки в рамках группы (1).
    Например: "mobmetricalib" Версия. Номер версии.
    Например: "5.2.0" Объединенные параметры, разделенные ":", квалифицируют библиотеку среди остальных: "com.yandex.android:mobmetricalib:5.2.0".
    Управление используемыми библиотеки в приложении FGX Native для Android осуществляется через наш менеджер, доступный через главное меню:  "Project -> FGX Android Libraries".

    Существует два способа интеграции Андроид-библиотеки.
    1. Старый. Долго, сложно и не поддерживает транзитивные зависимости. Добавление файла библиотеки и всех зависимостей вручную. 
    Для этого вам надо:
    Cкачать физический файл библиотеки в JAR или AAR формате. Определить все используемые транзитивные зависимости и скачать их файлы так же. После чего вручную добавить их через мастер "FGX Android Libraries". Например, чтобы этим способом добавить поддержку Yandex AppMetrika версии 5.2.0 нужно найти и добавить в сумме 11 файлов библиотек:

    2. Новый. Указание названия библиотеки для автоматического скачивания библиотеки и всех зависимостей и интеграция в FGX Native приложение. 
    Начиная с 1.15.2.0 достаточно указать полное название библиотеки и все остальное произойдет автоматически.
    Чтобы добавить новую зависимость, нужно нажать на кнопку "+" и выбрать "Зависимость-библиотека". После чего указать полное имя зависимости или воспользоваться быстрым поиском для поиска интересуемой зависимости.

    Таким способом достаточно указать только полное наименование библиотеки. Например, та же Yandex AppMetrika добавляется путем добавления зависимости на "com.yandex.android:mobmetricalib:5.2.0".
    Репозитории
    Все публичные Android библиотеки обычно хранятся в репозиториях. Репозиторий - это центральное хранилище, где можно найти библиотеку нужной версии, нужного автора (пакет), узнать используемые зависимости (библиотеки часто используют другие для своей работы). Среди наиболее известных публичных репозиториев:
    Maven Central - https://mvnrepository.com/ Google Maven - https://maven.google.com/web/index.html Помимо общеизвестных, любой желающий может развернуть свой репозиторий и хранить там свои наработки. В таком репозитории можно получить информацию о любой библиотеке. Например, Яндекс предлагает библиотеку "mobmetricalib" для работы с AppMetrika. Библиотека называется "com.yandex.android » mobmetricalib" и может быть найдена в одном из таких репозиториев:
     
    А так же здесь вы можете узнать, какие другие библиотеки использует данная библиотека:

    FGX Native подключает два публичных репозитория по умолчанию (Maven Central, Google Maven). Вы можете управлять списком репозиториев и добавлять свои, открыв список кнопкой "Репозитории", если это требуется:
     
    Как использовать добавленные библиотеки в коде?
    После того, как вы интегрировали стороннюю библиотеку, встает вопрос о том, как вызвать API, которое она поставляет. Для этого вам нужно получить заголовочные файлы. Это можно сделать при помощи нашей утилиты Java2Delphi, входящей в поставку FGX Native.
    Описание работы утилиты описано в этой статье:
    Всем спасибо за внимание
  13. Yaroslav Brovin
    Добрый день, уважаемые разработчики. 
    Скоро выйдет новое крупное обновление 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
    Спасибо за внимание.
  14. 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:+')) Это все изменения, которые необходимо сделать.
  15. Yaroslav Brovin
    Добрый день, уважаемые пользователи 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 успешно запускаются и работают.
     
    Если при тестировании вы столкнетесь с проблемами, просьба сообщить нам о них, и мы постараемся их оперативно поправить.
    Всем спасибо за внимание и хорошей продуктивной недели!
  16. 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.
  17. Yaroslav Brovin
    Добрый вечер,
    Мы плотно работаем над новой версией библиотеки FGX Native, в которую войдут новые компоненты-контейнеры и многие другие улучшения. В этой статье мы хотели бы поделиться двумя новыми компонентами-контейнерами TfgVirtualPagerLayout и TfgPagerLayout, которые появятся в релизе 1.13.1.0. 
    TfgVirtualPagerLayout
    Это базовый компонент, который предназначен для динамической загрузки/выгрузки страниц по мере их необходимости. В отличии от привычных подходов с добавлением вложенных компонентов заранее в дизайнере, этот компонент запрашивает загрузку/выгрузку страницы через события OnLoadPage и OnUnloadPage по мере их необходимости. Это значит, что фактически вместо загрузки 10-20 страниц, он загружает только видимую и еще 1-2 смежных в зависимости от текущего состояния компонента и, как следствие, ускоряет загрузку приложения.
    На базе данного компонента можно легко сделать оптимизированный слайдер изображений. Например вот такой:
    PhotoSlider.mp4
    Компонент не хранит все страницы у себя и работает по cхожему c TfgCollectionView принципу, те запрашивает необходимую информацию у разработчика через набор событий. Перед использованием компонента, вам необходимо написать обработчики для 3-х событий:
    OnGetPageCount - вернуть общее количество страниц в компоненте. OnLoadPage - вернуть компонент страницы. Это может быть любой визуальный компонент. Вы можете создавать  страницу в этом событии динамически, а можете реализовать пул объектов, чтобы повторно использовать выгруженные ранее страницы. OnUnloadPage - можно выполнить уничтожение страницы или вернуть страницу в пул объектов для дальнейшего повторного использования. Типичным примером реализации данных событий может быть такой код, создающий страницы с текстом на базе TfgLabel:
    procedure TFormMain.fgVirtualPagerLayout1GetPageCount(Sender: TObject; var ACount: Integer); begin // Сообщаем компоненту о количестве страниц. ACount := 100; end; procedure TFormMain.fgVirtualPagerLayout1LoadPage(Sender: TObject; const AItemIndex: Integer; var APage: TfgControl); var LPage: TfgLabel; begin // Создаем страницу на базе TfgLabel, которая будет отображать номер страницы. LPage := TfgLabel.Create(nil); LPage.Font.Size := 30; LPage.Text := Format('Page %d', [AItemIndex]); APage := LPage; end; procedure TFormMain.fgVirtualPagerLayout1UnloadPage(Sender: TObject; const AItemIndex: Integer; const APage: TfgControl); begin // Удаляем страницу. APage.Free; end; В результате получим:
    Basic_Text_Pages.mp4
     
    Пул страниц
    В этом примере вы можете обратить внимание, что если страницы по структуре одинаковые, то смысла удалять страницу и создавать заново особо не имеет смысла. Поэтому для этого случая, можно написать простой пул объектов, который не будет удалять вкладку, как только она не нужна, а складывать ее в список для дальнейшего повторного использования. Для реализации пула страниц создадим два списка:
    Список используемых страниц в компоненте в текущий момент времени - FAcquiredPages. Список использованных страниц, которые уже не используются в текущий момент времени - FReleasedPages. Код по объявлению списков выглядит так:
    type TFormMain = class(TfgForm) private FAcquiredPages: TList<TfgLabel>; FReleasedPages: TObjsetList<TfgLabel>; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; end; var FormMain: TFormMain; implementation {$R *.xfm} uses System.SysUtils, FGX.Application, FGX.Dialogs, FGX.Log; { TFormMain } constructor TFormMain.Create(AOwner: TComponent); begin inherited; FAcquiredPages := TList<TfgLabel>.Create; FReleasedPages := TObjsetList<TfgLabel>.Create; end; destructor TFormMain.Destroy; begin FreeAndNil(FAcquiredPages); FreeAndNil(FReleasedPages); inherited; end; Теперь, когда компонент запрашивает страницу мы выполняем простые действия:
    Если страница есть в пуле, то мы ее извлекаем. Если свободной страницы в пуле нет, то создаем новую. Когда же страница выгружается компонентом, мы просто возвращаем ее в пул.
    procedure TFormMain.fgVirtualPagerLayout1GetPageCount(Sender: TObject; var ACount: Integer); begin ACount := 100; end; procedure TFormMain.fgVirtualPagerLayout1LoadPage(Sender: TObject; const AItemIndex: Integer; var APage: TfgControl); var Page: TfgLabel; begin if FReleasedPages.Count = 0 then begin // В пуле нету свободных страниц, создаем новую Page := TfgLabel.Create(nil); Page.Font.Size := 30; end else // В пуле есть свободная страница, берем ее Page := FReleasedPages.ExtractAt(0); // Переносим страницу в список используемых страниц. FAcquiredPages.Add(Page); // Задаем текст и возвращаем страницу Page.Text := Format('Page %d', [AItemIndex]); APage := Page; end; procedure TFormMain.fgVirtualPagerLayout1UnloadPage(Sender: TObject; const AItemIndex: Integer; const APage: TfgControl); begin TfgAssert.IsClass(APage, TfgLabel); // Возвращаем страницу в пул для повторного использования FAcquiredPages.Remove(APage as TfgLabel); FReleasedPages.Add(APage as TfgLabel); end; Теперь мы получили такое же приложение, как и без использования пула, но теперь страницы не пересоздаются по мере их пролистывания, а повторно используются. Тем самым мы ускоряем процедуру загрузки страниц. 
    Таким образом, этот компонент позволяет ускорить загрузку приложения за счет загрузки только необходимых страниц, а не всех сразу. На базе данного компонента можно легко реализовать слайдер изображение с большим количеством изображений и многое другое.
    Динамическое изменение страниц
    Поскольку компонент запрашивает страницы и их количество у разработчика, то при любом изменении количества страниц, удаление/добавление страниц необходимо уведомить об этом компонент при помощи следующих методов:
    Reload - Уведомляет компонент о том, что список страниц изменился и надо заново его построить. NotifyPageInserted - Уведомляет компонент, что в список вставлены новые страницы по указанным индексам. NotifyPageRemoved - Уведомляет компонент, что из списка нужно удалить страницы по указанным индексам. Состав страниц нельзя менять в процессе переключения вкладок!
    Дополнительные события
    Данный компонент предлагает широкий набор дополнительных событий, позволяющих полностью контролировать процесс смены вкладок:
    OnChanged - Вызывается только при интерактивной смене вкладки, как только компонент понимает на какую вкладку окончательно переключается пользователь.  OnBeginDragging - Вызывается, когда пользователь опустил палец на экран и начал двигать содержимое.  OnEndDragging - Вызывается, когда пользователь поднял палец с экрана и закончил двигать содержимое. OnBeginScrolingAnimation - Вызывается, когда началась анимация смены вкладки. OnEndScrolingAnimation - Вызывается, когда анимация смены вкладки закончилась. TfgPagerLayout 
    Этот компонент-контейнер построен на базе TfgVirtualPagerLayout и в отличии от TfgVirtualPagerLayout выравнивает все добавленные в него компоненты по страницам. Он не выгружает/загружает страницы и по сути является аналогом TfgPageControl. Вы добавляете в него любые компоненты и TfgPagerLayout сам осуществляет их выравнивание и переключение.
     
  18. Yaroslav Brovin
    Добрый день, уважаемые разработчики. 
    Продолжаем обзор новых возможностей 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 информацию, дайте знать, мы добавим.
    Уверены данные нововведения позволят вам сократить ваш код.
    Спасибо за внимание
  19. Yaroslav Brovin
    Теперь в FGX Native появится новый компонент для отображения рекламы в вашем приложении TfgBannerAd. Компонент позволяет монетизировать ваше приложение и получать пассивный доход.
    Компонент поддерживает несколько видов баннера, поэтому вы всегда сможете подобрать подходящий размер.
    В качестве рекламной площадки используется Google AdMob.
      
    Компонент будет доступен в 1.1.6.0.
  20. Yaroslav Brovin
    В ближайшем релизе FGX Native 1.1.4.0 появится расширение возможностей TfgCollectionView. Речь идет о перетаскивании элементов списка для ручного упорядочивания элементов.
    video_2020-03-27_04-16-58.mp4.01ba77268ea2bcd5c7b56ad7cf398dcc.mp4
    Для того, чтобы воспользоваться новым функционалом нужно:
    1. Определить, за какой компонент элемента можно будет выполнять перетаскивание элемента.
    Например, можно использовать TfgImage с общепринятой иконкой перетаскивания элементов.
    2. Указать для такого компонента стиля имя через LookupName.

    3. Указать в настройках TfgCollectionView имя компонента из пункта (3).

    4. После перетаскивания элементов в списке, отразить изменение последовательности элементов в вашей модели данных в событии OnMovingItem. 
  21. 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
  22. 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 объектов. Однако теперь работа с созданным объектом будет осуществлять через интерфейс, а не класс, как было ранее.
    Всем спасибо за внимание и хорошего рабочего дня!
  23. Yaroslav Brovin
    В ближайшем релизе 1.1.4.0 появится возможность указывать форматированный текст, используя упрощенный HTML формат.
    Чтобы использовать форматированный текст необходимо:
    1. Указать в свойстве Text HTML разметку.
    Например: 
    <font color='red'>red</font> <b>and</b> <font color='blue'>blue</font> Внимание! Поддерживается только форматирование текста, такое как изменение цвета и стиля текста.
    2. Указать, что нужно воспринимать исходный текст, как HTML разметка (TextType = HTML).

    Внимание! В версии 1.1.4.0 TfgLabel не поддерживает отображение html в дизайнере IDE.

  24. Yaroslav Brovin
    Добрый день, уважаемые разработчики.
    Спешим порадовать вас главным нововведением 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 изображения.   
  25. 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.

     
×
×
  • Create New...