Jump to content

Yaroslav Brovin

Administrators
  • Posts

    2,584
  • Joined

  • Last visited

  • Days Won

    652

Blog Entries posted by Yaroslav Brovin

  1. Yaroslav Brovin

    Общая
    Добрый день,
    В ближайшее время выйдет релиз FGX Native 1.13.0.0 с полноценной поддержкой Delphi 11. Обо всех нововведениях по порядку.
    Delphi 11
    Начиная с версии 1.13.0.0 мы включили поддержку Delphi 11. В то же время, мы исключили поддержку 10.3 из инсталлятора на основании результатов голосования:
    Мы переработали все формы дизайнера и добавили полноценную поддержку HiDPI.
    Дизайнер форм
    Добавлен новый режим позволяющий отключать пунктирную рамку компонентов.

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

    Обновления TfgDatePicker и TfgTimePicker
    В этом релизе мы добавили несколько небольших улучшений этих компонентов. Теперь вы можете указать формат ввода времени: 12 или 24 часовой формат. За это отвечает новое свойство TfgTimePicker.Is24HoursMode = (LocaleDependent, True, False). Теперь при старте компонента на платформе Android он по умолчанию выбирает часовой формат на основании текущей локали устройства.
     
    Помимо этого мы добавили режим автоматического расчета размера для этих компонентов AutoSize, который включен по умолчанию. Поэтому, если вам необходимо, чтобы компоненты растягивались по ширине, нужно исключить значение AutoSize.Width.
    Так же, теперь вы можете отдельно указывать задний фон для этих компонентов при помощи свойства BackgroundName.
     
  2. 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
  3. 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, где нужно указать нужный язык. При смене кода языка, компонент автоматически выполнит перевод указанных свойств.
    Русский (по умолчанию):

    Английский:

  4. 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.
  5. Yaroslav Brovin
    В этот вторник совместно с компанией Embarcadero проводим вебинар посвященный разработке мобильного приложения с использованием FGX Native. На вебинаре разберем приемы верстки экранов мобильного приложения и одну из возможных примеров системы навигации между экранами.
    В качестве примера создаем прототип мобильного приложения, позволяющего выработать полезные привычки.
    Когда: 31 мая 2022 в 12:00 МСК Язык: русский Заголовок: Создание популярного мобильного приложения с FGX Native Ссылка на регистрацию: https://lp.embarcadero.com/fgx-native  
  6. Yaroslav Brovin
    Добрый день пользователи FGX Native.
    Сегодня мы хотим рассказать про переход Android части библиотеки FGX Native на AndroidX. О том, что это, зачем это нужно и как это влияет на разработчиков мы поговорим в этой статье.
    Что такое AndroidX?

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

    Сканер штрихкодов
    Обновленная реализация сканера штрихкодов, которая работает быстрее, стабильнее и лучше.
    Карты GoogleMap
    Поддержка свежих версий карт.
    Реклама AdMob
    Использование последних версий площадки по размещению рекламы.
    Прочее
    Обновление Yandex.AppMetrica, Google SignIn, Billing, InAppPurchase и тд.
    Что делать, если я не все понял в этой статье?
    Не расстраиваться! FGX Native команда делает все, чтобы вам не нужно было знать обо всем этом и вы могли сконцентрироваться на решении своих задач. Однако, нам приятно поделиться с вами действительно важными изменениями в FGX Native, которые позволят нашему продукту стать еще шире и добавить еще больше новых возможностей. У нас большой опыт в этой области, который позволяет нам реализовывать практически любые идеи. 
    Всем спасибо за внимание!
  7. 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 сам осуществляет их выравнивание и переключение.
     
  8. Yaroslav Brovin
    Добрый день,
    Мы выложили запись прошедшего 18 февраля вебинара по теме "Пробная сессия вопросов и ответов по FGX Native". Видео доступно на нашем YouTube канале.
    На вебинаре обсуждались следующие темы:
     Android SDK/NDK; Сервисы локации; Асинхронная загрузка изображений в списках; Планы на ближайшие релизы.  
     
  9. Yaroslav Brovin

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

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

    Стало:

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


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


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


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

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

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

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

    Delphi 11 Update 2
    Добавлена поддержка Delphi 11 Update 2. Из-за критических изменений на стороне IDE, перестали собираться приложения FGX Native из-за нарушения целостности в Deployment Manager. Данный релиз устраняет эту проблему.
    Надеемся, что новый функционал придется вам по душе и облегчит процесс разработки. Через релиз мы выпустим поддержку стилей, которые значительно упростят процесс верстки интерфейса вашего приложения в дизайнере.
  10. 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. Всем хороших выходных и успешного кодирования ?
  11. Yaroslav Brovin

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

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

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

     
  12. Yaroslav Brovin

    Общая
    Поздравляем вас с наступающим Новым годом!
    Мы благодарим вас за доверие и спасибо, что в этом году вы были с нами. В течении всего года мы прислушивались к вашим пожеланиям и старались сделать все возможное, чтобы наш продукт раз от раза становился удобнее и мощнее.
    В ближайшее время выйдет новый релиз 1.13.3.0. Традиционно в этом релизе вас ждет несколько полезных новинок и улучшений.
    GooglePay - TfgGooglePayClient 
    Первая новинка - это новый компонент TfgGooglePayClient оплаты покупок в вашем приложении через платежную систему GooglePay.
    Настройка 
    Для того, чтобы добавить возможность оплаты покупок в вашем приложении, вам необходимо выполнить первичную настройку на стороне Google - https://developers.google.com/pay/api/web/guides/setup?hl=ru
    В результате этой настройки вы получите идентификатор продавца Google - MerchantId.
    Настройка приложения FGX Native
    Для того, чтобы иметь возможность использовать GooglePay в FGX Native приложении, необходимо добавить в манифест Android приложения следующие строчки в любое место внутрь тега <application>:
     1. Версию GooglePlay сервисов. ТОЛЬКО, если вы не используете "Firebase PushNotification", Maps или AdMob.
    <meta-data android:name="com.google.android.gms.version" android:value="12451000" /> 2. Включить доступ приложения к кошельку:
    <meta-data android:name="com.google.android.gms.wallet.api.enabled" android:value="true" /> 3. Указать идентификатор продавца в свойстве "TfgGooglePayClient.MerchantName", полученный на предыдущем шаге.
    Проверка возможности оплаты через GooglePay
    GooglePay может быть недоступен на устройстве пользователя, поэтому, перед инициированием процесса оплаты, необходимо узнать текущий статус. Это можно сделать через асинхронный метод "TfgGooglePayClient.IsReadyToPayAsync":
    uses FGX.Payments.GooglePay.Types; if gpClient.IsSupported then gpClient.IsReadyToPayAsync(False, procedure (const AStatus: TfgGooglePayStatus) begin // Отображаем/Скрываем кнопку оплаты через GooglePay btnPay.Visible := AStatus = TfgGooglePayStatus.Available; end); Оплата через GooglePay
    Для инициации оплаты необходимо заполнить информацию о проводимой транзакции и воспользоваться асинхронным методом оплаты "TfgGooglePayClient.PayAsync". Минимально необходимая информация в транзакции - это код валюты и цена.
    procedure TFormMain.btnPayTap(Sender: TObject); var TransactionInfo: TfgTransactionInfo; begin TransactionInfo := TfgTransactionInfo.Create; try { Информация о покупке } TransactionInfo.SetCurrencyCode('RUB') .SetTotalPrice(100.12); gpClient.PayAsync(TransactionInfo); finally TransactionInfo.Free; end; end; Описание полей транзакции, смотрите в исходном коде или на сайте GooglePay.
    По результатам обработки запроса, будет вызвано одно из событий:
    "OnPaymentError" - в ходе оплаты произошла ошибка. "OnPaymentComplete" - пользователь выполнил оплату, токен для проведения оплаты передается в параметрах события. "OnPaymentCancelled" - пользователь отменил оплату. Если платеж прошел успешно, то в событии OnPaymentComplete будет передан JSON ответ, из которого вы можете извлечь необходимую информацию согласно документации:
    procedure TFormMain.gpClientPaymentComplete(Sender: TObject; const AResponse: TJSONValue); begin mLog.Lines.Add(Format('Completed: AResponse="%s"', [AResponse.Format])); end; После извлечения платежного токена, вам необходимо провести транзакцию на вашем сервере через ваш банк.
    Если же оплата по каким-то причинам не прошла, вы можете получить информацию об ошибке через событие OnPaymentError. В параметрах передается код ошибки и ее описание. Обратите внимание, что данный код и описание выдается самой системой. Поэтому иногда описание может отсутствовать или содержать неполную информацию (это нормально).
    Диагностика и отладка
    Все детальные ошибки настройки интеграции с GooglePay обычно выводятся в лог. Именно там можно узнать, почему платеж не запускается или не проходит. Обратите внимание, что чаще всего ошибки в лог попадают не от имени приложения, а от системы. Поэтому при поиске проблем, нужно это учитывать (не фильтровать сообщения вашим приложением).
    Все свойства компонента полностью соответствуют оберткам в документации Google Pay. Компонент формирует JSON запрос, который отправляется в нативное API. Вы можете проверить корректность формирования JSON запроса через лог. Для этого необходимо включить расширенное логирование в вашем приложении:
    TfgLog.MinimumLevel := TfgLogLevel.Trace; Полезные ссылки:
    Руководство по использованию бренда GooglePay. Советы UX по интеграции GooglePay. Чек лист по настройке GooglePay. Диагностика проблем. TfgApplicationEvents
    При разработке Android приложений и при использовании Android API очень часто требуется отправить запрос другим активностям и получить от них результат. Раньше это решалось через подписку на широковещательные сообщения  FGX.Platform.Android.TfgActivityResultMessage и TfgActivityNewIntentMessage и требовало написать следующий код:
    constructor TFormMain.Create(AOwner: TComponent); begin inherited; TMessageManager.DefaultManager.SubscribeToMessage(TfgActivityResultMessage, ActivityResultHandler); TMessageManager.DefaultManager.SubscribeToMessage(TfgActivityNewIntentMessage, ActivityNewIntentHandler); end; destructor TFormMain.Destroy; begin TMessageManager.DefaultManager.Unsubscribe(TfgActivityNewIntentMessage, ActivityNewIntentHandler); TMessageManager.DefaultManager.Unsubscribe(TfgActivityResultMessage, ActivityResultHandler); inherited; end; procedure TFormMain.ActivityNewIntentHandler(const Sender: TObject; const M: TMessage); var Message: TfgActivityNewIntentMessage; begin TfgAssert.IsClass(M, TfgActivityNewIntentMessage); Message := TfgActivityNewIntentMessage(M); TfgToast.Show(Format('Получен новый интент: intent=%s', [JStringToString(Message.Value.toString)])); end; procedure TFormMain.ActivityResultHandler(const Sender: TObject; const M: TMessage); var Message: TfgActivityResultMessage; begin TfgAssert.IsClass(M, TfgActivityResultMessage); Message := TfgActivityResultMessage(M); // Intent is available in Message.Data TfgToast.Show(Format('Получен результат из другого приложения: requestCode=%d, resultCode=%d', [Message.RequestCode, Message.ResultCode])); end; Сейчас же мы добавили два новых события "TfgApplicationEvents.OnActivityResult" и "TfgApplicationEvents.OnActivityNewIntent", которые позволяют значительно сократить код и сконцентрироваться только на реализации. 
    procedure TFormMain.fgApplicationEvents1ActivityNewIntent(Sender: TObject; const AIntent: TfgAndroidIntent); begin {$IFDEF ANDROID} TfgToast.Show(Format('Получен новый интент: intent=%s', [JStringToString(AIntent.toString)])); {$ENDIF} end; procedure TFormMain.fgApplicationEvents1ActivityResult(Sender: TObject; const ARequestCode, AResultCode: Integer; const AIntent: TfgAndroidIntent); begin {$IFDEF ANDROID} TfgToast.Show(Format('Получен результат из другого приложения: requestCode=%d, resultCode=%d', [ARequestCode, AResultCode])); {$ENDIF} end; TfgCollectionView
    Мы провели улучшение контроллера выделения элементов и предоставили больше гибкости в точной настройке поведения. Раньше при режиме выделения  "TfgCollectionViewSelectionMode = SingleSelect" мы не позволяли сбросить выделение элемента повторным нажатием. Это было сделано для возможности реализации меню с отображением текущего выбранного раздела. Однако, для некоторых пользователей такое поведение компонента было нежелательным.
    Теперь мы предлагаем вам самостоятельно решить, как должно работать выделение при помощи новых событий  "TfgCollectionView.OnItemCanSelect" и "TfgCollectionView.OnItemCanDeselect". Данные события вызываются непосредственно до момента установки или снятия выделения и позволяют отменить действие при помощи передаваемого параметра AAllow.
    Так же мы исправили ряд ошибок выделения на платформе iOS, так что теперь процесс выделения работает одинаково на всех платформах.
    ВАЖНО! Теперь по умолчанию компонент позволяет сбросить выделение элемента в режиме SingleSelect. 
    Заключении
    Желаем вам свершения всего задуманного, интересных проектов и амбициозных целей!
    Спасибо, что вы с нами!
  13. Yaroslav Brovin
    Добрый день!
    Рады с вами поделиться будущим выступлением по FGX Native на крупнейшей Итальянской конференции по Delphi в 2022 году. Конференция пройдет 21-23 июня 2022 года. Позже будет детальная информация о выступлении.
    https://www.delphiday.it/
     
  14. 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
  15. Yaroslav Brovin
    Доброго дня, уважаемые пользователи FGX Native.
    Наши клиенты делают интересные проекты на базе нашего продукта, однако, к сожалению, об этом знаю только я в результате получения обратной связи по FGX Native. Мне кажется, что всем было бы интересно узнать о таких приложениях, о применяемых возможностях FGX Native и об использованных технических решениях. Сегодня я начну с обзора приложения, которое первоначально задумывалось, как приложения для каршеринга. Однако, в ходе разработки, области применения гораздо расширились за счет универсальности разработанного решения. Но обо всем по порядку.
       
    Далее приведен текст автора @r3h0soft.
    Перед нами стояла задача реализовать программный комплекс мониторинга за ГЛОНАСС устройствами, который бы включал возможности:
    Отслеживание местоположения устройств Мониторинг телеметрии Формирование различных отчётов за выбранный период времени И т.д. В комплекс входило так же и мобильная разработка, при которой стоило преимущественно выбрать среду разработки с лаконичными и понятным кодом имеющим в комплекте кроссплатформенной реализации. Выбор остался за Delphi. Мобильное приложение должно было отвечать всем требованиям на текущий момент что касаемо UI, отзывчивый интерфейс, анимации, поддержкой API и т.д.  Но если с реализацией бэкенд всё было прозрачно, то неотъемлемой частью разработки UI было не всё гладко с использованием FireMonkey. Выбор пал на FGX Native, который предлагает все инструменты для простой и лёгкой разработки и решению поставленных задач.
    В FGX Native реализовано собственное уникальное решение реализации UI, за основу взята система позиционирования FlexBox. С его помощью можно на лету, только через свойства компонента, реализовать UI любой сложности, которое будет одинаково выглядеть при любом разрешении устройств без единой строчки кода. Этот подход значительно ускорил процесс разработки и позволил сосредоточится на построении логики приложения, не загромождая код, вычислениями позиционирования элементов интерфейса.
    Карты
    Данный проект сложно представить без отражения мониторинга в режиме реального времени. За основу мы взяли компонент карт TfgMap с возможностью отображать маркеры, полигоны, географические зоны, строить маршруты, используя линии с большим количеством объектов. Удивила скорость работы компонента и его плавность. Одной из приятных функций для нашего проекта оказалась стилизация карт. Это позволило нам настроить внешний вид карты, чтобы он не выбивался из общего дизайна интерфейса. Одной из задач при использовании карт было построение маршрута, реализовав парсер точек по заданному диапазону времени с необходимой информацией о состоянии объекта и его положении GPS, используя фильтр настойки для разграничения маршрута использовали состояния "простоя" объекта, и иные события при которых объект не выполнял движения. Так мы получили точный список точек перемещения и реализовали отображение через поли линии. Через свойства реализации в FGX Native, мы смогли стилизовать под свои нужды, зная определенные участки состояния объекта смогли через маркеры объектов вывести определенные состояния (к примеру, участки превышения скорости). Хорошим моментом послужило что точками можно взаимодействовать присвоив им ID, так можно получить дополнительную информацию в любом участке трекера просто выбрав точку на карте. Конечно, в будущем очень хотелось бы использовать некую сущность для маркера имеющую стиль, для наполнения его своими объектами как в TfgCollectionView и отображения определенных маркеров при определенных состояниях.
    Сами маркеры добавляются легко через менеджер объектов.
      
    Списки
    Не обошлось и без списков, следовало подгружать объекты в стилизованные карточки одного списка, не нагружая при этом систему, с плавность отрисовки и высокой скоростью. Для решения данной задачи взят TfgCollectionView. Этот компонент отвечает всем требованиям и прост как и все другие решения библиотеки в освоении.  Мы использовали списки, как для формирования меню навигации, так и для отображения маршрутов, истории поездок и т.д. Чтобы не нагружать приложение разными формами, мы использовали выдвигаемые панели сбоку TfgDrawerLayout и снизу TfgBottomSheetLayout. С помощью этих компонентов решена задача быстрого доступа к данным истории телеметрии при этом не нагружая интерфейс и проект дополнительными формами.
     
    Не обошлось и без списков, следовало подгружать объекты в стилизованные карточки одного списка, не нагружая при этом систему, с плавность отрисовки и высокой скоростью. Для решения данной задачи взят TfgCollectionView. В списках мы добавили нужные нам стили объектов списка, что позволило генерировать нужный по событию изменяя только имя стиля, это удобно. Единственное чего не хватило, так это свайпа по элементам списка (лево/право). В общем и целом, этот компонент отвечает всем требованиям и прост как и все другие решения библиотеки в освоении.  Мы использовали списки, как для формирования меню навигации, так и для отображения маршрутов, истории поездок и т.д.
    Чтобы не нагружать приложение формами, мы использовали выдвигаемые панели сбоку TfgDrawerLayout и снизу TfgBottomSheetLayout. С помощью этих компонентов решена задача быстрого доступа к данным истории телеметрии при этом не нагружая интерфейс и проект дополнительными формами.
      
     
    Анимация
    Чтобы оживить интерфейс и порадовать пользователя внешним видом было принято решение встроить готовые сценарии анимации. В одном из обновлений FGX Native появилась поддержка продвинутых анимаций Lottie. Мы нашли готовые примеры анимации и просто встроили их в пару кликов. Таким образом получился такой вот симпатичный экран:
    AddingDriver.mp4
    Так же имеется и конструктор анимации для самих компонентов, мы использовали анимацию тряски для неправильного ввода пароля и анимацию появления для уведомлений.
    Сканер штрих кодов
    В ходе работы с приложением, пользователю необходимо выполнить регистрацию ГЛОНАСС устройства. Можно было бы ограничится вводом в ручную серийного номера, указанного на устройстве. Однако, мы воспользовались готовым сканером штрих кодов TfgBarcodeScanner и камерой TfgCamera и сделали эту процедуру автоматической.

    Уведомления и монетизация
    Любое приложение каршеринга - это контроль за местоположением транспортного средства. И в нашем случае это не исключение. Нам нужно было уведомлять пользователя при определенных событиях телеметрии устройства (вход/выход из геозоны, состояния устройства, ДТП, включения зажигания). Для этого мы использовали локальные уведомления. А вот для системных уведомлений, таких как "обновление приложения" или "необходимости оплаты" легко реализованы с помощью Push уведомлений на базе FGX и Firebase.
    Кстати, среди поставляемых примеров, вы найдете много готовых решений и примеров возможностей библиотеки.
    Хотите иметь возможность монетизации в приложении будь то подписка или продажа, для этого есть готовые компоненты оплаты, как для Android так и iOS.
    Реализация авторизации
    Как и любое приложение, работающее с пользователя, нам необходимо было организовать процесс авторизации. Мы использовали Firebase, реализация выполнена с помощью FB4D библиотеки, в FGX имеется возможность легко реализовать авторизацию и с помощью Google Sign, Facebook, VK, AppleID, что не может не радовать. Основная база крутится на PostgreSQL, используя штатные компоненты FireDAC. Общение построено с использованием REST API, чьим ответственным выступил DelphiMVCFramework фреймворк. Как видно, FGX Native не конфликтует с различными сторонними решениями, что позволяет расширять возможности разработки приложений любой сложности и поставленных задач.
    Bluetooth
    Не обошлось и без штатных задач управления устройством с помощью Bluetooth , мы использовали стандартные средства Delphi RTL для синхронизации и управления модулем через Bluetooth.
    Итог
    Это лишь малая часть которой хотел поделиться, возможности FGX Native для нас очень обширны, мы реализовали разные сложные проекты с его помощью, о которых я расскажу напишу в следующих статьях. Среди таких:
    Мониторинг за сотрудниками (курьерами, работниками, водителям где устройством мониторинга выступает мобильное приложение на FGX с использованием сервисов фоновой локации и состоянием устройства, мониторинга задач и управления через Bitrix), личный кабинета клиента микрофинансовой компании, личный кабинет клиентов интернет провайдера, управление модулем автопилота для лодок fishboat по Bluetooth и многое другое. FGX Native - это лучшее решение для нас!
  16. 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.

  17. Yaroslav Brovin
    Hello dear Delphi developers,
    We are happy to share with you two new FGX Native courses in Italian, which Claudio Piffer @claudio.piffer designed and prepared for you. Claudio Piffer is strong Delphi Developer with wide knowledge of different technologies. He often speaks at various Delphi conferences and shares his knowledge with other developers. For us, he is known for two speeches at the DelphiDays conference in Italy (2020, 2022), on which he clearly showed and told the possibilities of FGX Native in the shortest possible time. Claudio has prepared two courses that can help you go into the world of mobile development with Delphi and FGX Native:
    Basic. Mobile developement with FGX Native. Advanced. Advanced concepts in FGX Native. You can find the course description, topics and lessons covered by clicking on the links above.
    Thank you,
    Yaroslav Brovin
  18. Yaroslav Brovin
    В обновлении 1.1.6.0 процесс сборки android приложения претерпел незаметное на первый взгляд, но очень важное для пользователей изменение, а именно,  добавлена автоматическая генерация файла classes.dex.
    classes.dex - обязательный для android приложения файл, содержащий все используемые в приложении Java библиотеки. Ранее конечное приложение собиралось с готовым classes.dex файлом поставляемым вместе с библиотекой FGX Native, что создавало для разработчиков некоторые проблемы при использовании сторонних jar библиотек. Процесс добавления был нетривиален и требовал глубокого погружения в документацию, процессы сборки и микширования classes.dex.
    Механизм автоматической генерации уже используется в FMX проектах, однако, по ряду причин и ограничений, накладываемых IDE, он не мог быть задействован для FGX Native.
    Мы пересмотрели пользовательский опыт и рады представить вам новый удобный диалог для управления jar библиотеками, используемыми в проекте.
    Вызвать диалог можно двумя способами:
    Через главное меню: Project -> FGX Android Libraries Через контекстное меню панели Projects. Target Platforms -> Android (32/64 bits) -> Libraries -> Setup Android Libraries.
    Всё, что необходимо для включения в ваше приложение сторонней jar библиотеки — это добавить её в разделе «Все модули» или «Пользовательские».
    Для возврата списка библиотек к первоначальноиу состоянию воспользуйтесь кнопки «По-умолчанию».
  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
    В ближайшее время выйдет новый релиз 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".
  21. 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.
    Другие улучшения
    В этом релизе также содержится большое количество исправлений ошибок. 
    Всем спасибо за внимание!
  22. 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 части в части управления формами, выравниванием и тд. 
  23. 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 и большая часть экранов уже открывается и успешно работает.
     
    Всем хорошего окончания этих выходных!
×
×
  • Create New...