<?xml version="1.0"?>
<rss version="2.0"><channel><title>Product Updates</title><link>https://forum.fgx-native.com/blogs/blog/1-%D0%BE%D0%B1%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F-%D0%BF%D1%80%D0%BE%D0%B4%D1%83%D0%BA%D1%82%D0%B0/</link><description></description><language>en</language><item><title>&#x41C;&#x438;&#x433;&#x440;&#x430;&#x446;&#x438;&#x44F; &#x43F;&#x440;&#x43E;&#x435;&#x43A;&#x442;&#x43E;&#x432; &#x434;&#x43B;&#x44F; &#x438;&#x441;&#x43F;&#x43E;&#x43B;&#x44C;&#x437;&#x43E;&#x432;&#x430;&#x43D;&#x438;&#x44F; &#x43D;&#x43E;&#x432;&#x44B;&#x445; &#x442;&#x435;&#x43C; &#x432; 1.19.0.0</title><link>https://forum.fgx-native.com/blogs/entry/76-%D0%BC%D0%B8%D0%B3%D1%80%D0%B0%D1%86%D0%B8%D1%8F-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%BE%D0%B2-%D0%B4%D0%BB%D1%8F-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F-%D0%BD%D0%BE%D0%B2%D1%8B%D1%85-%D1%82%D0%B5%D0%BC-%D0%B2-11900/</link><description><![CDATA[<p>Добрый день, </p><p>В ближайшее время выйдет большой релиз <strong>1.19.0.0</strong>, который полностью будет посвящен большим изменения в работе с темами приложения, упростит ваш код и сделает управлением темами удобнее и понятнее.</p><p>Предварительно мы разработали полное руководство по темам:</p><div class="ipsEmbeddedOther" data-og-user_text="https://forum.fgx-native.com/blogs/entry/74-%D1%80%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE-%D1%82%D0%B5%D0%BC%D1%8B-%D0%B2-fgx-native-%D0%B2-11900/"><iframe src="https://forum.fgx-native.com/blogs/entry/74-%D1%80%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE-%D1%82%D0%B5%D0%BC%D1%8B-%D0%B2-fgx-native-%D0%B2-11900/?do=embed" data-embedcontent="" data-internalembed="" data-controller="core.front.core.autosizeiframe" data-embedauthorid="1" data-ipsembed-contentapp="blog" data-ipsembed-contentclass="blog_Entry" data-ipsembed-contentid="74" data-ipsembed-timestamp="1756833692" allowfullscreen="" data-og-user_text="https://forum.fgx-native.com/blogs/entry/74-%D1%80%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE-%D1%82%D0%B5%D0%BC%D1%8B-%D0%B2-fgx-native-%D0%B2-11900/" loading="lazy"></iframe></div><p>Обязательно прочитайте это руководство, потому что в этой теме будет затронута только миграции проектов на <strong>1.19.0.0</strong>.</p><p><strong><span data-i-color="red">Внимание:</span></strong> В данном релизе <strong>1.19.0.0</strong> введены изменения, которые ломают совместимость проектов этой версии со старыми версиями. Поэтому переход на <strong>1.19.0.0</strong> является необратимым. Перед тем, как открыть ваш проект необходимо <strong>ОБЯЗАТЕЛЬНО</strong> сделать резервную копию на случай необходимости временного возврата к предыдущим версиям.</p><h2>Новый ресурс - тема</h2><p>Не смотря на то, что есть несколько статей о том, как настраивать темы и как их использовать, концепция темы не была до конца закончена. Связано это прежде всего было с тем, что как таковой сущности "тема" в <strong>FGX Native</strong> не существовало до 1.19.0.0. Это создавало внутренние трудности в реализации <strong>FGX Native</strong> и требовало использовать не всегда очевидные подходы в определении, что есть тема в <strong>FGX Native</strong>.</p><p>Вы можете возразить, что понятие темы существует уже много лет. Однако, ответ очень прост. Вы никаким способом не можете определить программно до текущего релиза, названия тем приложения. Именно это и является камнем преткновения.</p><p>Теперь мы ввели полноценное понятие темы. При открытии старого проекта в 1.19.0.0 мигратор автоматически создает сущность темы на основании ваших ресурсов для каждой потенциальной темы.</p><p><a href="https://forum.fgx-native.com/uploads/monthly_2025_09/image.png.b6dea96502c9416be9882db8c2dc748f.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block ipsRichText__align--width-custom" style="--i-media-width: 320px" data-fileid="5490" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="5490" src="https://forum.fgx-native.com/uploads/monthly_2025_09/image.thumb.png.dac1e71e8ad18035e3ed945a76e47435.png" alt="image.png" style="--i-media-width: 320px" width="613" height="750" loading="lazy"></a></p><p>Тема обозначается специальным значком. Тему можно добавить одним из трех способов:</p><p><img class="ipsImage ipsRichText__align--block ipsRichText__align--width-custom" data-fileid="5491" src="https://forum.fgx-native.com/uploads/monthly_2025_09/image.png.412651bd55675f9e91e51ab287baf0c1.png" alt="image.png" style="--i-media-width: 400px" width="840" height="378" loading="lazy"></p><p>(1) Сгенерировать тему (по старому способу). Контекстное меню дерева ресурсов -&gt; "Сгенерировать тему".</p><p>(2) Добавить пустую тему. Все ресурсы темы вы должны добавить самостоятельно по вашему усмотрению. Контекстное меню дерева ресурсов -&gt; "Добавить тему".</p><p>В этом случае создается пустая тема без какого-либо ресурса. Все необходимые ресурсы вы должны добавить туда самостоятельно.</p><p><a href="https://forum.fgx-native.com/uploads/monthly_2025_09/image.png.d1e5931c805229c92384742d9d8f679b.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block ipsRichText__align--width-custom" style="--i-media-width: 400px" data-fileid="5492" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="5492" src="https://forum.fgx-native.com/uploads/monthly_2025_09/image.thumb.png.aa230b87eec52087a75c37b9cc5ea801.png" alt="image.png" style="--i-media-width: 400px" width="768" height="750" loading="lazy"></a></p><p>(3) Сконвертировать каталог с ресурсами в тему. Контекстное меню дерева ресурсов -&gt; "Конвертировать в тему".</p><p>Как только тема добавлена в менеджере ресурсов, так сразу вы можете ее использовать ее в вашем приложении. Темы могут располагаться в любом месте, в том числе во вложенных папках.</p><h2>Доступ к темам</h2><p>На уровне <code>TfgAssetsManager</code> добавлен новый метод, позволяющий получить список тем:</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>/// &lt;summary&gt;Возвращает названия всех доступных тем.&lt;/summary&gt;
function GetThemesNames: TArray&lt;TfgThemeName&gt;;</code></pre><h2>Применение темы</h2><p>Теперь тема может быть применена на уровне приложения без необходимости указывать ее на уровне каждой формы. Для этого добавлено новое свойство <code>Application.ThemeSettings</code>. Новые объект позволяет указать светлую и темную темы через свойства:</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>/// &lt;summary&gt;Название светлой темы FGX Native, используемой по умолчанию во всех формах.&lt;/summary&gt;
property LightThemeName: TfgThemeName read FLightThemeName write SetLightThemeName;
/// &lt;summary&gt;Название темной темы FGX Native, используемой по умолчанию во всех формах.&lt;/summary&gt;
property DarkThemeName: TfgThemeName read FDarkThemeName write SetDarkThemeName;</code></pre><p>За выборе темы при старте приложения отвечает свойство</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>/// &lt;summary&gt;Применяемая тема по умолчанию.&lt;/summary&gt;
/// &lt;remarks&gt;
///   Если приложение не поддерживает темную тему (Темная тема не включена в настроках проекта), то вид темы
///   будет всегда &lt;c&gt;Light&lt;/c&gt;.
/// &lt;/remarks&gt;
property ThemeKind: TfgThemeKind read FThemeKind write SetThemeKind;</code></pre><p>Теперь вы можете указать, чтобы тема автоматически была согласована с системной темой устройства, либо же принудительно применить светлую или темную тему.</p><p>Основным способом указания темы, является появление нового окна настроек Project -&gt; FGX Options... -&gt; Приложение -&gt; Темы</p><p><img class="ipsImage ipsRichText__align--block" data-fileid="5493" src="https://forum.fgx-native.com/uploads/monthly_2025_09/image.png.29db9639c8c8c3eebaa01d69313d00af.png" alt="image.png" loading="lazy"></p><p>Помимо задания темы на уровне приложения, вы так же можете указывать ее на уровне формы, если по каким-то причинам, вы хотите использовать другой вариант темы на какой-то форме.</p><h2>Использование файла Assets.Consts</h2><p>Начиная с 1.19.0.0 изменена логика генерации файла констант с именами ресурсов.</p><ol><li><p>В этом релизе мы провели унификацию названий полей.</p><ol><li><p><code>R.Fonts</code> -&gt; <code>R.Font</code></p></li><li><p><code>R.Images</code> -&gt; <code>R.Image</code></p></li><li><p><code>R.LottieAnimations</code> -&gt; <code>R.LottieAnimation</code></p></li><li><p><code>R.Files</code> -&gt; <code>R.&amp;File</code></p></li></ol></li></ol><p>Так же теперь <code>R.Theme</code> не возвращает ресурсы текущей темы. За это отвечает новое поле <code>R.CurrentTheme</code>, которое возвращает имя ресурса темы в зависимости от теущей темы приложения. Таким образом, вам больше не нужно вручную динамически формировать имя ресурса в зависимости от светлой или темной темы.</p><p><code>R.Theme</code> теперь выдает доступ ко всем темам приложения.</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>    TfgCurrentTheme = record
      /// &lt;summary&gt;Identifiers with current theme colors assets.&lt;/summary&gt;
      class var Color: TfgThemeColors;
    end;

    TfgThemes = record
      class var ThemeDark: TfgThemeThemeDark;
      class var ThemeLight: TfgThemeThemeLight;
    end;    

    /// &lt;summary&gt;Identifiers with current theme assets.&lt;/summary&gt;
    class var CurrentTheme: TfgCurrentTheme;

    /// &lt;summary&gt;Identifiers with themes names.&lt;/summary&gt;
    class var Theme: TfgThemes;</code></pre><h2>Использование ресурсов темы</h2><p>Теперь, при использовании ресурсов темы допускается два способа указания имени:</p><ol><li><p>Адаптированное имя под текущую тему. Если вы хотите, чтобы при смены темы, используемый ресурс так же брался из новой темы, то в качестве разделителя названия темы и ресурса нужно использовать ":".<br>Например: "<strong>Themes\Light\Green:Background</strong>". </p></li><li><p>Фиксированное имя. Если вы не хотите изменения названия ресурса темы при смене темы, то используйте старый способ указания имени "<strong>Themes\Light\Green\Background</strong>".</p></li></ol><h2><strong>Миграция</strong></h2><p><strong><span data-i-color="red">Важно</span></strong>: Перед выполнением миграции вашего проекта <strong>ОБЯЗАТЕЛЬНО</strong> сделать резервную копию проекта, чтобы в случае чего можно было откатиться обратно.</p><p>Чтобы облегчить миграцию ваших проектов для поддержки новых тем, мы разработали мастер, который поможет автоматически выявить все места использования ресурсов тем.</p><p>Мастер:</p><ol><li><p>Распознает все свойства (из библиотеки), связанные с ресурсами.</p></li><li><p>Извлекает текущее значение имени ресурса.</p></li><li><p>Для <strong>DFM/XFM</strong> файлов форм и фреймов проверяет имя ресурса на предмет принадлежности темы - вхождение слова "<strong>Theme</strong>" (без учета регистра). Если у вас в названии темы не фигурирует слово <strong>"Theme"</strong>, пожалуйста, сообщите в комментариях под этой статьёй.</p></li><li><p>Для обнаруженных имен ресурсов (<strong>только для XFM)</strong> автоматически формирует новое имя с учетом нового синтаксиса и предлагает автоматическую замену . </p></li></ol><p>При открытии старого проекта автоматически запускается миграция проекта на новую версию, в рамках чего будет отображен мастер только если в вашем проекте будут найдены потенциальные места использования ресурсов из тем. </p><p><a href="https://forum.fgx-native.com/uploads/monthly_2025_09/image.png.09193e7385460d2870e35b17affcd1f7.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block" data-fileid="5489" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="5489" src="https://forum.fgx-native.com/uploads/monthly_2025_09/image.thumb.png.252521bd4c66d0c3834a6680f7369ef3.png" alt="image.png" loading="lazy"></a></p><p><strong><span data-i-color="red">Важно</span>:</strong> Мастер сканирует только файлы добавленные в проект напрямую. Другими словами, все файлы, которые используются в проекте, но не добавлены в него анализироваться не будут.</p><h3>Адаптация DFM/XFM файлов</h3><p>Если вы не хотите применять предложенное изменение, снимите галку напротив строки с предложенным изменение в левом дереве. Мы применили наш мастер на все демонстрационные проекты, а так же проверили его на наших больших демонстрационных проектах с вебинаров. Ошибок в адаптации найдено не было.</p><p>Допускаем, что какие-то варианты могут быть не учтены, поэтому, важно делать резервные копии. По умолчанию мы создаем копию затрагиваемых оригинальных файлов и добавляем окончание "<strong>.backup</strong>". Если вы уверены в предложенных изменения, вы можете отключить резервные копии файлов через снятия галки чекбокса в футере окна.</p><h3>Адаптация PAS файлов</h3><p>Отдельно изучите найденные изменения в PAS файле и выполните адаптацию самостоятельно. Поскольку вариантов формирования имени ресурса из темы большое количество и ограничено только вашей фантазией, мы не можем корректно проанализировать ваш код, но можем предположительно найти только потенциальные места, где идет программное изменение свойств, затрагивающих работу с названием ресурсов.</p><p>Вот несколько советов, которые вам помогут:</p><ol><li><p>Если вы используете константы из файла <code>Assets.Consts.R</code>, то в этом релизе мы провели унификацию названий полей. Если вы используете программный доступ к этим ресурсам, переименуйте их согласно схеме выше.</p><ol><li><p><code>R.Fonts</code> -&gt; <code>R.Font</code></p></li><li><p><code>R.Images</code> -&gt; <code>R.Image</code></p></li><li><p><code>R.LottieAnimations</code> -&gt; <code>R.LottieAnimation</code></p></li><li><p><code>R.Files</code> -&gt; <code>R.&amp;File</code></p></li></ol></li><li><p>Изменена логика использования <code>R.Theme</code>. Теперь она содержит не ресурсы текущей темы, а все темы приложения, с возможностью получить доступ к ресурсам каждой темы. Если вы используете в проекта <code>R.Theme</code>, вам необходимо его заменить на <code>R.CurrentTheme</code>.</p></li></ol><p><strong><span data-i-color="red">Важно</span></strong>: Адаптацию pas файлов нужно выполнить самостоятельно.</p><h3>TfgControl.UpdateTheme</h3><p>В некоторых проектах используется метод <strong>TfgControl.UpdateTheme</strong>, который был добавлен для временного решения проблемы с применением тем при динамическом встраивании компонентов и фреймов</p><div class="ipsEmbeddedOther" data-og-user_text="https://forum.fgx-native.com/topic/3693-%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D0%B0-%D1%82%D0%B5%D0%BC%D0%BD%D0%BE%D0%B9-%D1%82%D0%B5%D0%BC%D1%8B-%D0%B2%D0%BE-%D0%B2%D1%81%D1%82%D1%80%D0%B0%D0%B8%D0%B2%D0%B0%D0%B5%D0%BC%D0%BE%D0%BC-%D1%84%D1%80%D1%8D%D0%B9%D0%BC%D0%B5/?&amp;do=findComment&amp;comment=8814"><iframe src="https://forum.fgx-native.com/topic/3693-%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D0%B0-%D1%82%D0%B5%D0%BC%D0%BD%D0%BE%D0%B9-%D1%82%D0%B5%D0%BC%D1%8B-%D0%B2%D0%BE-%D0%B2%D1%81%D1%82%D1%80%D0%B0%D0%B8%D0%B2%D0%B0%D0%B5%D0%BC%D0%BE%D0%BC-%D1%84%D1%80%D1%8D%D0%B9%D0%BC%D0%B5/?&amp;do=embed&amp;comment=8814&amp;embedComment=8814&amp;embedDo=findComment" data-embedcontent="" data-internalembed="" data-controller="core.front.core.autosizeiframe" data-embedauthorid="1" data-ipsembed-contentapp="forums" data-ipsembed-contentclass="forums_Topic" data-ipsembed-contentid="3693" data-ipsembed-timestamp="1756834632" data-ipsembed-contentcommentid="8814" allowfullscreen="" data-og-user_text="https://forum.fgx-native.com/topic/3693-%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D0%B0-%D1%82%D0%B5%D0%BC%D0%BD%D0%BE%D0%B9-%D1%82%D0%B5%D0%BC%D1%8B-%D0%B2%D0%BE-%D0%B2%D1%81%D1%82%D1%80%D0%B0%D0%B8%D0%B2%D0%B0%D0%B5%D0%BC%D0%BE%D0%BC-%D1%84%D1%80%D1%8D%D0%B9%D0%BC%D0%B5/?&amp;do=findComment&amp;comment=8814" loading="lazy"></iframe></div><p>В новой версии <strong>1.19.0.0</strong> этого метода больше нет, так как теперь адаптация применения темы выполняется библиотекой самостоятельно. Поэтому вам НЕ ТРЕБУЕТСЯ больше вызывать этот метод. Поэтому удалите использование этого метода из вашего проекта.</p><h2>Дизайнер формы</h2><p>В этом релизе так же добавлена возможность быстрого переключения тем вашего приложения в дизайнере формы. Таким образом вы можете в одно нажатие посмотреть, как выглядит форма в темной или светлой темах. Для этого воспользуйтесь новыми кнопками переключения темы на панели инструментов в дизайнере формы:</p><p><a href="https://forum.fgx-native.com/uploads/monthly_2025_09/image.png.41e48ed1de424baaf6010f93fd67f7cc.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block" data-fileid="5494" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="5494" src="https://forum.fgx-native.com/uploads/monthly_2025_09/image.thumb.png.62909a7b673a92ee9c76b8d94383468a.png" alt="image.png" loading="lazy"></a><a href="https://forum.fgx-native.com/uploads/monthly_2025_09/image.png.d2ece2ec4dec08d13d02b81a57e976a5.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block" data-fileid="5495" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="5495" src="https://forum.fgx-native.com/uploads/monthly_2025_09/image.thumb.png.4912df6152a2c99dd1aeed67cfe1313f.png" alt="image.png" loading="lazy"></a></p><p>При переключении темы для формы меняется выбранная тема по умолчанию. А именно, светлая или темная тема берется из настроек проекта. Поэтому, чтобы это переключение сработало нужно:</p><ol><li><p>Темная и светлая темы были добавлены в дизайнере ресурсов</p></li><li><p>Темная и светлая темы были указаны в настройках проекта.</p></li></ol><p>Если оба условия не выполнены, то переключение тем никак не приведет к изменению отображени</p><p><a href="https://forum.fgx-native.com/uploads/monthly_2025_09/image.png.0f15aba7d178ac71c0d98841423e9a02.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block" data-fileid="5496" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="5496" src="https://forum.fgx-native.com/uploads/monthly_2025_09/image.thumb.png.9af1bfa4129f28469d19623344fc7f3d.png" alt="image.png" loading="lazy"></a></p><p>Так же мы обновили дизайнер выбора ресурса. Теперь он открывается в отдельном окне.</p><p><a href="https://forum.fgx-native.com/uploads/monthly_2025_09/image.png.9172e88cd6d9e135a7f493aa412ae35a.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block" data-fileid="5501" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="5501" src="https://forum.fgx-native.com/uploads/monthly_2025_09/image.thumb.png.d16ce3113e0c89f2f186ac4a3351aac6.png" alt="image.png" loading="lazy"></a></p><p>Если ресурс применяется из темы, то в его имени используется ":", как разделитель названия темы и ресурса внутри него.</p><p>Помимо этого мы мы добавили ряд небольших изменений в сам дизайнер формы, которые, возможно, вам пригодятся.</p><p>(1) Теперь при выделении компонента, отображается его имя и размер. А при перетаскивании имя теперь не выводится.</p><p><img class="ipsImage ipsRichText__align--block" data-fileid="5499" src="https://forum.fgx-native.com/uploads/monthly_2025_09/image.png.64723dc20e1140cb28a59b42cc620cce.png" alt="image.png" loading="lazy"></p><p>Если вы нехотите, чтобы выводился размер или название. Вы можете отключить это поведение в общих настройках среды: Tools -&gt; Options -&gt; Third Party -&gt; Form Designer</p><p><a href="https://forum.fgx-native.com/uploads/monthly_2025_09/image.png.72930336a6d91a270b1f5383b6cf4462.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block" data-fileid="5500" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="5500" src="https://forum.fgx-native.com/uploads/monthly_2025_09/image.thumb.png.478f5f0804e3ea9820d4c95e152933c3.png" alt="image.png" loading="lazy"></a></p><p>(2) Добавлена возможность быстрого переключения формы в текстовый режим. Теперь при нажатии на кнопку "Как текст", дизайнер переключиться на режим отображения текста формы.</p><p><a href="https://forum.fgx-native.com/uploads/monthly_2025_09/image.png.5fa5fffd385dc4796fcf77d7c9831d43.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block" data-fileid="5498" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="5498" src="https://forum.fgx-native.com/uploads/monthly_2025_09/image.thumb.png.7c13268526db2aa9b133f7a486d2f8a5.png" alt="image.png" width="1000" height="389" loading="lazy"></a></p><p>(3) Теперь режим отображения сетки, границ компонентов, темы, стиля и тд. синхронизируется между дизайнерами форм. И например отображение сетки в одной форме приводит к отображению сетки на всех формах.</p><h2>Заключение</h2><p>Если в ходе миграции или проверки ваших приложений на <strong>1.19.0.0</strong> вы столкнулись с трудностями или у вас есть предложения, пожалуйста, дайте нам знать.</p>]]></description><guid isPermaLink="false">76</guid><pubDate>Tue, 02 Sep 2025 19:18:08 +0000</pubDate></item><item><title>&#x41D;&#x43E;&#x432;&#x44B;&#x435; &#x432;&#x43E;&#x437;&#x43C;&#x43E;&#x436;&#x43D;&#x43E;&#x441;&#x442;&#x438; &#x43A;&#x430;&#x43D;&#x432;&#x44B; &#x432; 1.18.14.0</title><link>https://forum.fgx-native.com/blogs/entry/75-%D0%BD%D0%BE%D0%B2%D1%8B%D0%B5-%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8-%D0%BA%D0%B0%D0%BD%D0%B2%D1%8B-%D0%B2-118140/</link><description><![CDATA[<p>Добрый день,</p><p>В скором времени выйдет новое крупное обновление <strong>1.18.14.0</strong>, в которое войдет новый функционал, который вам однозначно пригодится. В этой статье рассмотрим новые графические возможности по работе с канвой <code>TfgCanvas</code>.</p><h2>Работа с состоянием канвы</h2><p>Перед тем, как мы перейдем к новым возможностям, мы обязаны рассмотреть изменения в работе с состоянием канвы. Поскольку эти изменения необходимы для корректной работы с обрезанием изображений по произвольным кривым.</p><p>Напомню, что при работе с канвой <code>TfgCanvas</code> разработчик постоянно меняет ее параметры (настройки кисти, матрицы трансформации и т.д.). Поэтому, очень удобно иметь контрольные точки при отрисовке, к которым можно сбросить состояние канвы, чтобы не устанавливать все настройки заново. Для этих целей используются методы <code>SaveState</code> / <code>RestoreState</code>. Метод <code>SaveState</code> возвращал объект состояния, который в дальнейшем нужно было передавать в парный метод <code>RestoreState</code> для восстановления состояния. В новой версии, объект состояния больше не нужно использовать.</p><p><strong>Было</strong>:</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>var
  State: IFGXSaveState;

State := ACanvas.SaveState;
try
  // Задаем параметры отрисовки
  // Выполняем отрисовку  
finally 
  ACanvas.RestoreState(State);
end;</code></pre><p><strong>Стало</strong>:</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>ACanvas.SaveState;
try
  // Задаем параметры отрисовки
  // Выполняем отрисовку  
finally 
  ACanvas.RestoreState;
end;</code></pre><p>Теперь при вызове <code>SaveState</code>, канва автоматически сохраняет состояние во внутренний стек, а при вызове <code>RestoreState</code> извлекает его из стека и восстанавливает. </p><p><strong><u>Зачем?</u></strong> </p><p>Первая причина: Раньше мы сохраняли только параметры кистей, параметры шрифта, режим смешивания цветов и матрицу преобразования. Это было обусловленно тем, что мы в любой момент могли самостоятельно задать любые параметры канвы. Однако, в данном релизе добавлена операция накладывания произвольной области отсечения, которая является не обратимой операцией (это значит, что заданную область отсечения нельзя убрать парным методом). Единственный способ, сбросить или откатить заданную область отсечения - это использовать нативный механизм работы с состоянием канвы. В связи с этим, мы перешли от нашей реализации к нативной, которая НЕ предусматривает восстановление к произвольному состоянию. </p><p>Вторая причина: Чаще всего при выполнении последовательной отрисовки, восстановление канвы требуется не на произвольное состояние, а именно на предыдущее состояние.     </p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>{ State 1 }
ACanvas.SaveState; // Save State 1
{ State 2 }    
try
  // Задаем параметры отрисовки
  // Выполняем отрисовку  
  ACanvas.SaveState; // Save State 2
  try
    // Другая вложенная отрисовка
  finally 
    ACanvas.RestoreState; // Rollback to State 2
  end;
finally 
  ACanvas.RestoreState; // Rollback to State 1
end;</code></pre><p><strong><span data-i-color="red">Внимание</span></strong>: Не смотря на то, что старый подход по работе с состоянием сохранился, он может не корректно работать при использовании областей отсечения <code>TfgCanvas.ClipPath</code>.</p><h2>Обрезание по пути</h2><p>Одна из самых интересных графических возможностей - это ограничение области отрисовки на канве произвольной фигурой или путем. Накладывание ограничения выполняется при помощи нового метода <code>TfgCanvas.ClipPath</code>.</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>    /// &lt;summary&gt;
    ///   Выполняет накладывание области отсечения будущих команд отрисовки. Чтобы отменить наложенную область ограничения
    ///   необходимо использовать методы &lt;c&gt;SaveState&lt;/c&gt; / &lt;c&gt;RestoreState&lt;/c&gt;. Перед наложение области сохранить состояние
    ///   канвы, а после завершения работы - восстановить.
    /// &lt;/summary&gt;
    procedure ClipPath(const APath: TfgPath);</code></pre><p>Рассмотрим пример, где мы хотим нарисовать два овала красного и синего цветов. Красный обрезать по вписанному овалу в область отрисовки, а синий - не обрезать. </p><p><a href="https://forum.fgx-native.com/uploads/monthly_2025_08/simulator_screenshot_6444AD7F-C9BF-4EA5-BD3B-A26C91255748.png.fa6406e657dd22834f2da355664fcae5.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block" data-fileid="5435" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="5435" src="https://forum.fgx-native.com/uploads/monthly_2025_08/simulator_screenshot_6444AD7F-C9BF-4EA5-BD3B-A26C91255748.thumb.png.174680d27d4acc4b9a11f77bda226fab.png" alt="simulator_screenshot_6444AD7F-C9BF-4EA5-BD3B-A26C91255748.png" width="345" height="750" loading="lazy"></a></p><p>Тогда код по отрисовке будет выглядить так:</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>procedure TFormMain.fgPaintBoxPaint(Sender: TObject; const ACanvas: TfgCanvas);
var
  CirclePath: TfgPath;
begin
  // Сохраняем состояние, чтобы в будущем убрать область отсечения
  ACanvas.SaveState;
  CirclePath := TfgPath.Create(nil);
  try
    // Формируем область отсечения в виде эллипса, вписанного в область отрисовки.
    CirclePath.AddArc(fgPaintBox.LocalBounds, 0, 360)
              .ClosePath;
    ACanvas.ClipPath(CirclePath);

    // Рисуем красный круг, он будет обрезан 
    ACanvas.Fill.Kind := TfgBrushKind.Solid;
    ACanvas.Fill.Color := TAlphaColorRec.Red;
    ACanvas.FillCircle(TPointF.Create(0, fgPaintBox.Height / 2), fgPaintBox.Height / 2);
  finally
    CirclePath.Free;
  end;
  // Сбрасываем область отсечения
  ACanvas.RestoreState;
  
  // Рисуем синий круг без ограничений
  ACanvas.Fill.Color := TAlphaColorRec.Blue;
  ACanvas.FillCircle(TPointF.Create(fgPaintBox.Width, fgPaintBox.Height / 2), fgPaintBox.Height / 2);</code></pre><p><strong>Где это может пригодиться</strong>? Одной из областей применения может стать динамическая отрисовка изображений, обрезанных по произвольной фигуре. Например, вы хотите вывести фотографии или аватарки пользователей в виде круга или какой-нибудь декоративной рамки. Раньше вы могли использовать для этой цели маски. Для этого вам надо было сформировать изображение маски, и затем выполнить отрисовки битмапа с учетом этой маски. Теперь эта операция может выполняться гораздо проще, быстрее и без использования дополнительной памяти.</p><p><a href="https://forum.fgx-native.com/uploads/monthly_2025_08/simulator_screenshot_66B9A973-8B5E-42AD-8E90-4762BE9D9677.png.ed9845e0141ab08cadb32c6061bcea5b.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block" data-fileid="5437" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="5437" src="https://forum.fgx-native.com/uploads/monthly_2025_08/simulator_screenshot_66B9A973-8B5E-42AD-8E90-4762BE9D9677.thumb.png.8b11396fd7344cb7c5e95e1ec8892208.png" alt="simulator_screenshot_66B9A973-8B5E-42AD-8E90-4762BE9D9677.png" width="345" height="750" loading="lazy"></a></p><p>У нас есть изображение, которое мы хотим вывести в круглом варианте и декорировать белым кольцом. Код может выглядить следующим образом. Фотография находится в менеджере ресурсов.</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>procedure TFormMain.fgPaintBox1Paint(Sender: TObject; const ACanvas: TfgCanvas);
var
  PhotoBitmap: TfgBitmap;
  FramePath: TfgPath;
  FrameBounds: TRectF;
begin
  // Извлекаем изображение
  if not TfgAssetsManager.Current.TryGetBitmap(R.Bitmap.PHOTO, PhotoBitmap) then
    Exit;

  ACanvas.SaveState;
  try
    // Формируем круглую форму рамки и рисуем битмап
    FramePath := TfgPath.Create(nil);
    try
      FrameBounds := fgPaintBox1.LocalBounds;
      FramePath.AddArc(FrameBounds, 0, 360)
              .ClosePath;
      ACanvas.ClipPath(FramePath);
      ACanvas.DrawBitmap(PhotoBitmap, FrameBounds);
    finally
      FramePath.Free;
    end;
  finally
    ACanvas.RestoreState;
  end;

  // Декорируем белым кольцом
  ACanvas.Stroke.Thickness := 10;
  ACanvas.Stroke.Color := TAlphaColorRec.White;
  ACanvas.DrawCircle(FrameBounds.CenterPoint, FrameBounds.Width / 2 - 10);
end;</code></pre><h2>Заполнение пути</h2><p>Есть как минимум два способа заливки кривых фигур по пути <code>TfgPath</code>. По умолчанию, в <strong>FGX Native</strong> использовался способ заливки правой фигуры. Теперь же вы можете выбирать способ заливки и указывать его через свойство <code>TfgCanvas.FillPathRule</code>. Помимо этого, теперь это свойство так же доступно в компоненте <code>TfgSvgPath</code>.</p><p><img class="ipsImage ipsRichText__align--block" data-fileid="5438" src="https://forum.fgx-native.com/uploads/monthly_2025_08/image.png.5874c67736d1e48eb8990b96f2ae169c.png" alt="image.png" width="610" height="315" loading="lazy"></p><p>Детали о двух способах заливки доступны <a rel="external nofollow" href="https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/fill-rule">здесь</a>.</p><p><strong><span data-i-color="red">Внимание</span></strong>: Данная настройка пока не поддерживается в дизайнере, так как не поддерживается на уровне FMX, которая используется для реализации в дизайнере.</p><h2>Штрихи кисти</h2><p>Теперь вы можете использовать свои варианты штрихов при отрисовки кривых. На уровне кисти <code>TfgStrokeBrush</code> доступен новый вид линии - <code>Dash = Custom</code>. Параметры штриха задаются через новый метод <code>TfgStrokeBrush.SetCustomDash</code>.</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>procedure TfgStrokeBrush.SetCustomDash(const ADash: TDashArray; const AOffset: Single);</code></pre><ul><li><p><code>ADash</code> - это массив парных значений. Первое - это длина штриха, второе - длина пробела.</p></li></ul><h2>SVG</h2><p>В этом релизе расширена поддержка параметров SVG, а именно добавлена поддержка следующих атрибутов: <code>stroke-dasharray</code>, <code>stroke-dashoffset</code>, <code>stroke-linecap</code>, <code>stroke-linejoin</code>, <code>fill-rule</code>.</p><h2>Редактор градиента</h2><p>Мы добавили дизайнер для управления параметрами градиента. Новое окно доступно через кнопку, встроенную в свойство типа <code>TfgGradient</code>.</p><p><a href="https://forum.fgx-native.com/uploads/monthly_2025_08/image.png.d9b9416a0a19c3a3adb5742e4ed38869.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block" data-fileid="5436" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="5436" src="https://forum.fgx-native.com/uploads/monthly_2025_08/image.thumb.png.8906a92038727790a863a6544038a80d.png" alt="image.png" width="1000" height="851" loading="lazy"></a></p><p>Данный дизайнер позволяет, управлять практически всеми параметрами градиента:</p><ol><li><p><strong>Добавлять и удалять точки градиента</strong>. Чтобы добавить точку, нужно нажать в свободное место на нижнем компоненте с отображением градиента. Чтобы удалить, точку надо утянуть за пределы компонента.</p></li><li><p>Менять тип градиента - линейный или радиальный</p></li><li><p>Менять направление градиента при помощи точек на правой панели просмотра градиента.</p></li><li><p>Сбросить параметры градиента до значений по умолчанию.</p></li></ol><h2>Итог</h2><p>В следующей статье нас ждет обзор новой функции перетаскивания компонентов <strong>Drag &amp; Drop</strong>.</p>]]></description><guid isPermaLink="false">75</guid><pubDate>Mon, 04 Aug 2025 18:54:21 +0000</pubDate></item><item><title>Yandex AppMetrica - &#x430;&#x43D;&#x430;&#x43B;&#x438;&#x442;&#x438;&#x43A;&#x430; &#x43F;&#x440;&#x438;&#x43B;&#x43E;&#x436;&#x435;&#x43D;&#x438;&#x44F; &#x432; 1.18.9.0</title><link>https://forum.fgx-native.com/blogs/entry/71-yandex-appmetrica-%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D1%82%D0%B8%D0%BA%D0%B0-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B2-11890/</link><description><![CDATA[<p style="text-align: justify;">
	Добрый вечер,
</p>

<p>
	Если вас интересует, сколько пользователей используют ваше приложение, как часто, как именно и т.д., то вы можете использовать аналитику приложения от <strong>Firebase Google Analytics</strong>. Эта возможность была добавлена в <strong>1.18.5.0</strong>. 
</p>

<p>
	Начиная с версии <strong>1.18.9.0,</strong> мы добавили поддержку сбора аналитик так же и от сервиса <strong>Yandex AppMetrica</strong>. Ранее мы выкладывали инструкции, как это можно сделать самостоятельно, отдельно настраивать приложение, отдельно использовать разное API для отправки метрик. Однако, мы полностью интегрировали эту поддержку и теперь ей так же легко воспользоваться, как и <strong>Firebase Google Analytics</strong>. Но, обо всем по порядку.
</p>

<p>
	<strong><span style="font-size:22px;">Регистрация приложения в Yandex AppMetrica</span></strong>
</p>

<p>
	1. Регистрируемся на сервисе, если не сделали этого ранее: <a href="https://appmetrica.yandex.ru/" ipsnoembed="true" rel="external nofollow">https://appmetrica.yandex.ru/</a>
</p>

<p>
	1. Создаем <a href="https://appmetrica.yandex.ru/application/new" rel="external nofollow">новый проект</a> в учетной записи <strong>AppMetrica</strong> и даем ему название:
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="5105" href="https://forum.fgx-native.com/uploads/monthly_2025_01/image.png.2ed89fc8f57c301956bbd9e99a688a46.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="5105" data-unique="gezb8zu5p" style="height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2025_01/image.thumb.png.b15c47d8cb6cde8e7f9ea685d4854635.png" loading="lazy" height="490"></a>
</p>

<p>
	Затем <strong>далее</strong>. По окончании добавления сервис отобразит ваш <strong>API ключ</strong>, который нужно запомнить. Именно он будет использоваться для взаимодействия вашего приложения и сервиса <strong>Yandex AppMetriсa</strong>.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="5104" href="https://forum.fgx-native.com/uploads/monthly_2025_01/image.png.4b660f5ba263b497e973227713ed934f.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="5104" data-unique="s3m6m5tiw" style="height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2025_01/image.thumb.png.61a864b49d36a2d0e2df53a868083102.png" loading="lazy" height="510"></a>
</p>

<p>
	Теперь переходим к настройкам вашего проекта, путем перехода в пункт меню <strong>Settings </strong>-&gt; <strong>Main</strong> (<strong>Настройки</strong> -&gt; <strong>Главные</strong>) в левой панели.
</p>

<p>
	<em><u>Если нам необходимо связать наш проект с <strong>iOS </strong>приложением</u></em>. Среди большого числа настроек нас интересует вкладка "Основное" -&gt; "Universal Link". Нам необходимо заполнить поля <strong>Bundle ID</strong> и <strong>App Prefix</strong> на основании данных вашего iOS приложения, зарегистрированного в портале <a href="https://developer.apple.com/account/resources/profiles/list" rel="external nofollow">Apple Developer</a>.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="5106" href="https://forum.fgx-native.com/uploads/monthly_2025_01/image.png.36c8e34078b0ce2a3e3fb2cd1224d4ed.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="5106" data-unique="fwi7k4ant" style="width: 500px; height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2025_01/image.thumb.png.f52459503d838b7cbc2f6b79c047ea48.png" loading="lazy" height="500"></a>
</p>

<ul>
	<li>
		<strong>AppPrefix </strong>- это уникальный префикс, выданный Apple при участии в программе iOS разработчиков. Он же добавляется к названию пакета iOS приложения, тем самым формируя уникальное название приложения. Его можно найти в личном кабинете Apple на вкладке Membership:<br>
		<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="5108" href="https://forum.fgx-native.com/uploads/monthly_2025_01/image.png.a8ebc51bc19246b8a41e58b2f9b46182.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="5108" data-unique="7nqmljfoc" style="width: 500px; height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2025_01/image.thumb.png.2a7dbe02ebcb1bc4741788be3ff9811d.png" loading="lazy" height="330"></a>
	</li>
	<li>
		<strong>Bundle ID</strong> - это идентификатор пакета вашего <strong>FGX Native</strong> приложения. Если приложение уже зарегистрировано, то вы можете найти название пакета на сайте <strong>Apple</strong> в разделе <strong>Identifiers</strong>. <br>
		<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="5109" href="https://forum.fgx-native.com/uploads/monthly_2025_01/image.png.75da4303575af4e152e9a9d7b909ec05.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="5109" data-unique="086dpcxlf" style="width: 500px; height: 142px;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2025_01/image.thumb.png.83728b9c8bbc50a21bd8ab38af288ff5.png" loading="lazy" height="280"></a>
	</li>
</ul>

<p>
	После того, как вы указали все данные, необходимо включить "<strong>Использовать Universal Link</strong>" - это специальная технология, которая призвана обезопасить передачу статистики с устройств пользователя на сервера Yandex.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="5111" href="https://forum.fgx-native.com/uploads/monthly_2025_01/image.png.8ac1a5afa9d1f0d87fdcd7785eabbcbd.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="5111" data-unique="ryttvy2g5" style="width: 500px; height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2025_01/image.thumb.png.b891331f0fb72dc2de8bd50eb6f6a8df.png" loading="lazy" height="630"></a>
</p>

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

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="5110" href="https://forum.fgx-native.com/uploads/monthly_2025_01/image.png.a044675cbc928c046ceefcbc9e7fae14.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="5110" data-unique="6eyawuyiz" style="height: auto;" width="999" src="https://forum.fgx-native.com/uploads/monthly_2025_01/image.thumb.png.31416ab0ba6759d6ec65faa68c9604ef.png" loading="lazy" height="749.25"></a>
</p>

<p>
	Теперь ваш профиль приложения сконфигурирован для приема статистики с вашего приложения. Переходим к подключению <strong>Yandex AppMetrica</strong> к <strong>FGX Native</strong> приложению. 
</p>

<p>
	<strong><span style="font-size:22px;">Подключение и настройка Yandex AppMetrica в FGX Native приложении</span></strong>
</p>

<p>
	Чтобы подключить <strong>Yandex AppMetrica</strong> в приложении, достаточно настроить подключение в настройках проекта и бросить новый компонент <strong>TfgAppMetricaAnalytics</strong> на главную форму или дата модуль, который создается при старте приложения.
</p>

<p>
	1. Переходим в настройки приложения <strong>Project </strong>-&gt; <strong>FGX Options... </strong>-&gt; <strong>Services </strong>(Сервисы) -&gt; <strong>Yandex AppMetrica</strong> 
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="5112" href="https://forum.fgx-native.com/uploads/monthly_2025_01/image.png.99edf94432b58b40f200ebd5ad1952f0.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="5112" data-unique="y55dvn4pe" style="height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2025_01/image.thumb.png.ddac209ef6c0149a011ed04a0d5c7ed0.png" loading="lazy" height="650"></a>
</p>

<p>
	Для всех требуемых конфигураций <strong>Android 32-bits </strong>/ <strong>Android 64-bits</strong> / <strong>iOS Device 64-bit</strong> включаем поддержку сервиса (<strong>Enabled </strong>- <span style="color:#e74c3c;"><strong>1</strong></span>) и указываем API ключ (<strong><span style="color:#e74c3c;">2</span></strong>).
</p>

<p>
	Опционально можно поменять значение длительности сессии. По умолчанию <strong>AppMetrica</strong> использует значение 10 секунд. Если в течении этого времени пользователь ничего не будет делать в приложении, то это будет означать, что при новом взаимодействии пользователя с приложением, это будет считаться как новая сессия взаимодействия пользователя. 
</p>

<p>
	2. Бросаем на главную форму или дата модуль, который создается при запуске приложения, новый компонент <strong>TfgAppMetricaAnalytics</strong>. Через него же можно будет отправлять пользовательские события.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="5114" href="https://forum.fgx-native.com/uploads/monthly_2025_01/image.png.196ea55f53e69e572553a53e00d25b52.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="5114" data-unique="w7gme65r8" style="height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2025_01/image.thumb.png.718a00990378075a7976c02801d99420.png" loading="lazy" height="380"></a>
</p>

<p>
	После чего все готово и можно запускать приложение.
</p>

<p>
	<strong><span style="font-size:22px;">Как посмотреть статистику</span></strong>
</p>

<p>
	Чтобы посмотреть аналитику, нужно перейти в личный кабинет Yandex AppMetrica: <a href="https://appmetrica.yandex.ru/overview" ipsnoembed="true" rel="external nofollow">https://appmetrica.yandex.ru/overview</a> и уже на главной странице можно будет увидеть информацию о количестве установок вашего приложения, аудитории, падениях приложения и т.д.
</p>

<p>
	<span style="color:#e74c3c;"><strong>Важно</strong></span>: первые отчеты в <strong>AppMetrica</strong> появляются с небольшой задержкой, а не в режиме реального времени. Если приложение запустилось без видимых ошибок, то подождите пару минут появления метрик на портале <a href="https://appmetrica.yandex.ru/application" ipsnoembed="true" rel="external nofollow">https://appmetrica.yandex.ru/application</a>
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="5115" href="https://forum.fgx-native.com/uploads/monthly_2025_01/image.png.bd5ca46b41aeff988f7a8e1407ef8397.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="5115" data-unique="ubbgci2vf" style="height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2025_01/image.thumb.png.89883b5a9503d9a4882b788a599a7198.png" loading="lazy" height="580"></a>
</p>

<p>
	В разделе <strong>Technologies</strong>/<strong>Технологии</strong> будут доступны интересные технические отчеты о версиях SDK, приложениях, размерах экранов, типах устройств и многое другое.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="5116" href="https://forum.fgx-native.com/uploads/monthly_2025_01/image.png.a7640e39a877f7c5504e8149bf40c18f.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="5116" data-unique="5fu2t0xrl" style="height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2025_01/image.thumb.png.f9330a6d8d933a2eb80fb2a3deb04c1b.png" loading="lazy" height="610"></a>
</p>

<p>
	<strong><span style="font-size:22px;">Отслеживание экранов приложения и отправка пользовательских метрик</span></strong>
</p>

<p>
	В интеграции сервиса у нас встроены две дополнительные возможности:
</p>

<p>
	1. Это отслеживания открытых форм/экранов вашего приложения.
</p>

<p>
	Если вы хотите узнать, с какими экранами чаще всего взаимодействуют ваши пользователи, вы можете воспользоваться методом компонента <strong>SetCurrentScreen</strong>. Данный метод отправляет на сервер информацию о названии формы/экрана и ее классе.
</p>

<p>
	Типичный пример отслеживания открытия формы, может выглядеть так:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2093_20" style=""><span class="pln">procedure TFormMain.fgFormShow(Sender: TObject);
begin
  fgAppMetricaAnalytics1.SetCurrentScreen(Name, ClassName);
end;</span></pre>

<p>
	После запуска приложения, в личном кабинете <strong>AppMetrica</strong> на вкладке <strong>Reports </strong>/ <strong>Отчеты </strong>-&gt; <strong>Events </strong>/ <strong>События </strong>можно наблюдать названия открытых экранов:
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="5117" href="https://forum.fgx-native.com/uploads/monthly_2025_01/image.png.4bcd7d983e963cbb298a5e4b340360d5.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="5117" data-unique="m8owjqeyv" style="height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2025_01/image.thumb.png.eb686220b253132bf41d72bf67baad7b.png" loading="lazy" height="680"></a>
</p>

<p>
	2. Для отправки своего события на сервер, можно воспользоваться методом LogEvent. Доступно две версии этого метода: простой и с параметрами:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2093_22" style=""><span class="pln">    /// </span><span class="tag">&lt;summary&gt;</span><span class="pln">
    ///   Отправляет на сервер AppMetrica событие с именем </span><span class="tag">&lt;c&gt;</span><span class="pln">AName</span><span class="tag">&lt;/c&gt;</span><span class="pln">, параметрами c именами </span><span class="tag">&lt;c&gt;</span><span class="pln">AKeys</span><span class="tag">&lt;/c&gt;</span><span class="pln"> и значениями
    ///   </span><span class="tag">&lt;c&gt;</span><span class="pln">AValues</span><span class="tag">&lt;/c&gt;</span><span class="pln">.
    /// </span><span class="tag">&lt;/summary&gt;</span><span class="pln">
    procedure LogEvent(const AName: string; const AKeys: TArray</span><span class="tag">&lt;string&gt;</span><span class="pln">; const AValues: array of const); overload;

    /// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Отправляет на сервер AppMetrica событие с именем </span><span class="tag">&lt;c&gt;</span><span class="pln">AName</span><span class="tag">&lt;/c&gt;</span><span class="pln">.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
    procedure LogEvent(const AName: string); overload;</span></pre>

<p>
	 <strong>Например</strong>, если мы хотим зафиксировать, что пользователь в приложении покупок нажимал на кнопку "положить товар в корзину", то отправка этого события может выглядеть так:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_2093_24" style=""><span class="pln">LogEvent('Положили в корзину', ['product_id', 'product_name', price], [1423, 'Sony PlayStation 5', 60000]);</span></pre>

<p>
	<strong><span style="font-size:22px;">Решение возможных проблем</span></strong>
</p>

<p>
	<span style="font-size:18px;"><em>Приложение падает на старте</em></span>
</p>

<p>
	Если приложение при запуске падает, то скорее всего, вы:
</p>

<ol>
	<li>
		либо не указали API ключ
	</li>
	<li>
		или же указали некорректный ключ
	</li>
	<li>
		либо не включили сервис в настройках проекта
	</li>
</ol>

<p>
	Еще раз проверьте, что все пункты выше выполнены. Так же, при таком падении, можно узнать причину падения в логе устройства, что на <strong>iOS</strong>, что и на <strong>Android</strong>.
</p>

<p>
	<em><span style="font-size:18px;">Приложение падает на старте и вы используете компоненты <strong>FireDAC</strong>. (спасибо <a contenteditable="false" data-ipshover="" data-ipshover-target="https://forum.fgx-native.com/profile/73-roman/?do=hovercard" data-mentionid="73" href="https://forum.fgx-native.com/profile/73-roman/" id="ips_uid_6979_6" rel="">@Roman</a>)</span></em>
</p>

<blockquote class="ipsQuote" data-gramm="false" data-ipsquote="">
	<div class="ipsQuote_citation">
		Quote
	</div>

	<div class="ipsQuote_contents ipsClearfix" data-gramm="false">
		<p>
			Отдельно хочу отметить, что при использовании в приложении компонента <strong>TFDConnection </strong>с драйвером SQLite (<strong>TFDConnection.DriverName=SQLite</strong>), по умолчанию устанавливается режим статической привязки движка <strong>SQLite</strong>. Что в свою очередь, после интеграции <strong>YandexAppMetrica</strong>, приводит к падению iOS-приложения при запуске.
		</p>

		<p>
			Для исправления проблемы необходимо:
		</p>

		<ol>
			<li>
				вместе с TFDConnection разместить компонент <strong>TFDPhysSQLiteDriverLink</strong>;
			</li>
			<li>
				установить динамическую привязку SQLite: <strong>TFDPhysSQLiteDriverLink.EngineLinkage=slDynamic</strong>;
			</li>
			<li>
				в модуле, который использует <strong>TFDConnection</strong>, из uses удалить <strong>FireDAC.Phys.SQLiteWrapper.Stat</strong>. 
			</li>
		</ol>

		<p>
			Обратите внимание!<br>
			Все вышеописанное справедливо ТОЛЬКО для <strong>iOS</strong>!
		</p>

		<p>
			Для Android необходима статическая привязка движка <strong>SQLite</strong>!
		</p>

		<p>
			Чтобы ваше приложение на <strong>Android </strong>смогло работать с БД, необходимо пойти по одному из вариантов:
		</p>

		<ol>
			<li>
				для <strong>Android </strong>использовать отдельный модуль данных со статической привязкой SQLite;
			</li>
			<li>
				перед сборкой <strong>Android</strong>-приложения вернуть значение <strong>TFDPhysSQLiteDriverLink.EngineLinkage=slStatic</strong>.
			</li>
		</ol>

		<p>
			Надеюсь, эта информация позволит избежать аналогичных ошибок <span class="ipsEmoji">😉</span>
		</p>
	</div>
</blockquote>

<p>
	<span style="font-size:22px;"><strong>Заключение</strong></span>
</p>

<p>
	Подключение данного сервиса выполняется довольно просто и быстро в <strong>FGX Native</strong>, но при этом открывает для вас большой набор полезной статистики, которую вы можете предложить, как вашим клиентам, так и использовать ее для совершенствования ваших личных приложений. 
</p>
]]></description><guid isPermaLink="false">71</guid><pubDate>Fri, 24 Jan 2025 22:33:19 +0000</pubDate></item><item><title>&#x421;&#x435;&#x440;&#x432;&#x438;&#x441; &#x431;&#x438;&#x43E;&#x43C;&#x435;&#x442;&#x440;&#x438;&#x447;&#x435;&#x441;&#x43A;&#x43E;&#x439; &#x430;&#x443;&#x442;&#x435;&#x43D;&#x442;&#x438;&#x444;&#x438;&#x43A;&#x430;&#x446;&#x438;&#x438; (Touch ID, Face ID, Iris) 1.18.8.0</title><link>https://forum.fgx-native.com/blogs/entry/70-%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81-%D0%B1%D0%B8%D0%BE%D0%BC%D0%B5%D1%82%D1%80%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8-touch-id-face-id-iris-11880/</link><description><![CDATA[<p>
	Здравствуйте, уважаемые разработчики. 
</p>

<p style="text-align: justify;">
	Близится к своему завершению 2024 год, и, не смотря на то, что пришло время подводить итоги и готовиться к праздникам, мы ни на секунду не прекращаем развитие и усовершенствование библиотеки <strong>FGX Native</strong>. Финальным в этом году станет релиз под номером <strong>1.18.8.0</strong>, который будет содержать не только исправления ошибок, но и привнесёт ряд новых приятных возможностей. Одной из таких возможностей станет новый сервис биометрической аутентификации. 
</p>

<p>
	<span style="font-size: 20px;"><b>Что такое биометрическая аутентификация</b></span>
</p>

<p>
	В последние годы биометрическая аутентификация на смартфонах стала неотъемлемой частью повседневной жизни. Эта технология позволяет пользователям разблокировать устройства и авторизоваться в приложениях, используя уникальные физические характеристики, такие как отпечаток пальца, лицо или даже радужная оболочка глаза. Биометрическая идентификация заменяет или дополняет традиционные пароли и PIN-коды, делая процесс аутентификации быстрее и удобнее. <br>
	Преимущества биометрической аутентификации
</p>

<ol>
	<li>
		<strong>Удобство</strong>: Биометрические методы позволяют разблокировать телефон или войти в приложение быстрее, чем вводить пароль.
	</li>
	<li>
		<strong>Повышенная безопасность</strong>: Физические характеристики сложно подделать или украсть, что делает биометрию надежнее традиционных паролей.
	</li>
	<li>
		<strong>Персонализированный доступ</strong>: Биометрическая аутентификация позволяет настроить телефон так, чтобы только владелец мог получить к нему доступ.
	</li>
</ol>

<p>
	<strong><span style="font-size:20px;">Пример работы </span></strong><span style="font-size: 20px;"><b>биометрической аутентификации в приложении</b></span>
</p>

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

<div class="ipsSpoiler" data-ipsspoiler="">
	<div class="ipsSpoiler_header">
		<span>Spoiler</span>
	</div>

	<div class="ipsSpoiler_contents ipsClearfix" data-gramm="false">
		<p>
			<video class="ipsEmbeddedVideo" controls="" data-fileid="5052" data-unique="mqjhuwowt" id="ips_uid_5297_6" src="https://forum.fgx-native.com/uploads/monthly_2024_12/Demo.mp4.0c075a03b746a5a3b4fc596d4cb40d97.mp4" data-controller="core.global.core.embeddedvideo" preload="metadata">
				<source type="video/mp4" src="https://forum.fgx-native.com/uploads/monthly_2024_12/Demo.mp4.0c075a03b746a5a3b4fc596d4cb40d97.mp4"><a class="ipsAttachLink" data-fileext="mp4" data-fileid="5052" href="https://forum.fgx-native.com/applications/core/interface/file/attachment.php?id=5052&amp;key=4d3f6c04302c87230530b3dda40cb418" rel="">Demo.mp4</a>
			</source></video>
		</p>
	</div>
</div>

<p>
	<strong><span style="font-size:20px;">Компонент TfgBiometricAuthentication</span></strong>
</p>

<p>
	<strong>TfgBiometricAuthentication </strong>это невизуальный компонент, который позволяет запускать процесс биометрической аутентификации, а так же получать информацию о её текущем состоянии и типе.
</p>

<p>
	<span style="font-size:16px;"><strong>Настройки</strong></span>
</p>

<p>
	<strong>Title</strong>  - основной текст, объясняющий для чего именно осуществляется запрос аутентификации. Старайтесь не указывать имя приложения, потому что, как правило, оно будет отображено самой ОС.<br>
	<strong>Fallback.Kind</strong> - Тип резервного действия на случай, если биометрическая аутентификация завершается неудачей. Возможны следующие варианты:
</p>

<ul>
	<li>
		<strong>Passcode </strong>- Использовать ключ (пароль, PIN-код, графический ключ).
	</li>
	<li>
		<strong>Action </strong>- Пользовательское действие.
	</li>
	<li>
		<strong>None </strong>- Не использовать резервное действие.
	</li>
</ul>

<p>
	<strong>Fallback.Action</strong> - Этот текст будет отображен на кнопке, если в качестве резервного действия выбрано пользовательское действие.<br>
	<strong>Subtitle </strong>- Подзаголовок. Актуально только для <strong>Android</strong>.<br>
	<strong>Description </strong>- Описание. Актуально только для <strong>Android</strong>. 
</p>

<p>
	<span style="font-size:16px;"><strong>Методы</strong></span>
</p>

<p>
	<strong>Authenticate </strong>- Запуск асинхронного процесса биометрической аутентификации с учётом выбранных настроек. Функция возвращает булево значение в зависимости от успешности запуска процесса аутентификации. Чтобы узнать причину неудачного запуска вы можете проанализировать состояние <strong>AInfo.State</strong> в перегруженной версии метода.  Результат процесса аутентификации будет передан в одном из событий компонента.<br>
	<strong>GetBiometricInformation</strong> - Получение информации о состоянии и типе биометрической аутентификации. При запросе передается флаг <strong>AAllowUsePasscode</strong>, который будет учитывать<br>
	планируете ли вы разрешать использовать ключ (пароль, PIN-код, графический ключ) в качестве резервного способа аутентификации. Результат возвращается в виде записи <strong>TfgBiometricInfo</strong>.<br>
	<strong>TfgBiometricInfo.Kind</strong> - Тип биометрической аутентификации, доступной на устройстве:
</p>

<ul>
	<li>
		<strong>TouchID </strong>- Биометрическая аутентификация по отпечатку пальца.
	</li>
	<li>
		<strong>FaceID </strong>- Биометрическая аутентификация по лицу.
	</li>
	<li>
		<strong>Iris </strong>- Биометрическая аутентификация по радужной оболочке глаза.
	</li>
</ul>

<p>
	<strong>TfgBiometricInfo.State</strong> - Текущее состояние биометрической аутентификации, доступной на устройстве. 
</p>

<ul>
	<li>
		<strong>Error </strong>- При определении состояния произошла ошибка.
	</li>
	<li>
		<strong>Supported </strong>- Биометрическая аутентификация поддерживается на устройстве.
	</li>
	<li>
		<strong>Unsupported </strong>- Биометрическая аутентификация не поддерживается на устройстве.
	</li>
	<li>
		<strong>NotEnrolled </strong>- Пользователь не настроил биометрическую аутентификацию.
	</li>
	<li>
		<strong>Unavailable </strong>- Биометрическая аутентификация недоступна в данный момент.
	</li>
	<li>
		<strong>Locked </strong>- Биометрическая аутентификация заблокирована (например превышено количество попыток).
	</li>
</ul>

<p>
	Важно: в случае, если вас интересует только биометрическая аутентификация и вы не планируете разрешать использовать ключ в качестве резервного варианта, устанавливайте параметр <strong>AAllowUsePasscode = False</strong>. В противном случае при ненастроенной биометрической аутентификации и наличии ключа вы получите <strong>State = Supported</strong>, что может создать впечатление доступности биометрической аутентификации.
</p>

<p>
	<strong><span style="font-size:16px;">События</span></strong>
</p>

<p>
	<strong>OnAuthenticationError </strong>- Событие возникает при неудачной аутентификации. Подробности возникшей проблемы вы можете узнать из аргумента <strong>AError</strong>.<br>
	<strong>OnAuthenticationSuccess </strong>- Событие возникает при успешной аутентификации.<br>
	<strong>OnAuthenticationFallbackAction </strong>- Событие возникает, если пользователь выбрал резервный способ аутентификации. В этом событии вы можете предложить пользователям альтернативный вариант аутентификации - например по логину и паролю.
</p>

<p>
	<span style="font-size:20px;"><strong>Использование биометрической аутентификации без компонента</strong></span>
</p>

<p>
	Процесс биометрической аутентификации осуществляется с помощью интерфейса <strong>IFGXBiometricAuthentication</strong>, который вы можете получите напрямую из платформенного сервиса <strong>IFGXBiometricAuthenticationService</strong>, либо фабрики <strong>TfgBiometricAuthenticationFactory</strong>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5297_8" style=""><span class="kwd">class</span><span class="pln"> function </span><span class="typ">TfgBiometricAuthenticationFactory</span><span class="pun">.</span><span class="typ">CreateBiometricAuthentication</span><span class="pun">:</span><span class="pln"> </span><span class="typ">IFGXBiometricAuthentication</span><span class="pun">;</span><span class="pln">
var
  </span><span class="typ">LService</span><span class="pun">:</span><span class="pln"> </span><span class="typ">IFGXBiometricAuthenticationService</span><span class="pun">;</span><span class="pln">
begin
  </span><span class="kwd">if</span><span class="pln"> not </span><span class="typ">TfgPlatformServicesManager</span><span class="pun">.</span><span class="typ">RequestService</span><span class="pun">(</span><span class="typ">IFGXBiometricAuthenticationService</span><span class="pun">,</span><span class="pln"> </span><span class="typ">LService</span><span class="pun">)</span><span class="pln"> then
    raise </span><span class="typ">EfgPlatformService</span><span class="pun">.</span><span class="typ">CreateFmt</span><span class="pun">(</span><span class="typ">SServiceIsNotSupported</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="str">'IFGXBiometricAuthenticationService'</span><span class="pun">]);</span><span class="pln">

  </span><span class="typ">Result</span><span class="pln"> </span><span class="pun">:=</span><span class="pln"> </span><span class="typ">LService</span><span class="pun">.</span><span class="typ">CreateBiometricAuthentication</span><span class="pun">;</span><span class="pln">
end</span><span class="pun">;</span></pre>

<p>
	Интерфейс <strong>IFGXBiometricAuthentication  </strong>реализует <strong>Fluent interface</strong>, что позволяет удобно настраивать аутентификацию и запускать её.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4292_9" style=""><span class="typ">TfgBiometricAuthenticationFactory</span><span class="pun">.</span><span class="typ">CreateBiometricAuthentication</span><span class="pln">
    </span><span class="pun">.</span><span class="typ">SetFallbackAsPasscode</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">.</span><span class="typ">SetSubtitle</span><span class="pun">(</span><span class="str">'Subtitle'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="typ">SetDescription</span><span class="pun">(</span><span class="str">'Description'</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">.</span><span class="typ">Execute</span><span class="pun">(</span><span class="typ">BiometricAuthenticationResul</span><span class="pun">,</span><span class="pln"> </span><span class="str">'Title'</span><span class="pun">);</span></pre>

<p>
	Нет надобности хранить ссылку на <strong>IFGXBiometricAuthentication </strong>до окончания процесса аутентификации. Память будет автоматически освобождена при условии, что снаружи никто не держит ссылку на интерфейс.<br>
	Важно помнить, что нельзя повторно запускать процесс аутентификации для одного и того же экземпляра <strong>IFGXBiometricAuthentication </strong>не смотря то, с каким именно результатом завершился предыдущий процесс. В противном случае будет возбуждено исключение <strong>EfgBiometricAuthentication</strong>.
</p>

<p>
	<span style="font-size:20px;"><strong>Настройки проекта</strong></span>
</p>

<p>
	Есть некоторые отличия в настройках проекта между <strong>Android </strong>и <strong>iOS</strong>.<br>
	Для <strong>Android </strong>необходимо поставить галочку <strong>Enabled</strong>, чтобы при сборке проекта добавилась необходимая библиотека-зависимость.<br>
	Для <strong>iOS </strong>необходимо описать причину, почему вашему приложению необходим доступ к биометрической аутентификации. Данный текст будет показан пользователю при первой попытке приложения использовать биометрическую аутентификацию.
</p>

<p>
	<span style="font-size:20px;"><strong>Минимально поддерживамые версии</strong></span>
</p>

<p>
	<strong>Android: </strong>Android 6 (API level 23)<br>
	<strong>iOS: </strong>iOS 8.0
</p>

<p>
	<span style="font-size:20px;"><strong>Заключение</strong></span>
</p>

<p>
	Для того, чтобы лучше ознакомиться с возможностями нового сервиса мы подготовили демо пример "<strong>Authentication - Biometric\BiometricAuthentication.dproj</strong>", который дополнит коллекцию примеров, входящих в дистрибутив библиотеки <strong>FGX Native</strong>.
</p>

<p>
	Спасибо за внимание и с наступающими вас новогодними праздниками!
</p>
]]></description><guid isPermaLink="false">70</guid><pubDate>Sat, 14 Dec 2024 23:38:44 +0000</pubDate></item><item><title>&#x410;&#x43D;&#x438;&#x43C;&#x438;&#x440;&#x43E;&#x432;&#x430;&#x43D;&#x43D;&#x430;&#x44F; &#x437;&#x430;&#x441;&#x442;&#x430;&#x432;&#x43A;&#x430;, &#x43D;&#x43E;&#x432;&#x44B;&#x435; &#x43D;&#x430;&#x441;&#x442;&#x440;&#x43E;&#x439;&#x43A;&#x438; &#x43F;&#x440;&#x43E;&#x435;&#x43A;&#x442;&#x430; &#x438; &#x443;&#x43F;&#x440;&#x43E;&#x449;&#x435;&#x43D;&#x43D;&#x430;&#x44F; &#x438;&#x43D;&#x442;&#x435;&#x433;&#x440;&#x430;&#x446;&#x438;&#x44F; &#x441;&#x435;&#x440;&#x432;&#x438;&#x441;&#x43E;&#x432; &#x432; 1.18.0.0</title><link>https://forum.fgx-native.com/blogs/entry/66-%D0%B0%D0%BD%D0%B8%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%B0%D1%8F-%D0%B7%D0%B0%D1%81%D1%82%D0%B0%D0%B2%D0%BA%D0%B0-%D0%BD%D0%BE%D0%B2%D1%8B%D0%B5-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B8-%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%B0-%D0%B8-%D1%83%D0%BF%D1%80%D0%BE%D1%89%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F-%D0%B8%D0%BD%D1%82%D0%B5%D0%B3%D1%80%D0%B0%D1%86%D0%B8%D1%8F-%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D0%BE%D0%B2-%D0%B2-11800/</link><description><![CDATA[<p>
	Добрый день, уважаемые разработчики. 
</p>

<p>
	FGX Native содержит большое количество разнообразных компонентов: начиная от визуальных компонентов, составляющих основу для создания UI вашего приложения, продолжая невизуальными компонентами, облегчающими отслеживание состояния вашего приложения  и заканчивая компонентами-интеграциями с различными сервисами. И если использование первых двух - не зависит от внешних сервисов, то третья - как раз часто требует настройки и более точной интеграции на стороне приложения.
</p>

<p>
	Так, например, при желании подключить Push-уведомления, вам нужно выбрать провайдера, выполнить первичную настройку на стороне сервиса и затем выполнить настройку клиента (<strong>FGX Native</strong> приложения). А при использовании <strong>Facebook </strong>аутентификации уже требуется гораздо больше действия, включая ручное подключение <strong>Android </strong>библиотек, добавление в деплой новых файлов, правку манифеста и тд.
</p>

<p>
	Отдельно стоит упомянуть про необходимость настроить приложение в целом: поменять заставку, настроить иконки и базовые цвета и так далее. Все это требует не столько кодирования, сколько внесения и размещения нужных значений параметров в манифесты и файлы настроек. К сожалению, эта часть настроек осуществляется при помощи штатного окна настройки проекта <strong>Project </strong>-&gt; <strong>Options</strong>. И поскольку мы не имеем возможности его как-то модифицировать, то мы не можем добавлять туда новые настройки и адаптировать логику. 
</p>

<p>
	Именно по этой причине в этом релизе <strong>1.18.0.0</strong> нас ждет новое окно настроек проекта.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" href="https://forum.fgx-native.com/uploads/monthly_2024_02/image.png.ff1490ef43d4d83a539348515e3c1b01.png" data-fileid="4668" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="4668" data-unique="ry02vndf9" width="1000" alt="image.png" src="https://forum.fgx-native.com/uploads/monthly_2024_02/image.thumb.png.1609fe45d009ca8e72b060a4eed8eb44.png" loading="lazy" height="640"></a>
</p>

<p>
	Однако стоит обратить внимание, что просто новое окно настроек не имеет смысла без интеграции процесса сборки <strong>MSBuild</strong>. Так как введенные параметры и настройки нужно передавать и упаковывать в собираемого приложение.  В течении несколько месяцев мы разрабатывали базовый механизм для создания расширяемого окна настроек. Основная идея - это добавление любых страниц настроек и внедрение в систему сборки <strong>MSBuild</strong> для любых сторонних сервисов. В рамках разработки мы написали несколько расширений для <strong>MSBuild</strong>, чтобы в будущем проект можно было собрать полностью с командной строки. Процесс перевода в пользу сборки целиком с помощью <strong>MSBuild</strong> еще не завершен полностью, но мы движемся в этом направлении.
</p>

<p>
	В этой статье мы не будем разбирать API для сторонних разработчиков, которое они могут использовать для регистрации своих настроек, а сосредоточимся на утилитарном использовании.
</p>

<p>
	<strong><span style="font-size:22px;">Анимированная заставка Android</span></strong>
</p>

<p>
	Первым главным нововведением нового окна настроек являются анимированные заставки для <strong>Android 12+</strong>. 
</p>

<ul>
	<li>
		<a href="https://developer.android.com/develop/ui/views/launch/splash-screen" ipsnoembed="true" rel="external nofollow">https://developer.android.com/develop/ui/views/launch/splash-screen</a>
	</li>
</ul>

<p>
	Начиная с <strong>Android 12+</strong> структура заставок изменилась и теперь появилась возможность использовать современные анимированные заставки. Раньше была статья, которая описывала детально ручные правки, которые можно было внести 
</p>
<iframe allowfullscreen="" class="ipsEmbed_finishedLoading" data-embedauthorid="2" data-embedcontent="" data-embedid="embed4541422846" id="ips_uid_3295_6" src="https://forum.fgx-native.com/topic/1586-splash-screen-%D0%BD%D0%B0-android-12/?do=embed&amp;comment=5425&amp;embedComment=5425&amp;embedDo=findComment#comment-5425" style="overflow: hidden; height: 331px; max-width: 500px;" loading="lazy"></iframe>

<p>
	Сейчас достаточно включить опцию и настроить внешний вид заставки. Описание параметров смотрите в <a href="https://developer.android.com/develop/ui/views/launch/splash-screen#elements" rel="external nofollow">официальной документации</a> Андроида.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4654" href="https://forum.fgx-native.com/uploads/monthly_2024_02/image.png.70a086c7135c46d0acee3ec639ae2798.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4654" data-unique="upa5vs2uq" style="height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2024_02/image.thumb.png.76947482dd3fa3c748eb866292ea4fe6.png" loading="lazy" height="700"></a>
</p>

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

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4659" href="https://forum.fgx-native.com/uploads/monthly_2024_02/image.png.a5b76650536d9f9172656bc9a61fd246.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4659" data-unique="f3rm9qgu6" style="width: 250px; height: auto;" width="337" src="https://forum.fgx-native.com/uploads/monthly_2024_02/image.thumb.png.722447517987c3e21fbb9effc7ffc463.png" loading="lazy" height="748.14"></a>
</p>

<p>
	Добавлен новый пример: "<strong>Android Api</strong>" -&gt; "<strong>Анимированная заставка</strong>"
</p>

<p>
	<strong>Примечание</strong>: Настройки статической версии заставки пока находятся в старом окне настроек. По мере возможности мы будем переносить значимые для нас настройки из старого окна настроек проекта в новое.
</p>

<p>
	<strong><span style="font-size:22px;">Google Maps</span></strong>
</p>

<p>
	<span id="cke_bm_256E" style="display: none;"> </span><a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4655" href="https://forum.fgx-native.com/uploads/monthly_2024_02/image.png.a0d10cd52d72dd11dee3bd4010fd1505.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4655" data-unique="ahz07g3qq" style="width: 600px; height: auto;" width="999" src="https://forum.fgx-native.com/uploads/monthly_2024_02/image.thumb.png.964f173985a4e775338057b3c264ed4a.png" loading="lazy" height="749.25"></a>
</p>

<p>
	<strong>Было</strong>: Раньше ключ карты указывался в стандартном окне настроек проекта в разделе <strong>VersionInfo</strong>. Помимо этого необходимо было включить поддержку карт в разделе "<strong>Entitlements List</strong>" -&gt; "<strong>Maps Service</strong>".
</p>

<p>
	<strong>Стало</strong><span>:</span> Теперь включение сервиса карт и <strong>API </strong>ключ указываются в разделе "<strong>Сервисы</strong>" -&gt; "<strong>Google Maps</strong>".
</p>

<p>
	<strong>Что нужно сделать</strong>: Дополнительных действий не требуется. При открытии проекта в этой версии ключ будет автоматически перенесен. Однако, после этого ключ надо менять только в новом окне настроек.
</p>

<p>
	<strong><span style="font-size:22px;">Facebook Login</span></strong>
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4657" href="https://forum.fgx-native.com/uploads/monthly_2024_02/image.png.f52529653df9774395d57af3358e49cb.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4657" data-unique="dyx5lj0mr" style="width: 600px; height: auto;" width="999" src="https://forum.fgx-native.com/uploads/monthly_2024_02/image.thumb.png.be5fe1c7dde5360ed973d078635009f9.png" loading="lazy" height="749.25"></a>
</p>

<p>
	<strong>Было</strong>: Раньше при использовании "<strong>Facebook Login</strong>" необходимо было вручную вносить настройки <strong>Facebook Login</strong> в файлы "<strong>strings.xml</strong>" и "<strong>info.plist.TemplateiOS.xml</strong>". Так же требовалось вручную добавлять зависимость на <strong>Android </strong>библиотеку и править <strong>Android </strong>манифест.
</p>

<p>
	<strong>Стало</strong>: Достаточно включить сервис в новых настройках "<strong>Сервисы</strong>" -&gt; "<strong>Аутентификация</strong>" -&gt; "<strong>Facebook Login</strong>" и указать требуемые параметры.
</p>

<p>
	<strong>Что нужно сделать</strong>: Если вы уже используете <strong>Facebook Login</strong>, то вы либо можете оставить все, как есть. Либо же перейти на новую настройку. Для этого нужно откатить все изменения сделанные в статьях:
</p>

<ul>
	<li>
		<a href="https://forum.fgx-native.com/blogs/entry/64-%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D1%8B-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-facebook-login-android/" rel="">Сервисы аутентификации. Аутентификация с помощью Facebook Login (Android)</a>
	</li>
	<li>
		<a href="https://forum.fgx-native.com/blogs/entry/41-%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D1%8B-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-facebook-login/" rel="">Сервисы аутентификации. Аутентификация с помощью Facebook Login (iOS).</a>
	</li>
</ul>

<p>
	И выполнить включение и ввод настроек в новом окне.
</p>

<p>
	<span style="font-size:22px;"><strong>VK Login</strong></span>
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4658" href="https://forum.fgx-native.com/uploads/monthly_2024_02/image.png.2936e9b23027bbc5c793b6f00b22c01f.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4658" data-unique="i91p3jesm" style="width: 600px; height: auto;" width="999" src="https://forum.fgx-native.com/uploads/monthly_2024_02/image.thumb.png.cb01ee983199e90fe53b4f1dc7ade4b9.png" loading="lazy" height="749.25"></a>
</p>

<p>
	<strong>Было</strong>: Раньше при использовании "<strong>VK Login</strong>" необходимо было вручную вносить настройки в файл "<strong>info.plist.TemplateiOS.xml</strong>".
</p>

<p>
	<strong>Стало</strong>: Достаточно включить сервис в новых настройках "<strong>Сервисы</strong>" -&gt; "<strong>Аутентификация</strong>" -&gt; "<strong>VK Login</strong>" и указать требуемые параметры.
</p>

<p>
	<strong>Что нужно сделать</strong>: Если вы уже используете <strong>VK Login</strong>, то вы либо можете оставить все, как есть, либо же перейти на новую настройку. Для этого нужно откатить все изменения сделанные в статьях:
</p>

<ul>
	<li>
		<a href="https://forum.fgx-native.com/blogs/entry/44-%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D1%8B-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-vk-login/" rel="">Сервисы аутентификации. Аутентификация с помощью VK Login (iOS)</a>
	</li>
</ul>

<p>
	И выполнить включение и ввод настроек в новом окне.
</p>

<p>
	<strong><span style="font-size:22px;">Заключение</span></strong>
</p>

<p>
	В следующих релизах мы будем переносить значимые параметры - такие как настройки Push-уведомлений, реклама, аналитика и тд.
</p>
]]></description><guid isPermaLink="false">66</guid><pubDate>Thu, 15 Feb 2024 21:36:52 +0000</pubDate></item><item><title>&#x421;&#x435;&#x440;&#x432;&#x438;&#x441;&#x44B; &#x430;&#x443;&#x442;&#x435;&#x43D;&#x442;&#x438;&#x444;&#x438;&#x43A;&#x430;&#x446;&#x438;&#x438;. &#x410;&#x443;&#x442;&#x435;&#x43D;&#x442;&#x438;&#x444;&#x438;&#x43A;&#x430;&#x446;&#x438;&#x44F; &#x441; &#x43F;&#x43E;&#x43C;&#x43E;&#x449;&#x44C;&#x44E; Facebook Login (Android)</title><link>https://forum.fgx-native.com/blogs/entry/64-%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D1%8B-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-facebook-login-android/</link><description><![CDATA[<p>
	<a href="https://forum.fgx-native.com/blogs/entry/41-%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D1%8B-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-facebook-login/" rel="">Ранее в блоге</a> мы уже рассматривали использование аутентификацию с помощью <strong>Facebook Login</strong> в рамках <strong>iOS </strong>приложения. В данной статье мы рассмотрим использование сервиса <strong>Facebook Login</strong> для <strong>Android </strong>приложений, поддержка которого появится в версии<strong> FGX Native 1.16.1.0</strong>.
</p>

<p>
	Настройка серверной части была подробно расписана в <a href="https://forum.fgx-native.com/blogs/entry/41-%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D1%8B-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8-%D0%B0%D1%83%D1%82%D0%B5%D0%BD%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-facebook-login/" rel="">статье для iOS</a>. Если вы ранее уже настраивали серверную часть для <strong>iOS </strong>приложения, то можете пропустить этот шаг. 
</p>

<p>
	Перейдем непосредственно к настройке приложения.
</p>

<p>
	 
</p>

<p>
	1. Добавить библиотеку-зависимость <strong>Facebook SDK</strong> в настройках проекта с помощью диалога <strong>Project </strong>-&gt; <strong>FGX Android Libraries</strong> -&gt; <strong>Добавить библиотеку-зависимость</strong>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9944_9" style=""><span class="pln">com.facebook.android:facebook-login:16.2.0</span></pre>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4443" href="https://forum.fgx-native.com/uploads/monthly_2023_09/image.png.efad038ad6188146b56804a7fb47400b.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4443" data-unique="i2lxf6dq7" style="height: auto; width: 500px;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2023_09/image.thumb.png.318e9c4f88ba60ec71e54929636ebca5.png" loading="lazy" height="680"></a>
</p>

<p>
	(на момент написания статьи (03/09/2023) актуальная версия <strong>SDK 16.2.0</strong>)
</p>

<p>
	2. Создаем текстовый файл в папке проекта с именем <strong>strings.xml</strong>, в который добавляем константы, взятые из настроек приложения на сервере.
</p>

<pre class="ipsCode prettyprint lang-xml prettyprinted" id="ips_uid_9944_17" style=""><span class="tag">&lt;resources&gt;</span><span class="pln">
    </span><span class="tag">&lt;string</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"app_name"</span><span class="tag">&gt;</span><span class="pln">APP-NAME</span><span class="tag">&lt;/string&gt;</span><span class="pln">
    </span><span class="tag">&lt;string</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"facebook_app_id"</span><span class="tag">&gt;</span><span class="pln">APP-ID</span><span class="tag">&lt;/string&gt;</span><span class="pln">
    </span><span class="tag">&lt;string</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"fb_login_protocol_scheme"</span><span class="tag">&gt;</span><span class="pln">fb1234</span><span class="tag">&lt;/string&gt;</span><span class="pln">
    </span><span class="tag">&lt;string</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"facebook_client_token"</span><span class="tag">&gt;</span><span class="pln">CLIENT-TOKEN</span><span class="tag">&lt;/string&gt;</span><span class="pln">
</span><span class="tag">&lt;/resources&gt;</span></pre>

<p>
	где <strong>APP-ID</strong> - <strong>App ID</strong> из шага <strong>8a</strong><br>
	<strong>CLIENT-TOKEN</strong> - <strong>Client token</strong> из шага <strong>8b</strong><br>
	<strong>APP-NAME</strong> - имя приложения
</p>

<p>
	3. Добавляем файл <strong>strings.xml</strong> в деплой приложения (<strong>Project </strong>-&gt; <strong>Deployment</strong>) для обеих платформ <strong>Android32</strong>/<strong>64</strong>. <strong>Remote path</strong> должен быть <strong>res\values\</strong>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4445" href="https://forum.fgx-native.com/uploads/monthly_2023_09/image.png.66fca0558f6551d6aa81c0d295714422.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4445" data-unique="pzz4y79d4" style="height: auto; width: 500px;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2023_09/image.thumb.png.8559f409267de7d48cfcc83609f4bf6a.png" loading="lazy" height="40"></a>
</p>

<p>
	4. Вносим изменения в шаблон манифеста <strong>AndroidManifest.template.xml </strong>сразу после плейсхолдера <strong>&lt;%fgx-activities%&gt;</strong> и до основной <strong>activity</strong>
</p>

<pre class="ipsCode prettyprint lang-xml prettyprinted" id="ips_uid_9944_21" style=""><span class="pln">        ...
        </span><span class="pun">&lt;%</span><span class="pln">fgx</span><span class="pun">-</span><span class="pln">activities%&gt;

          
        </span><span class="com">&lt;!--begin insertion--&gt;</span><span class="pln">  
        </span><span class="tag">&lt;meta-data</span><span class="pln"> </span><span class="atn">android:name</span><span class="pun">=</span><span class="atv">"com.facebook.sdk.ApplicationId"</span><span class="pln"> </span><span class="atn">android:value</span><span class="pun">=</span><span class="atv">"@string/facebook_app_id"</span><span class="tag">/&gt;</span><span class="pln">
        </span><span class="tag">&lt;meta-data</span><span class="pln"> </span><span class="atn">android:name</span><span class="pun">=</span><span class="atv">"com.facebook.sdk.ClientToken"</span><span class="pln"> </span><span class="atn">android:value</span><span class="pun">=</span><span class="atv">"@string/facebook_client_token"</span><span class="tag">/&gt;</span><span class="pln">

        </span><span class="tag">&lt;activity</span><span class="pln"> </span><span class="atn">android:name</span><span class="pun">=</span><span class="atv">"com.facebook.FacebookActivity"</span><span class="pln">
            </span><span class="atn">android:configChanges</span><span class="pun">=</span><span class="pln">
                    </span><span class="atv">"keyboard|keyboardHidden|screenLayout|screenSize|orientation"</span><span class="pln">
            </span><span class="atn">android:label</span><span class="pun">=</span><span class="atv">"@string/app_name"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
            
        </span><span class="tag">&lt;activity</span><span class="pln">
            </span><span class="atn">android:name</span><span class="pun">=</span><span class="atv">"com.facebook.CustomTabActivity"</span><span class="pln">
            </span><span class="atn">android:exported</span><span class="pun">=</span><span class="atv">"true"</span><span class="tag">&gt;</span><span class="pln">
            </span><span class="tag">&lt;intent-filter&gt;</span><span class="pln">
                </span><span class="tag">&lt;action</span><span class="pln"> </span><span class="atn">android:name</span><span class="pun">=</span><span class="atv">"android.intent.action.VIEW"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
                </span><span class="tag">&lt;category</span><span class="pln"> </span><span class="atn">android:name</span><span class="pun">=</span><span class="atv">"android.intent.category.DEFAULT"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
                </span><span class="tag">&lt;category</span><span class="pln"> </span><span class="atn">android:name</span><span class="pun">=</span><span class="atv">"android.intent.category.BROWSABLE"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
                </span><span class="tag">&lt;data</span><span class="pln"> </span><span class="atn">android:scheme</span><span class="pun">=</span><span class="atv">"@string/fb_login_protocol_scheme"</span><span class="pln"> </span><span class="tag">/&gt;</span><span class="pln">
            </span><span class="tag">&lt;/intent-filter&gt;</span><span class="pln">
        </span><span class="tag">&lt;/activity&gt;</span><span class="pln">
        </span><span class="com">&lt;!--end insertion--&gt;</span><span class="pln">    
          
        &lt;activity android:name="com.embarcadero.firemonkey.FMXNativeActivity"
        ....</span></pre>

<p>
	 
</p>

<p>
	<span style="color:#c0392b;"><strong>Внимание!</strong></span> Из-за ошибки в <strong>Facebook Login SDK</strong> пока недоступно получение дополнительных данных таких как email, имя и т.д. На данный момент в случае успешной аутентификации сервис возвращает только основной токен.
</p>

<p>
	Мы следим за исправлением этой ошибки и сообщим вам, как только это произойдет.
</p>

<p>
	 
</p>

<p>
	Спасибо за внимание.
</p>
]]></description><guid isPermaLink="false">64</guid><pubDate>Sun, 03 Sep 2023 20:48:09 +0000</pubDate></item><item><title>&#x41D;&#x43E;&#x432;&#x44B;&#x435; &#x43C;&#x435;&#x442;&#x43E;&#x434;&#x44B; &#x43F;&#x43E; &#x440;&#x430;&#x431;&#x43E;&#x442;&#x435; &#x441; TfgBitmap &#x438; EXIF &#x432; 1.16.0.0</title><link>https://forum.fgx-native.com/blogs/entry/63-%D0%BD%D0%BE%D0%B2%D1%8B%D0%B5-%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D1%8B-%D0%BF%D0%BE-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B5-%D1%81-tfgbitmap-%D0%B8-exif-%D0%B2-11600/</link><description><![CDATA[<p>
	Добрый день, уважаемые разработчики. 
</p>

<p>
	Продолжаем обзор новых возможностей <strong>1.16.0.0</strong> и в этой статье поговорим об улучшениях связанных с изображениями.
</p>

<p>
	В этом релизе мы добавили вспомогательные методы для решения часто встречаемых задач: таких как кадрирование, превью, изменение размера, повороты и перекрашивание. 
</p>

<p>
	Для того, чтобы воспользоваться методами необходимо подключить модуль "<strong>FGX.Bitmap.Helpers</strong>" в секцию <strong>uses</strong>. 
</p>

<p>
	<span style="font-size:22px;"><strong>Кадрирование - Crop</strong></span>
</p>

<p>
	Данные методы позволяют вырезать из исходного битмапа указанную область.
</p>

<p>
	Предлагается два метода:
</p>

<ol><li>
		<strong>CreateCropped </strong>- создает новый экземпляр битмапа, не изменяя исходный
	</li>
	<li>
		<strong>Crop </strong>- модифицирует исходный экземпляр битмапа.
	</li>
</ol><pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7159_9" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">
///   Создает новое изображение сформированное из указанной области. </span><span class="tag">&lt;c&gt;</span><span class="pln">ARegion</span><span class="tag">&lt;/c&gt;</span><span class="pln"> - физические координаты области.
/// </span><span class="tag">&lt;/summary&gt;</span><span class="pln">
function CreateCropped(const ARegion: TRect): TfgBitmap;

/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Выполняет вырезание указанной области изображения. </span><span class="tag">&lt;c&gt;</span><span class="pln">ARegion</span><span class="tag">&lt;/c&gt;</span><span class="pln"> - физические координаты области.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
/// </span><span class="tag">&lt;remarks&gt;</span><span class="pln">
///   </span><span class="tag">&lt;para&gt;</span><span class="pln">
///     Если координаты области </span><span class="tag">&lt;c&gt;</span><span class="pln">ARegion</span><span class="tag">&lt;/c&gt;</span><span class="pln"> выходят за пределы физического размера изоюбражения, то они отсекаются
///     по размеру изображения.
///   </span><span class="tag">&lt;/para&gt;</span><span class="pln">
///   </span><span class="tag">&lt;para&gt;</span><span class="pln">
///     Если результирующая область имеет нулевой размер, то текущий битмап принимает нулевой размер.
///   </span><span class="tag">&lt;/para&gt;</span><span class="pln">
/// </span><span class="tag">&lt;/remarks&gt;</span><span class="pln">
procedure Crop(const ARegion: TRect);</span></pre>

<p>
	<span style="font-size:22px;"><strong>Повороты - Rotate</strong></span>
</p>

<p>
	Методы поворота позволяют повернуть изображение на углы (90 - 180 - 270) градусов.
</p>

<p>
	<span style="background-color: rgb( var(--theme-area_background_reset) ); color: rgb( var(--theme-text_color) );">Предлагается два метода:</span>
</p>

<ol><li>
		<strong>CreateRotated </strong>- создает новый экземпляр битмапа, не изменяя исходный
	</li>
	<li>
		<strong>Rotate </strong>- модифицирует исходный экземпляр битмапа и выполняет поворот.
	</li>
</ol><pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7159_14" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Созадет новое изоюражение и поворачивает его на указанный угол.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
function CreateRotated(const AAngle: TfgRotation): TfgBitmap;

/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Поворачивает изображение на указанный угол.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
procedure Rotate(const AAngle: TfgRotation);</span></pre>

<p>
	<strong><span style="font-size:22px;">Отражение - Flip</span></strong>
</p>

<p>
	Два метода по симметричному отражению исходного экземпляра битмапа относительно вертикальной и горизонтальной осей.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7159_16" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Симметричное отражение изображения по горизонтальной оси.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
procedure FlipHorizontal;

/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Симметричное отражение изображения по вертикальной оси.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
procedure FlipVertical;</span></pre>

<p>
	<strong><span style="font-size:22px;">Создание превью - Thumbnail</span></strong>
</p>

<p>
	Очень часто требуется получить из исходного битмапа большого размера превью ограниченного размера. Для этого мы предлагаем метод:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7159_18" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">
///   Создает миниатюрное изображение, которое может использовать в виде превью. Изображение вписывается в
///   указанный размер с сохранение пропорций и центрируется.
/// </span><span class="tag">&lt;/summary&gt;</span><span class="pln">
/// </span><span class="tag">&lt;remarks&gt;</span><span class="pln">Если передается нулевой размер, то метод поднимает исключение.</span><span class="tag">&lt;/remarks&gt;</span><span class="pln">
function CreateThumbnail(const ASize: TSize): TfgBitmap;</span></pre>

<p>
	<span style="font-size:22px;"><strong>Перекрашивание - Tint</strong></span>
</p>

<p>
	Методы по перекрашиванию исходного экземпляра изображения в указанный цвет.
</p>

<p>
	<span style="background-color: rgb( var(--theme-area_background_reset) ); color: rgb( var(--theme-text_color) );">Предлагается два метода:</span>
</p>

<ol><li>
		<strong>CreateTinted </strong>- создает новый экземпляр битмапа, не изменяя исходный
	</li>
	<li>
		<strong>ApplyTintColor </strong>- модифицирует исходный экземпляр битмапа и выполняет поворот.
	</li>
</ol><pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7159_20" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Создает новое изображение и применяет указанный оттенок.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
function CreateTinted(const ATintColor: TAlphaColor): TfgBitmap;

/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Задает оттенок изображения. Операция не отменяемая.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
procedure ApplyTintColor(const ATintColor: TAlphaColor);</span></pre>

<p>
	<span style="font-size:22px;"><strong>Мета информация EXIF</strong></span>
</p>

<p>
	Помимо вспомогательных методов по трансформации битмапов зачастую требуется выполнить нормализацию угла поворота изображения. Когда пользователь делает снимок с камеры, то камера сохраняет файл в ориентации фото сенсора, который не обязательно совпадает с текущей ориентаций экрана. Дополнительно, камера используя мета информацию EXIF помещает в нее ориентацию съемки фотографии. Поэтому при попытке загрузить такое изображение в FGX Native битмап будет отображаться в ориентации съемки с сенсора. Для того, чтобы выполнить коррекцию угла поворота для отображения мы предлагаем новое API для извлечения EXIF информации из файла. Типовой пример использования может выглядеть так:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7159_26" style=""><span class="pln">uses  
  FGX.Exif;
  
var 
  Properties: TfgExifProperties;
  
  if TfgExif.TryLoad(AFileName, Properties) then
  begin
    // Properties.Rotation;
    // Properties.Rotation.ToRotation - возвращает TfgRotation, который можно передать в метод TfgBitmap.Rotate.
  end;</span></pre>

<p>
	На текущий момент мы извлекаем только ориентацию. Но если вам требуются получать дополнительную EXIF информацию, дайте знать, мы добавим.
</p>

<p>
	Уверены данные нововведения позволят вам сократить ваш код.
</p>

<p>
	Спасибо за внимание
</p>
]]></description><guid isPermaLink="false">63</guid><pubDate>Wed, 31 May 2023 20:53:15 +0000</pubDate></item><item><title>&#x418;&#x43D;&#x442;&#x435;&#x440;&#x430;&#x43A;&#x442;&#x438;&#x432;&#x43D;&#x44B;&#x439; &#x432;&#x44B;&#x431;&#x43E;&#x440; &#x43E;&#x431;&#x43B;&#x430;&#x441;&#x442;&#x438; &#x441; TfgRegionPicker &#x432; 1.16.0.0</title><link>https://forum.fgx-native.com/blogs/entry/62-%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D0%B0%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B9-%D0%B2%D1%8B%D0%B1%D0%BE%D1%80-%D0%BE%D0%B1%D0%BB%D0%B0%D1%81%D1%82%D0%B8-%D1%81-tfgregionpicker-%D0%B2-11600/</link><description><![CDATA[<p>
	Добрый день, уважаемые разработчики. 
</p>

<p style="text-align: justify;">
	Скоро выйдет новое крупное обновление <strong>1.16.0.0</strong>, которое содержит ряд новых компонентов, серию улучшений и исправление ошибок. Одним из новых компонентов станет интерактивный выбор прямоугольной области, который может использоваться для обрезания изображения. 
</p>

<p>
	Компонент представляет собой слой, который можно наложить поверх редактируемого объекта. Например, <strong>TfgImage</strong>.  Для удобства расположения, можно воспользоваться якорями <strong>FlexBox</strong> - свойство <strong>RelativePosition</strong>.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" href="https://forum.fgx-native.com/uploads/monthly_2023_05/image.png.a2de5a70e7e3a6712543aa594b0fc2c5.png" data-fileid="4287" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="4287" data-unique="fwec1o8yx" width="999" alt="image.png" src="https://forum.fgx-native.com/uploads/monthly_2023_05/image.thumb.png.56961518da5226b56c7f664ff7e9cf91.png" loading="lazy" height="749.25"></a>
</p>

<p>
	При помощи точек выделения можно интерактивным путем расширить регион. А получить или указать его координаты можно при помощи свойства <strong>TfgRegionPicker.Region</strong>. При интерактивном изменении области вызывается событие <strong>OnChanged</strong>. 
</p>

<p>
	При первом отображении компонента можно отцентрировать регион при помощи свойства <strong>RegionOptions.DefaultPlacement</strong>. 
</p>

<p>
	<strong><span style="font-size:20px;">Настройки внешнего вида</span></strong>
</p>

<p>
	Компонент предлагает набор настроек, позволяющие настроить отображение отдельных элементов компонента, таких как:
</p>

<ol><li>
		<strong>Точки выделения (Appearance.Grip)</strong>. Здесь можно поменять размер точек и параметры кистей заливки и контура.<br><img class="ipsImage ipsImage_thumbnailed" data-fileid="4289" data-unique="xtfrhfl5m" style="width: 320px; height: auto;" width="646" alt="image.png" src="https://forum.fgx-native.com/uploads/monthly_2023_05/image.png.e83871ffda6ea7857bb4f3868f78357b.png" loading="lazy" height="626.62"></li>
	<li>
		<strong>Регион (Appearance.Region)</strong>. Здесь можно поменять параметры отрисовки пунктирной рамки области выделения.
	</li>
	<li>
		<strong>Затемнение вне региона (ContentShading)</strong>. По умолчанию все, что вне области выделения затемняется. Это настраивается этим свойством. Можно указать базовый цвет затемнения и ее прозрачность.<br><img class="ipsImage ipsImage_thumbnailed" data-fileid="4290" data-unique="cvhgbs8bq" style="width: 307px; height: auto;" width="614" alt="image.png" src="https://forum.fgx-native.com/uploads/monthly_2023_05/image.png.a63e6bc6948a2f067267555e3d6b20ac.png" loading="lazy" height="178.06"></li>
</ol><p>
	<strong><span style="font-size:20px;">Кадрирование</span></strong>
</p>

<p>
	В релизе <strong>1.16.0.0</strong> добавлены новые метод, позволяющие легко выполнить базовые преобразования. К одному из таких методов относится кадрирование битмапа по области <strong>TfgBitmap.CreateCropped</strong> (Чтобы воспользоваться методом нужно подключить модуль <strong>FGX.Bitmap.Helpers</strong>). Ниже представлен пример кода, выполняющий кадрирование изображения на основании координат региона, полученных от <strong>TfgRegionPicker</strong>. Пример доступен в разделе "Компоненты" -&gt; "TfgRegionPicker" -&gt; "Обрезание фотографии":
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3645_16" style=""><span class="pln">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</span><span class="tag">&lt;TfgAssetBitmapSet&gt;</span><span class="pln">(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;</span></pre>

<p>
	Результат работы представлен на видео ниже:
</p>

<p>
	<video class="ipsEmbeddedVideo" controls="" data-fileid="4291" data-unique="femila82w" style="max-width:300px" data-controller="core.global.core.embeddedvideo" preload="metadata"><source type="video/mp4" src="https://forum.fgx-native.com/uploads/monthly_2023_05/TfgRegionPicker-demo.mp4.748be0371bf51bcd79ff0c0567ea0e2e.mp4"><a class="ipsAttachLink" href="https://forum.fgx-native.com/applications/core/interface/file/attachment.php?id=4291&amp;key=293b135e2e821d6e7ae2f4d014b4e0ed" data-fileid="4291" data-fileext="mp4" rel="">TfgRegionPicker-demo.mp4</a>
	</source></video></p>

<p>
	Спасибо за внимание.
</p>
]]></description><guid isPermaLink="false">62</guid><pubDate>Mon, 29 May 2023 23:04:45 +0000</pubDate></item><item><title>&#x41F;&#x43E;&#x434;&#x434;&#x435;&#x440;&#x436;&#x43A;&#x430; SVG &#x432; 1.15.5.0</title><link>https://forum.fgx-native.com/blogs/entry/61-%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D0%B0-svg-%D0%B2-11550/</link><description><![CDATA[<p>
	Добрый день, уважаемые разработчики.
</p>

<p>
	Спешим порадовать вас главным нововведением <strong>1.15.5.0</strong> - это поддержка векторных изображений <strong>SVG</strong>.
</p>

<p>
	<strong><span style="font-size:22px;">Добавление и использование</span></strong>
</p>

<p>
	В новой версии добавлен новый тип ресурсов - <strong>SVG изображение</strong>. В него вы можете загрузить SVG файл в дизайнере ресурсов для дальнейшего использования в компонентах. Добавление <strong>SVG </strong>изображения доступно в дизайнере ресурсов: <strong>Project</strong> <strong>-&gt; FGX Assets Manager</strong>.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4167" href="https://forum.fgx-native.com/uploads/monthly_2023_04/image.png.dba552b9a93399052b8bc9a5de652705.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4167" data-unique="yupup2p94" style="width: 470px; height: auto;" width="936" src="https://forum.fgx-native.com/uploads/monthly_2023_04/image.thumb.png.8f2f76bbf81575005e1dcf8537d419b7.png" loading="lazy" height="748.8"></a> <a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4168" href="https://forum.fgx-native.com/uploads/monthly_2023_04/image.png.44a742a36979f99e2d59c065844267ee.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4168" data-unique="os4qw0unr" style="width: 500px; height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2023_04/image.thumb.png.3a51d81e9417ff493fbb6079f698b98f.png" loading="lazy" height="700"></a>
</p>

<p>
	При использовании данного изображения в компонентах, происходит автоматическое формирование растрового изображения <strong>TfgBitmap</strong> с требуемым текущим коэффициентом масштабирования окна и указанным размером иконки. При этом логический размер (dp, без учета коэффициента масштабирования) иконки указывается в окне редактирования SVG файла.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4169" href="https://forum.fgx-native.com/uploads/monthly_2023_04/image.png.677f47a84501a36584a50cc3d5cf671f.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4169" data-unique="28q22h4a0" style="height: auto;" width="810" src="https://forum.fgx-native.com/uploads/monthly_2023_04/image.thumb.png.3be6e42f09613886f1b2d5b8a7855fcb.png" loading="lazy" height="745.2"></a>
</p>

<p>
	<span style="font-size:22px;"><strong>Особенности реализации</strong></span>
</p>

<p>
	Как выяснилось в ходе разработки, <strong>iOS</strong> и <strong>Android </strong>не поддерживают <strong>SVG </strong>изображения. Вместо этого, они конвертируют SVG файлы в Android Studio / XCode в свой внутренний промежуточный формат, которыйв свою очередь уже используется для формирования растровых изображений. 
</p>

<p>
	В связи с этим, нам пришлось полностью своими силами разработать парсер и рендер SVG. В итоге мы выполняем обработку SVG файла на стороне Delphi и формируем наш формат, используемый для отрисовки SVG. Далее в рантайме по файлам нашего формата, генерируем изображения.
</p>

<p>
	<strong><span style="font-size:22px;">Генерация </span></strong>
</p>

<p>
	При необходимости вы можете сформировать экземпляр растрового изображения <strong>TfgBitmap</strong> по <strong>SVG </strong>изображению любого размера. Для этого вам нужно запросить ресурс у <strong>TfgAssetsManager</strong>. При этом вы отвечаете за удаление экземпляра <strong>TfgBitmap</strong><span><span><span>:</span></span></span>
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5426_9" style=""><span class="pln">uses
  FGX.Canvas, FGX.Canvas.Types, FGX.Assets, FGX.Assets.SVG;

var
  Asset: TfgAssetSVG;
  Bitmap: TfgBitmap;
begin
  if TfgAssetsManager.Current.Find</span><span class="tag">&lt;TfgAssetSVG&gt;</span><span class="pln">('SVG asset name', Asset) then
  begin
    Bitmap := Asset.CreateBitmap(TSizeF.Create(100, 20));
    try
      // Works with bitmap.
    finally
      Bitmap.Free;
    end;
  end;
end;</span></pre>

<p>
	<strong><span style="font-size:22px;">Ограничения</span></strong>
</p>

<p>
	1. <strong>Неполноценная поддержка спецификации SVG</strong>. Мы проверили наш SVG парсер на иконках разных поставщиков от <strong>MaterialDesign</strong>, <strong>Microsoft Visual Studio Icons</strong> и до <strong>Icons 8</strong>. Однако, стандарт <strong>SVG</strong> довольно большой и написать за такое короткое время полноценный парсер задача довольно непростая. Несмотря на это, мы хотели бы, чтобы вы делились с нами SVG файлами, которые не могут прочитаться и отобразиться корректно. Это поможет нам оперативнее расширять парсер в тех направлениях, которые нужны для отображения массовых SVG изображений. 
</p>

<p>
	При загрузке изображения в дизайнере, у иконки появится специальный значок ошибки, если она не поддерживается.
</p>

<p>
	 <img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4170" data-unique="096t8jr4x" style="height: auto; width: 175px;" width="254" src="https://forum.fgx-native.com/uploads/monthly_2023_04/image.png.db45d1bd84406d4981263ea61bbfb6f3.png" loading="lazy" height="256.54"></p>

<p>
	Если файл загрузился и может быть отображен, но при чтении не удалось распознать какие-либо элементы, то он помечается значком-предупреждением:
</p>

<p>
	<img alt="warn.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4171" data-unique="vc684onmc" style="width: 345px; height: auto;" width="673" src="https://forum.fgx-native.com/uploads/monthly_2023_04/warn.png.8f93236158b83ea33904d98474104579.png" loading="lazy" height="457.64"></p>

<p>
	Это означает, что теоретически изображение может отобразиться, но оно может отображаться не корректно.
</p>

<p>
	2. <strong>Отображение превью svg иконки в дизайнере ассетов не говорит о поддержке SVG файла</strong>. Для отображения <strong>SVG </strong>изображений в <strong>IDE </strong>мы используем <strong>Skia4Delphi</strong>. Однако, практика показала, что иногда SVG иконки, которые мы отображаем успешно на устройствах, не отображаются корректно в <strong>Skia4Delphi</strong>.
</p>

<p>
	Например, отображение иконки в Runtime через FGX Native:
</p>

<p>
	<img alt="image_2023-03-29_21-43-06.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4173" data-unique="5p52lo03w" style="width: 230px; height: auto;" width="462" src="https://forum.fgx-native.com/uploads/monthly_2023_04/image_2023-03-29_21-43-06.png.8cc35fc2732bef4d187cf665fd0d6e66.png" loading="lazy" height="314.16"></p>

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

<p>
	<img alt="image_2023-03-29_16-56-53.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4172" data-unique="piobk2u8j" style="height: auto;" width="274" src="https://forum.fgx-native.com/uploads/monthly_2023_04/image_2023-03-29_16-56-53.png.7df7a763ed2f8cbbeb353f31fd00ae9a.png" loading="lazy" height="274"></p>

<p>
	Поэтому вам необходимо временно проверять корректно отображения SVG иконки именно на основании Runtime. Несмотря на то, что мы можем формировать SVG изображения и в дизайнере тоже нашим средство, мы пока используем <strong>Skia4Delphi</strong>, чтобы была возможность сравнить, как иконки должны отображаться корректно (парсер SVG должен по идее поддерживать больше функций). Спустя время, как только наш парсер будет поддерживать все ваши иконки, мы заменим в дизайнере рендер SVG иконок в дизайнере на наш.
</p>

<p>
	3. <strong>Временно недоступна возможность динамически добавлять SVG файл в рантайме</strong>. Например, вы загрузили SVG файл в рантайме и хотите его отобразить. Несмотря на то, что технически у нас уже есть такая возможность, наш парсер пока не оптимизирован, чтобы выполнять преобразование SVG формата достаточно быстро. Чтобы потенциально не побуждать пользователей к проседанию производительности, данная возможность временно недоступна. При этом мы считаем, что такой сценарий довольно редкий. И по большей части, вы будете использовать именно заранее добавленные SVG изображения.   
</p>
]]></description><guid isPermaLink="false">61</guid><pubDate>Mon, 03 Apr 2023 21:12:09 +0000</pubDate></item><item><title>&#x41F;&#x440;&#x43E;&#x432;&#x430;&#x439;&#x434;&#x435;&#x440;&#x44B; &#x442;&#x430;&#x439;&#x43B;&#x43E;&#x432; &#x432; TfgMap &#x441; 1.15.3.0. OpenStreetMap</title><link>https://forum.fgx-native.com/blogs/entry/60-%D0%BF%D1%80%D0%BE%D0%B2%D0%B0%D0%B9%D0%B4%D0%B5%D1%80%D1%8B-%D1%82%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2-%D0%B2-tfgmap-%D1%81-11530-openstreetmap/</link><description><![CDATA[<p><strong>Вступление</strong></p><p>Мы стараемся прислушиваться к потребностям наших клиентов. На этот раз мы добавили чрезвычайно важную возможность для всех пользователей карт — а именно возможность использования собственных изображений (тайлов) карт.</p><div class="ipsRichText__table-wrapper"><table style="min-width: 40px"><colgroup><col style="min-width:20px;"><col style="min-width:20px;"></colgroup><tbody><tr><td colspan="1" rowspan="1"><p><a href="https://forum.fgx-native.com/uploads/monthly_2023_02/designer.png.db896bbe7b98f5dec0b254b5ca6da495.png" class="ipsAttachLink ipsAttachLink_image ipsRichText__align--block" data-fileid="4083" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="4083" src="https://forum.fgx-native.com/uploads/monthly_2023_02/designer.thumb.png.5c931dadfccbbe36fc4de003575b244c.png" alt="designer.png" width="425" height="748" loading="lazy"></a></p></td><td colspan="1" rowspan="1"><p><video class="ipsEmbeddedVideo ipsRichText__align--block" data-controller="core.global.core.embeddedvideo" controls="" preload="metadata"><source src="https://forum.fgx-native.com/uploads/monthly_2023_02/runtime.mp4.251de916d2508f0b049d96007d3df546.mp4" type="video/mp4"><a href="https://forum.fgx-native.com/applications/core/interface/file/attachment.php?id=4084" class="ipsAttachLink" data-fileid="4084" data-fileext="mp4" rel="">runtime.mp4</a></source></video></p></td></tr></tbody></table></div><p><strong>Когда и кому это может понадобиться?</strong></p><p>На первый взгляд стандартные поставщики карт имеют полноценный, законченный функционал и не требуют вмешательства со стороны программиста. Но, как это зачастую бывает в реальной жизни, есть нюансы. Что, если вам нужно единообразие карт на обоих платформах iOS и Android (напоминаем, кто каждая ОС имеет своего поставщика карт/тайлов)? Если вам нужен оффлайн доступ к картам? Если вы разрабатываете игру и вам нужно нарисовать необычный ландшафт? Так же вам может понадобиться выбор локального поставщика карт, который имеет лучшую детализацию для конкретной местности, в которой планируется использовать приложение. И это далеко неполный список, когда собственный провайдер тайлов может быть полезен.</p><p><strong>Что такое тайлы? Модель тайлов</strong></p><p>Тайлы — это подготовленные заранее изображения части карты из которых, как в пазле, строится полная карта. Каждый тайл имеет три основных характеристики: координата по оси X, координата  по оси Y, а так же зум, к которому принадлежит данный тайл. <br>Чтобы понять, что означают эти характеристики в контексте карты, нужно разобраться с моделью тайлов. <br>Как было сказано ранее, карта строится из прямоугольных кусков и, в первую очередь, загружаются только те тайлы, которые видимы на текущем экране, а не вся карта целиком. Данный подход позволяет как оптимизировать расходы трафика (т. к. чаще всего речь идет об онлайн поставщиках карт), так и ускорить загрузку видимой части карты в целом.<br>Карта имеет координатную сетку и зум. От уровня зума зависит разрешение координатной сетки. Чем выше зум, тем больше координатная сетка и тем выше детализация карты.<br><a rel="external nofollow" href="https://yandex.ru/maps-api/docs/tiles-api/index.html#chto-takoe-tajly">По этой ссылке</a> можно наглядно увидеть зависимость разрешения карты от зума. </p><p><strong>Где взять тайлы?</strong></p><p>Когда мы разобрались с вопросом зачем, надо понять кто и на каких условиях предоставляет тайлы. <br>В первую очередь существует несколько крупных сервисов, которые специализируются на предоставлении тайлов. Как правило, поставщики имеют несколько планов — бесплатный с некоторыми ограничениями и платный доступ, когда количество запросов от вашего приложения превышает некий заранее оговоренный лимит. Краткий обзор основных поставщиков географических карт можно посмотреть <a rel="external nofollow" href="https://habr.com/ru/company/umbrellaitcom/blog/425737/">по ссылке</a>. Так же есть бесспорный лидер среди бесплатных поставщиков географических карт —  <a rel="external nofollow" href="https://ru.wikipedia.org/wiki/OpenStreetMap">OpenStreetMap</a>. <br>И, конечно же, вы сами можете сделать свою собственную реализацию поставщика тайлов, если вам не подходит ни один из готовых вариантов.</p><p><strong>Используем провайдеры тайлов в FGX Native</strong></p><p>Библиотека <strong>FGX Native</strong> предусматривает несколько вариантов добавления альтернативных провайдеров тайлов в ваш проект.</p><p><strong>Готовые провайдеры тайлов</strong><br>На момент публикации статьи в поставке библиотеки есть только один готовый компонент-провайдер  <strong>TfgOSMMapTileProvider</strong>, который, как не сложно догадаться из названия, предоставляет доступ к тайлам сервиса <strong>OpenStreetMap</strong>. Не исключено, что со временем список готовых провайдеров будет пополняться новыми сервисами.<br>Использование: бросить на форму компонент TfgOSMMapTileProvider, в инспекторе объектов связать свойство <strong>TfgMap.TileProvider</strong> и компонент <strong>TfgOSMMapTileProvider</strong>.</p><p><strong>Универсальные пользовательские провайдеры тайлов</strong><br>Универсальные провайдеры дают большую гибкость по сравнению с готовыми провайдерами за счет того, что разработчик сам отвечает за предоставление тайлов. В библиотеке такие провайдеры  представлены компонентом TfgMapTileProvider. <br>Использование: <br>1) Прежде всего необходимо задать свойство <strong>TfgEventMapTileProvider.TileSize</strong>, которое отвечает за размер отдаваемых провайдером тайлов в пикселях.<br><strong>Внимание:</strong> Смена размера тайла после задействования провайдера приведет к сбросу кэша тайлов карты и повторной загрузке карты.<br>2) Задать событие  <strong>TfgEventMapTileProvider.OnGetTile</strong>, в котором должен возвращаться графический тайл в виде интерфейса <strong>IFGXMapTile</strong>.<br><strong>Внимание:</strong> Событие  <strong>OnGetTile </strong>вызывается асинхронно из вторичных (не UI потоков). Реализация события должна быть потокобезопасной.<br><br>Размер тайла всегда должен содержать актуальное, согласованное с реальным размером тайла значение. Если вам по какой-то причине нужно перенастроить провайдер — сначала отлинкуйте его от карты, настройте и потом прилинкуйте заново.<br>Типичный пример реализации события: </p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>function TFormMain.fgMapTileProvider1GetTile(Sender: TObject; const X, Y,
  Z: Integer; const AScale: Single): IFGXMapTile;
begin
  Result := TfgMapTileSource.CreateFromUrl(Format('https://stamen-tiles.a.ssl.fastly.net/watercolor/%d/%d/%d.png', [Z, X, Y]));
end;</code></pre><p>В примере выше используется класс-хэлпер <strong>TfgDefaultMapTile </strong>, который реализует требуемый для результата события интерфейс <strong>IFGXMapTile</strong>.<br>Класс <strong>TfgDefaultMapTile </strong>содержит несколько конструкторов, каждый из которых отвечает за загрузку данных тайла тем или иным способом:</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>    constructor CreateFromBitmap(const ABitmap: TfgBitmap);
    constructor CreateFromFileName(const AFileName: string);
    constructor CreateFromStream(const AStream: TStream);
    constructor CreateFromUrl(const AUrl: string);</code></pre><p><strong>Собственная реализация провайдеров тайлов</strong></p><p>Если же ни один из двух вышеперечисленных способов вам не подходит и нужен максимальный контроль над процессом — вам поможет собственная реализация провайдера тайлов и самих тайлов.<br>Реализация провайдеров строится на базе двух интерфейсов <strong>IFGXMapTileProvider </strong>и <strong>IFGXMapTile</strong>.<br><strong>IFGXMapTile</strong><br>За представление тайла в библиотеке <strong>FGX Native</strong> отвечает интерфейс  <strong>IFGXMapTile</strong>. Он имеет два свойства: сырые данные, содержащие изображение тайла в любом поддерживаемом графическом формате (обычно png) и размер данных в байтах.</p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>  IFGXMapTile = interface
    ['{77F3C69D-6C83-4CAB-8A8C-6ED483B28275}']
    function GetData: Pointer;
    function GetSize: Integer;
    property Data: Pointer read GetData;
    property Size: Integer read GetSize;
  end;</code></pre><p><strong>IFGXMapTileProvider</strong><br>Провайдер тайлов реализуется с помощью интерфейса <strong>IFGXMapTileProvider</strong>.<br><strong>GetTileSize </strong>- возвращает общий для всех тайлов размер тайла в пикселях.<br><strong>GetTile </strong>- возвращает тайл для указанных координат. Метод должен быть потокобезопасным.<br><strong>AddObserver</strong>, <strong>RemoveObserver </strong>— подписка на уведомления/отписка от уведомлений. Реализация должна уведомлять всех заинтересованных наблюдателей об изменении размера тайла и разрушении провайдера. </p><pre spellcheck="" class="ipsCode language-plaintext" data-language="Plain Text"><code>  IFGXMapTileProvider = interface
    ['{AE2174DA-7362-4566-A307-6164E31635F1}']
    function GetTileSize: TSize;
    function GetTile(const X, Y, Z: Integer; const AScale: Single): IFGXMapTile;
    procedure AddObserver(const AObserver: IFGXMapTileProviderObserver);
    procedure RemoveObserver(const AObserver: IFGXMapTileProviderObserver);
  end;</code></pre><p>Использование: <br>1) Реализовать интерфейс <strong>IFGXMapTileProvider</strong>.<br>2) По желанию реализовать интерфейс <strong>IFGXMapTile</strong>.<br>Данный тип провайдера идеально подойдет для реализации собственного кэша тайлов, оффлайн доступа к картам и тд, те там где нужна исключительная гибкость и полный контроль над процессом.</p><p>На этом знакомство с механизмом провайдеров тайлов подходит к концу. </p><p>Спасибо за внимание.</p>]]></description><guid isPermaLink="false">60</guid><pubDate>Mon, 13 Feb 2023 02:27:00 +0000</pubDate></item><item><title>&#x423;&#x43B;&#x443;&#x447;&#x448;&#x435;&#x43D;&#x43D;&#x430;&#x44F; &#x43F;&#x43E;&#x434;&#x434;&#x435;&#x440;&#x436;&#x43A;&#x430; &#x442;&#x435;&#x43C;&#x43D;&#x43E;&#x439; &#x442;&#x435;&#x43C;&#x44B; &#x441; 1.15.3.0</title><link>https://forum.fgx-native.com/blogs/entry/59-%D1%83%D0%BB%D1%83%D1%87%D1%88%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F-%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D0%B0-%D1%82%D0%B5%D0%BC%D0%BD%D0%BE%D0%B9-%D1%82%D0%B5%D0%BC%D1%8B-%D1%81-11530/</link><description><![CDATA[<p>
	Добрый день, уважаемые разработчики.
</p>

<p>
	В этой статье мы поговорим о поддержке темной темы в <strong>FGX Native</strong> приложении, о том, как ее добавить, как сделать автоматическое переключение и о том, что добавлено в 1.15.3.0 в этой области.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4064" href="https://forum.fgx-native.com/uploads/monthly_2023_02/image.png.075467b566640574f12e7d15bbffe922.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4064" data-unique="v0nsvjtp5" style="height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2023_02/image.thumb.png.d7e7d6120264273f30801cf5f12823dd.png" loading="lazy" height="590"></a>
</p>

<p>
	<span style="font-size:22px;"><strong>Введение</strong></span>
</p>

<p>
	Тема - это набор цветов и способов отрисовки компонентов. В светлой теме метка использует черный цвет текста и светлый фон, а в темной теме - наоборот, белый текст на темном фоне. Используя это правило, несложно настроить параметры отображения компонентов так, чтобы добавить темную тему.
</p>

<p>
	 <a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4070" href="https://forum.fgx-native.com/uploads/monthly_2023_02/image.png.ef41fb854805292b17f5f1af38bcbe66.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4070" data-unique="uq8n8olrf" style="height: auto;" width="496" src="https://forum.fgx-native.com/uploads/monthly_2023_02/image.thumb.png.a33bdd5e85897f87f8afd1e164146e85.png" loading="lazy" height="748.96"></a><a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4071" href="https://forum.fgx-native.com/uploads/monthly_2023_02/image.png.d50eb0e506ca9804ef46446ae6e67803.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4071" data-unique="sk1awzuif" style="height: auto;" width="489" src="https://forum.fgx-native.com/uploads/monthly_2023_02/image.thumb.png.2645f8d529e48c1f0a89661941815a0a.png" loading="lazy" height="748.17"></a>
</p>

<p>
	Для того, чтобы добавить темную тему буквально в один клик, мы предлагаем генератор темной темы в дизайнере ресурсов (Project -&gt; FGX Assets Manager).
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4072" href="https://forum.fgx-native.com/uploads/monthly_2023_02/image.png.9749043f36a11cdb311c0d1f56e53aeb.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4072" data-unique="40qdg8nc9" style="height: auto;" width="760" src="https://forum.fgx-native.com/uploads/monthly_2023_02/image.thumb.png.e1d945a88113469506ac787fbe1d5550.png" loading="lazy" height="744.8"></a>
</p>

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

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4073" href="https://forum.fgx-native.com/uploads/monthly_2023_02/image.png.9180238f7d3d58e3be25cb9262eacf09.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4073" data-unique="n29stf2ty" style="width: 175px; height: auto;" width="350" src="https://forum.fgx-native.com/uploads/monthly_2023_02/image.thumb.png.47dca3f9d1c0a36408ad20916150ac6a.png" loading="lazy" height="749"></a>
</p>

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

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4074" href="https://forum.fgx-native.com/uploads/monthly_2023_02/image.png.afb841e2db04a895c12fa779875b76f1.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4074" data-unique="c2rz0ll23" style="height: auto;" width="656" src="https://forum.fgx-native.com/uploads/monthly_2023_02/image.thumb.png.50e5c6d26a7d37678b9ddca6976ac8cd.png" loading="lazy" height="747.84"></a>
</p>

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

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4075" href="https://forum.fgx-native.com/uploads/monthly_2023_02/image.png.12c3c729238533366bfefe895c056c84.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4075" data-unique="xwc4z34b3" style="width: 260px; height: auto;" width="529" src="https://forum.fgx-native.com/uploads/monthly_2023_02/image.thumb.png.70059e0f2df2bc2dcdf4969b6887a119.png" loading="lazy" height="745.89"></a>
</p>

<p>
	Если вы хотите переключиться на светлую тему, то либо создаете аналогично отдельно светлую тему или же просто убираете присваивание темной темы для формы. И все казалось бы выглядит отлично. Однако, есть нюансы. И их здесь два:
</p>

<ol><li>
		Не все нативные компоненты предоставляют настройки, при помощи которых можно полностью подстроить отображение компонента под темную тему.
	</li>
	<li>
		Нет возможности выполнить автоматическое переключение темы на основании системной темы.
	</li>
</ol><p>
	Если с настройками цвета текста все просто и очевидно, то с отрисовкой не все так однозначно. Операционная система самостоятельно рисует свои родные компоненты и умеет их отображать в зависимости от текущей <strong>системной</strong> темы. Сравните два скриншота окна выбора даты для темной и светлой темы.
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4065" data-unique="q51yxzmin" style="width: 320px; height: auto;" width="640" src="https://forum.fgx-native.com/uploads/monthly_2023_02/image.png.086b045222787c04eacb46eed97a2265.png" loading="lazy" height="518.4"><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4069" data-unique="6gksqzmby" style="width: 407px; height: auto;" width="625" src="https://forum.fgx-native.com/uploads/monthly_2023_02/image.png.4503c8fe74b33ab01e3405eb24873a5a.png" loading="lazy" height="393.75"></p>

<p>
	Если у кнопок и у меток вы можете поменять цвет шрифта, то с самим барабаном возникают вопросы, так как iOS не дает возможности для изменения цвета.  А значит вы не можете его корректно отобразить только при помощи цветов в <strong>FGX Native</strong>. И даже если вы примените темную тему <strong>FGX Native</strong> барабан у вас будет или с темным текстом или же он будет светлый для светлой темы, в результате чего стилизация будет некорректной.
</p>

<p>
	<strong><span style="font-size:22px;">Темная тема на уровне системы</span></strong>
</p>

<p>
	Темная тема появилась в операционных системах довольно недавно, а значит возникает вопрос, а что делать с поддержкой темной темы в старых приложениях, которые не обновляются? И тут в iOS/Android поступают немного по разному.
</p>

<p>
	<span style="font-size:20px;">iOS</span>
</p>

<p>
	Все новые приложения для iOS, которые нацелены на свежие версии iOS, где была уже добавлена тема, автоматически получают поддержку темной темы. Это значит, что система при старте приложения автоматически рисует нативный компонент согласно текущей системной темы приложения и также выбирает соответствующие системные цвета.
</p>

<p>
	Если разработчик не готов или не хочет использовать темную тему, то он явно указывает в настройках проекта <a href="https://developer.apple.com/documentation/uikit/uiuserinterfacestyle?language=objc" rel="external nofollow">UIUserInterfaceStyle</a> = light. В этом случае, iOS рисует родные компоненты в светлой теме и игнорирует темную тему.  Мы используем этот режим в FGX Native, так как у нас не было полноценной поддержки темной темы. Поэтому все приложения FGX Native содержат этот флаг:
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4076" href="https://forum.fgx-native.com/uploads/monthly_2023_02/image.png.6c85ed1b29b739604a51c8e888701c56.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4076" data-unique="6iftvgpuy" style="width: 470px; height: auto;" width="999" src="https://forum.fgx-native.com/uploads/monthly_2023_02/image.thumb.png.414f3a953ea68fec63aa392bcc5f5360.png" loading="lazy" height="789.21"></a>
</p>

<p>
	<span style="font-size:20px;">Android</span>
</p>

<p>
	Поддержка темной темы в <strong>Android </strong>более сложная. Она чем-то похожа на iOS, за исключением того, что некоторые производители <strong>Android </strong>устройств добавляют "свою" поддержку темной темы для старых версий. Например MIUI. В этом случае, производитель автоматом принудительно пытается применить темную тему и вычислить цвета на основании текущих (сделать их автоматический реверс). В результате кто-то из вас мог столкнуться с некорректным отображением приложения. Чтобы избежать этого мы принудительно отключаем все подобные попытки при помощи специального атрибута в стиле андроид приложения  
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8519_27" style=""><span class="com">&lt;!-- MIUI automatically recolors UI in dark mode, it uses emulation mode. --&gt;</span><span class="pln">
</span><span class="tag">&lt;item</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"android:forceDarkAllowed"</span><span class="tag">&gt;</span><span class="pln">false</span><span class="tag">&lt;/item&gt;</span></pre>

<p>
	Выбор же темной темы в <strong>Android </strong>приложения строится на основании используемой темы приложения в файле <strong>styles.xml</strong>. По причинам отсутствия полноценной поддержки темной темы, мы так же используем строго светлую тему для <strong>Android </strong>приложения
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8519_29" style=""><span class="pln">    </span><span class="com">&lt;!-- Basic theme for all Android versions --&gt;</span><span class="pln">
    </span><span class="tag">&lt;style</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"BaseAppTheme"</span><span class="pln"> </span><span class="atn">parent</span><span class="pun">=</span><span class="atv">"Theme.AppCompat.Light"</span><span class="tag">&gt;</span></pre>

<p>
	<strong><span style="font-size:22px;">Как добавить темную тему в FGX Native?</span></strong>
</p>

<p>
	Добавление темной темы состоит из нескольких шагов:
</p>

<p>
	1. Разрешаем <strong>FGX Native</strong> приложению автоматически использовать темную системную тему (<span style="color:#e74c3c;"><strong>Важно! FGX Native приложения не включают темную тему по умолчанию, поэтому требуется делать этот шаг</strong></span>).
</p>

<ul><li>
		<strong>iOS</strong>: Удаляем ключ <a href="https://developer.apple.com/documentation/uikit/uiuserinterfacestyle?language=objc" rel="external nofollow">UIUserInterfaceStyle</a> из настроек проекта: Project -&gt; Options -&gt; Version Info (для iOS конфигураций)
	</li>
	<li>
		<strong>Android</strong>: Меняем базовую тему в файле <strong>styles.xml</strong> (расположен в корне вашего приложения) cо значения "<strong>Theme.AppCompat.Light</strong>" на "<strong>Theme.MaterialComponents.DayNight</strong>"   
		<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8519_31" style=""><span class="pln">    </span><span class="tag">&lt;style</span><span class="pln"> </span><span class="atn">name</span><span class="pun">=</span><span class="atv">"BaseAppTheme"</span><span class="pln"> </span><span class="atn">parent</span><span class="pun">=</span><span class="atv">"Theme.MaterialComponents.DayNight"</span><span class="tag">&gt;</span></pre>
	</li>
</ul><p>
	Эти правки позволят приложению автоматически менять отрисовки нативных компонентов при смене системной темы.
</p>

<p>
	2. Добавляем светлую/темную темы в FGX Native через дизайнер ресурсов при помощи генератора тем:
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="4079" href="https://forum.fgx-native.com/uploads/monthly_2023_02/image.png.c3a77a66db487af1de3353f3aedfca28.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4079" data-unique="gzlhwol14" style="height: auto;" width="276" src="https://forum.fgx-native.com/uploads/monthly_2023_02/image.thumb.png.f2a5205fbe519a0c083239bd0b7c16a8.png" loading="lazy" height="747.96"></a>
</p>

<p>
	3. Отлавливаем изменение системной темы и применяем к форме тему из ресурсов. Для этого используем новое событие <strong>TfgForm.OnSystemAppearanceChanged</strong>, которое содержит параметры текущей системной темы и которое вызывается каждый раз при смене системной темы. 
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8519_35" style=""><span class="pln">procedure TFormMain.fgFormSystemThemeChanged(Sender: TObject; const AAppearance: TfgSystemAppearance);
begin
  case AAppearance.ThemeKind of
    TfgSystemThemeKind.Dark:
      ThemeName := 'Theme Dark';
    TfgSystemThemeKind.Light:
      ThemeName := 'Theme Light';
  end;
end;</span></pre>

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

<p>
	Если по каким-то соображениям, вы хотите узнать параметры системной темы, вы можете это сделать при помощи нового свойства <strong>FGX.SystemInfo.TfgSystemInfo.Appearance</strong>.
</p>

<p>
	Результат работы представлен ниже:
</p>

<p>
	<video class="ipsEmbeddedVideo" controls="" data-fileid="4080" data-unique="th53k35bw" id="ips_uid_455_6" src="https://forum.fgx-native.com/uploads/monthly_2023_02/video_2023-02-08_00-03-12.mp4.df2922cb930ece4fe8db4b960b7b1b56.mp4" style="max-width: 320px" data-controller="core.global.core.embeddedvideo" preload="metadata"><source type="video/mp4" src="https://forum.fgx-native.com/uploads/monthly_2023_02/video_2023-02-08_00-03-12.mp4.df2922cb930ece4fe8db4b960b7b1b56.mp4"><a class="ipsAttachLink" data-fileext="mp4" data-fileid="4080" href="https://forum.fgx-native.com/applications/core/interface/file/attachment.php?id=4080&amp;key=4e4739ed2d42fd3911af18d1bc6474fc" rel="">video_2023-02-08_00-03-12.mp4</a>
	</source></video><video class="ipsEmbeddedVideo" controls="" data-fileid="4081" data-unique="jntgxn3zw" id="ips_uid_455_7" src="https://forum.fgx-native.com/uploads/monthly_2023_02/video_2023-02-09_22-47-34.mp4.117f9f9b6f9a6d966958857e0582d5bd.mp4" style="max-width: 320px" data-controller="core.global.core.embeddedvideo" preload="metadata"><source type="video/mp4" src="https://forum.fgx-native.com/uploads/monthly_2023_02/video_2023-02-09_22-47-34.mp4.117f9f9b6f9a6d966958857e0582d5bd.mp4"><a class="ipsAttachLink" data-fileext="mp4" data-fileid="4081" href="https://forum.fgx-native.com/applications/core/interface/file/attachment.php?id=4081&amp;key=f971ac88d7160862ff9618512a5d508a" rel="">video_2023-02-09_22-47-34.mp4</a>
	</source></video></p>

<p>
	<strong><span style="font-size:22px;">Планы на будущее</span></strong>
</p>

<p>
	В будущем мы будем стараться упростить этот процесс, чтобы темная тема на стороне FGX Native создавалась автоматически, если разработчик не использует темы в своем приложении, и она автоматически переключалась при смене системной темы.
</p>
]]></description><guid isPermaLink="false">59</guid><pubDate>Thu, 09 Feb 2023 19:50:00 +0000</pubDate></item><item><title>Firebase Google Analytics &#x441; 1.15.3.0</title><link>https://forum.fgx-native.com/blogs/entry/57-firebase-google-analytics-%D1%81-11530/</link><description><![CDATA[<p>
	Добрый вечер,
</p>

<p>
	Начиная с <strong>FGX Native</strong> <strong>1.15.3.0,</strong> появится новый компонент для сборка аналитики использования вашего приложения <strong>TfgFirebaseAnalytics</strong>.
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="4041" data-unique="mgy4hb06z" style="height: auto;" width="293" src="https://forum.fgx-native.com/uploads/monthly_2023_01/image.png.8afc19c49e424c95b6caee5431693ba2.png" loading="lazy" height="93.76"></p>

<p>
	Данный компонент позволяет собрать информацию об использовании вашего приложения пользователями. <span style="background-color: rgb( var(--theme-area_background_reset) ); color: rgb( var(--theme-text_color) );">Например, вы можете определить:</span>
</p>

<ol><li>
		Какую форму пользователи открывают чаще всего.
	</li>
	<li>
		Какие версии вашего приложения успешно запускаются.
	</li>
	<li>
		Сколько пользователей первый раз запустили приложение.
	</li>
	<li>
		Какие покупки чаще всего делают в вашем приложении.
	</li>
	<li>
		С какими компонентами чаще всего взаимодействуют. 
	</li>
	<li>
		И многое другое.
	</li>
</ol><p>
	Подробности о <strong>Firebase Analytics</strong>: <a href="https://firebase.google.com/docs/analytics?authuser=0" ipsnoembed="true" rel="external nofollow">https://firebase.google.com/docs/analytics?authuser=0</a>
</p>

<p>
	<strong><span style="font-size:22px;">Настройка использования</span></strong>
</p>

<p>
	Чтобы использовать новый компонент, необходимо выполнить общую регистрацию <strong>FGX Native</strong> приложения в <strong>Firebase </strong>консоли (Шаги такие же, как регистрация приложения для использования Push-уведомлений): 
</p>

<ul><li>
		<a href="https://forum.fgx-native.com/blogs/entry/55-firebase-push-%D1%83%D0%B2%D0%B5%D0%B4%D0%BE%D0%BC%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F-%D0%BD%D0%B0-ios-%D1%81-11520/" rel="">Настройка Firebase для iOS</a>.
	</li>
	<li>
		<a href="https://fgx-native.com/ru/push-notifications.html" rel="external nofollow">Настройка Firebase для Android</a>.
	</li>
</ul><p>
	Дополнительно для Android нужно вручную добавить зависимость на библиотеку "<strong>com.google.firebase:firebase-analytics:21.2.0</strong>"
</p>

<p>
	<a href="https://forum.fgx-native.com/blogs/entry/56-%D0%B8%D0%BD%D1%82%D0%B5%D0%B3%D1%80%D0%B0%D1%86%D0%B8%D1%8F-android-%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA-%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE-%D0%B8-%D0%B1%D1%8B%D1%81%D1%82%D1%80%D0%BE-%D1%81-11520/" ipsnoembed="false" rel="">https://forum.fgx-native.com/blogs/entry/56-интеграция-android-библиотек-просто-и-быстро-с-11520/</a>
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" href="https://forum.fgx-native.com/uploads/monthly_2023_01/image.png.6b4d49c7e834c47e95d0611ca593562c.png" data-fileid="4043" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="4043" data-unique="g8v6ar4cr" style="width: 500px; height: auto;" width="999" alt="image.png" src="https://forum.fgx-native.com/uploads/monthly_2023_01/image.thumb.png.84f4ac03a22f979ac3246cef240808f1.png" loading="lazy" height="749.25"></a>
</p>

<p>
	Если вы не выполните корректную настройку приложения, то на iOS запуск приложения закончится ошибкой старта, а в Android ни одна метрика не будет отправлена в облако Firebase. 
</p>

<p>
	<strong><span style="font-size:22px;">Отправка событий</span></strong>
</p>

<p>
	Чтобы начать отправку событий необходимо разместить новый компонент <strong>TfgFirebaseAnalytics</strong>. Рекомендуем разместить его на общем дата модуле, чтобы вы могли пользоваться одним экземпляром компонента в любом месте. Однако, вы можете использовать и несколько экземпляров данного компонента.
</p>

<p>
	Как только вы размещаете его в приложении, так сразу компонент начинает автоматический сбор базовых событий в вашем iOS/Android приложении, такие как:
</p>

<ul><li>
		Определение первого запуска приложения
	</li>
	<li>
		Статистику использования разных версий вашего приложения.
	</li>
	<li>
		Сбор сессий использования. 
	</li>
	<li>
		И тд.
	</li>
</ul><p>
	Такие события доступны в консоли <strong>Firebase </strong>в разделе <strong>Analytics</strong> -&gt; <strong>Realtime</strong>.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" href="https://forum.fgx-native.com/uploads/monthly_2023_01/image.png.2f39833dc47d72df586b59e9a87f437b.png" data-fileid="4042" data-fileext="png" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="4042" data-unique="zhq624ym7" width="1000" alt="image.png" src="https://forum.fgx-native.com/uploads/monthly_2023_01/image.thumb.png.1355e77756b4bf209b39af673a05ea47.png" loading="lazy" height="470"></a>
</p>

<p>
	Помимо автоматического сбора событий, вы можете выполнять отправку своих событий.
</p>

<p>
	Каждое событие, происходящее в вашем приложении, характеризуется:
</p>

<ul><li>
		<strong>Name </strong>- имя. Строковый код события. <strong>Firebase </strong>предлагает готовые коды событий. С ними можно познакомиться <a href="https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event" rel="external nofollow">на этой странице</a>. Вы можете использовать, как готовые коды, так и свои собственные.<br>
		Например: событие <strong>select_content</strong> предназначено для информирования о том, что пользователь выбрал важный для вас контент (нажал на кнопку, открыл форму и тд).
	</li>
	<li>
		<strong>Parameters </strong>- параметры в формате - название параметра - значение. Каждое событие может сопровождаться соответствующими параметрами. <strong>Firebase</strong> описывает связанные с событиями параметрами, которые вы можете отправить.<br>
		Например, событие <strong>select_content </strong>сопровождается двумя параметрами: <strong>content_type </strong>и <strong>item_id </strong>(<a href="https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event#SELECT_CONTENT" rel="external nofollow">документация</a>)
	</li>
</ul><p>
	Для отправки события в компоненте есть два метода, позволяющие это сделать:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6147_11" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">
///   Отправляет на сервер Firebase событие с именем </span><span class="tag">&lt;c&gt;</span><span class="pln">AName</span><span class="tag">&lt;/c&gt;</span><span class="pln">, параметрами c именами </span><span class="tag">&lt;c&gt;</span><span class="pln">AKeys</span><span class="tag">&lt;/c&gt;</span><span class="pln"> и значениями
///   </span><span class="tag">&lt;c&gt;</span><span class="pln">AValues</span><span class="tag">&lt;/c&gt;</span><span class="pln">.
/// </span><span class="tag">&lt;/summary&gt;</span><span class="pln">
procedure LogEvent(const AName: string; const AKeys: TArray</span><span class="tag">&lt;string&gt;</span><span class="pln">; const AValues: array of const); overload;

/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Отправляет на сервер Firebase событие с именем </span><span class="tag">&lt;c&gt;</span><span class="pln">AName</span><span class="tag">&lt;/c&gt;</span><span class="pln">.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
procedure LogEvent(const AName: string); overload;</span></pre>

<ul></ul><p>
	Чтобы узнать, что пользователь нажал на кнопку покупки в вашем приложении, необходимо добавить в обработчик вызов метода <strong>LogEvent</strong>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6147_20" style=""><span class="pln">procedure TFormMain.fgButtonBuyTap(Sender: TObject);
begin
  fbAnalytics.LogEvent('select_content', ['content_type', 'item_id'], ['Button', 'Buy subscription']);
end;</span></pre>

<p>
	<strong><span style="font-size:22px;">Определение открытых экранов/форм</span></strong>
</p>

<p>
	Помимо отправки любых событий, компонент <strong>TfgFirebaseAnalytics</strong> позволяет отправлять информацию о том, какие формы/экраны открывает пользователь. Чтобы воспользоваться данной возможностью, необходимо в момент отображения формы передавать на сервер Firebase информацию о текущей форме.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6147_22" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">
///   Задает текущее название экрана, которое определяет текущий визуальный контекст в вашем приложении.
///   Это помогает определить области в вашем приложении, где пользователи проводят свое время и как они
///   взаимодействуют с вашим приложением.
/// </span><span class="tag">&lt;/summary&gt;</span><span class="pln">
procedure SetCurrentScreen(const AScreenName: string; const AScreenClassName: string);</span></pre>

<p>
	Для удобства отслеживания, когда форма появляется на переднем плане, в FGX Native 1.15.3.0 для формы <strong>TfgForm</strong> добавлены два новых события:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6147_24" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Вызывается, когда форма выходит на передний план на экране.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
/// </span><span class="tag">&lt;remarks&gt;</span><span class="pln">Не вызывается для встроенных форм-фреймов.</span><span class="tag">&lt;/remarks&gt;</span><span class="pln">
property OnActivate: TNotifyEvent read FOnActivate write FOnActivate;

/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Вызывается, когда форма уходит с переднего плана на экране.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
/// </span><span class="tag">&lt;remarks&gt;</span><span class="pln">Не вызывается для встроенных форм-фреймов.</span><span class="tag">&lt;/remarks&gt;</span><span class="pln">
property OnDeactivate: TNotifyEvent read FOnDeactivate write FOnDeactivate;</span></pre>

<p>
	Именно их мы рекомендуем использовать для указания текущего экрана в Firebase Analytics.
</p>

<p>
	Например, код по отображению главной формы может выглядеть так:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6147_26" style=""><span class="pln">procedure TFormMain.fgFormActivate(Sender: TObject);
begin
  Shared.fbAnalytics.SetCurrentScreen('Main form', ClassName);
end;</span></pre>

<p>
	Первым параметром указывание название экрана, вторым - класс. 
</p>

<p>
	<strong><span style="font-size:22px;">Общие настройки</span></strong>
</p>

<p>
	Помимо главной задачи отправления статистики в <strong>Firebase Analyitcs</strong>, вы можете выполнять базовые настройки компонента:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6147_30" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">
///   Удаляет все аналитические данные для этого приложения с устройства и сбрасывает идентификатор экземпляра приложения.
/// </span><span class="tag">&lt;/summary&gt;</span><span class="pln">
procedure ResetAnalyticsData;

/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">
///   Включен ли сбор аналитики для этого приложения на данном устройстве. Этот параметр сохраняется во всех сеансах
///   приложения. По умолчанию он включен.
/// </span><span class="tag">&lt;/summary&gt;</span><span class="pln">
property Enabled: Boolean read FEnabled write SetEnabled default DefaultEnabled;

/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Уникальный идентификатор текущего пользователя.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
property UserId: string read FUserId write SetUserId;

/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Задает продолжительность бездействия, которая завершает текущий сеанс.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
property SessionTimeoutDuration: Integer read FSessionTimeoutDuration write SetSessionTimeoutDuration default DefaultSessionTimeoutDuration;</span></pre>

<p>
	С остальными подробности использования вы можете ознакомиться в официальной документации Firebase:  <a href="https://firebase.google.com/docs/analytics?authuser=0" ipsnoembed="true" rel="external nofollow">https://firebase.google.com/docs/analytics?authuser=0</a>
</p>

<p>
	Спасибо
</p>
]]></description><guid isPermaLink="false">57</guid><pubDate>Fri, 20 Jan 2023 18:23:00 +0000</pubDate></item><item><title>&#x41D;&#x43E;&#x432;&#x430;&#x44F; &#x441;&#x438;&#x441;&#x442;&#x435;&#x43C;&#x430; &#x441;&#x431;&#x43E;&#x440;&#x43A;&#x438; Android &#x43F;&#x440;&#x438;&#x43B;&#x43E;&#x436;&#x435;&#x43D;&#x438;&#x439; &#x441;&#x43E; &#x437;&#x43D;&#x430;&#x447;&#x438;&#x442;&#x435;&#x43B;&#x44C;&#x43D;&#x44B;&#x43C; &#x43F;&#x440;&#x438;&#x440;&#x43E;&#x441;&#x442;&#x43E;&#x43C; &#x441;&#x43A;&#x43E;&#x440;&#x43E;&#x441;&#x442;&#x438; &#x200B;&#x1F525;&#x200B;</title><link>https://forum.fgx-native.com/blogs/entry/52-%D0%BD%D0%BE%D0%B2%D0%B0%D1%8F-%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0-%D1%81%D0%B1%D0%BE%D1%80%D0%BA%D0%B8-android-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9-%D1%81%D0%BE-%D0%B7%D0%BD%D0%B0%D1%87%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%BC-%D0%BF%D1%80%D0%B8%D1%80%D0%BE%D1%81%D1%82%D0%BE%D0%BC-%D1%81%D0%BA%D0%BE%D1%80%D0%BE%D1%81%D1%82%D0%B8-%E2%80%8B%F0%9F%94%A5%E2%80%8B/</link><description><![CDATA[<p>
	Добрый день, уважаемые пользователи <strong>FGX Native!</strong>
</p>

<p>
	Вот мы и подошли к главной ключевой новинке версии <strong>FGX Native 1.15.0.0</strong>, а именно речь пойдет о новой системе сборки для <strong>Android </strong>приложений <span class="ipsEmoji">🔥</span>. Долгое время мы шли к этому решению и уверены, что данная система сборки является ключевым нововведением для всех будущих релизов <strong>FGX Native</strong>. Это огромный шаг и потенциал для мобильной разработки на <strong>Delphi</strong>.
</p>

<p>
	Перед тем, как окунуться в детали новинки, настоятельно рекомендуем ознакомиться с нашей статьей о миграции на <strong>AndroidX</strong>, в которой мы частично описали текущие проблемы, которые стоят за штатной системой сборки <strong>Delphi</strong>.
</p>
<iframe allowfullscreen="" class="ipsEmbed_finishedLoading" data-embedauthorid="1" data-embedcontent="" data-embedid="embed6578070355" id="ips_uid_3831_6" scrolling="no" src="https://forum.fgx-native.com/blogs/entry/50-fgx-native-%D0%BF%D0%B5%D1%80%D0%B5%D1%85%D0%BE%D0%B4%D0%B8%D1%82-%D0%BD%D0%B0-androidx-%D1%81-11500/?do=embed" style="overflow: hidden; height: 417px; max-width: 502px;" loading="lazy"></iframe>

<p>
	<strong><span style="font-size:22px;">Что не так со стандартной системой сборки Delphi для Android приложений?</span></strong>
</p>

<p>
	Для начала нужно понять, почему в чём проблемы стандартной системы сборки.
</p>

<p>
	<span style="font-size:20px;">1. Поддержка сторонних Android-библиотек</span>
</p>

<p>
	Это самая важная часть для <strong>FGX Native</strong>. Мы используем различные сторонние <strong>Android</strong> библиотеки - <strong>Firebase</strong>, <strong>AdMob</strong>, <strong>Visio </strong>и прочие. Все эти библиотеки в свою очередь используют другие библиотеки, и тд т тп. Каждая библиотека - это не только код, но и ресурсы, изменения необходимые для <strong>Android</strong> манифеста и тд. Соотвественно, для полноценной поддержки сторонних <strong>Android</strong>-библиотек требуется не только внедрить исполняемый код, но и так же поставить все ресурсы и слить правки в <strong>Android</strong> манифесте.
</p>

<p>
	Стандартная система сборки <strong>Delphi </strong>ограничена только внедрением кода. А это значит, что выдрав из Андроид-библиотеки только код и проигнорировав ресурсы, манифесты и нативный код, мы получаем нестабильное решение, которое может не работать, падать и тд. Поэтому в <strong>Delphi </strong>сообществе очень много проблем с использованием сторонних <strong>Android</strong> решений. И все они зачастую упираются в ограничение стандартной системы сборки.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5271_11" style=""><span class="pln">Более подробно проблема поддержки Android-библиотек описана в статье про миграцию на AndroidX.</span></pre>

<p>
	<span style="font-size:20px;">2. Скорость</span>
</p>

<p>
	Не секрет, что скорость сборки <strong>Android</strong> приложений из <strong>Delphi</strong>, по сравнению с нативными средствами разработки, оставляет желать лучшего.  И если во время сборки простого приложения проблема не так заметна, то ситуация кардинально менятся, когда мы имеем дело с приложениями готовыми для продакшена и содержащими большое количество кода, ресурсов и тд.
</p>

<p>
	Повторный запуск приложения (после сборки без изменений) может занимать минуты(!) (в зависимости от используемых ресурсов). А после внесения любых, даже самых незначительных изменений в проект, требуется потратить почти столько же времени, как на сборку проекта с нуля.
</p>

<p>
	Мы собрали немного статистики от наших клиентов по сборке существующих продакшен-приложений с большим количеством экранов и ресурсов. Данные показатели зависят от многих факторов: сложность проекта, характеристики  компьютера, на котором осуществляется сборка и тд. Но для нас важно относительные значения времени в рамках одного проекта и одного компьютера. Поэтому следует иметь ввиду, что в каждом конкретном случае числа будут другими.
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3783" data-unique="qu2mtwo8a" style="width: 440px; height: auto;" width="876" src="https://forum.fgx-native.com/uploads/monthly_2022_10/image.png.b0683c25c517b44cf85d58cc695f5ece.png" loading="lazy" height="236.52"></p>

<ol><li>
		<strong>Первый столбец</strong> содержит время старта (без отладки) проекта с нуля. До этого проект не собирался и нет никаких промежуточных результатов сборки.
	</li>
	<li>
		<strong>Второй столбец</strong> указывает время старта (без отладки) проекта после внесения изменения в проект: изменили исходный код и тд.
	</li>
	<li>
		<strong>Третий столбец</strong> отвечает за повторный старт (без отладки) приложения без внесения изменений .    
	</li>
</ol><p>
	Из этой таблицы хорошо видно, что в среднем на сборку с запуском уходит <strong>~1 минута.</strong> Обычный сценарий использования: внес изменений в коде, собрал, запустил, поймал ошибку, опять внес изменений и тд. Грубо говоря, в среднем <strong>60 запусков</strong> в день приложения (без отладки) может занимать <strong>1 час</strong> рабочего времени! С отладкой цифры становятся еще более угрожающими. Тратится драгоценное время на ожидание, вместо того, чтобы потратить его с пользой.
</p>

<p>
	<span style="font-size:20px;">3. Технологическое отставание от требований Google</span>
</p>

<p>
	Стоит отметить, что <strong>Google </strong>активно развивает сборку <strong>Android</strong> приложений, каждый раз выдвигая всё новые и новые требования к полученному приложению:
</p>

<ul><li>
		Был <strong>APK</strong>, на его смену пришел более умный <strong>AAB</strong>.
	</li>
	<li>
		Новые требования к версии используемых библиотек. Если используемая библиотека старая, то приложение не может быть загружено в маркет или же просто не работать на свежих версиях <strong>Android</strong>.
	</li>
</ul><p>
	Поскольку <strong>Delphi</strong> самостоятельно реализует систему сборки, то получается состояние вечной гонки, в которой <strong>Delphi</strong>, к сожалению, всегда в роли догоняющего. Поэтому, как только <strong>Google</strong>/<strong>Apple </strong>меняют структуру пакета приложения, вам приходится ждать обновлений <strong>Delphi</strong>, которые изменят встроенную систему сборки в соответствии с новыми требованиями. С учётом частоты выхода новых версий <strong>Delphi </strong>это может вылиться в длительное ожидание, а иногда и финансовые затраты, необходимые для приобретения новой версии.
</p>

<p>
	<strong><span style="font-size:22px;">Что нам дает новая система сборки</span></strong>
</p>

<p>
	Учитывая все перечисленные выше минусы встроенной сборки <strong>Android</strong> приложений, мы пошли по единственному верному на наш взгляд пути, а именно, мы внедрили родную систему сборки, которая используется в <strong>Android Studio</strong> и которую рекомендует сам<strong> Google</strong>.
</p>

<p>
	<span style="font-size:20px;">1. Поддержка Android-библиотек</span>
</p>

<p>
	Полноценная поддержка всех <strong>Android</strong>-библиотек. Теперь перед <strong>Delphi </strong>разработчиком не будет практических никаких ограничений для использования сторонних библиотек. Мы предлагаем полный цикл интеграции любого стороннего решения в <strong>FGX Native</strong> приложения под <strong>Android</strong>:
</p>

<ol><li>
		Вы находите интересуемое решение на <strong>Java </strong>для <strong>Android</strong>
	</li>
	<li>
		Вы добавляете <strong>Java </strong>библиотеку в <strong>FGX Native</strong> проект
	</li>
	<li>
		Вы генерируете заголовочные файлы для <strong>Java </strong>библиотеки на языке <strong>Delphi</strong> при помощи нашей утилиты <strong>Java2Delphi</strong>.
	</li>
</ol><p>
	В будущем появится автоматическое скачивания всех зависимостей. Так что вам даже не придется искать файл библиотеки, достаточно будет указать имя библиотеки и её версию. Остальное на себя возьмет <strong>FGX Native</strong>.
</p>

<p>
	<span style="font-size:20px;">2. Скорость</span>
</p>

<p>
	После внедрения новой системы сборки, мы попросили наших клиентов, повторно протестировать сборку их проектов. Все результаты сведены в таблицу ниже. Из нее наглядно видно, что в целом сборка и запуск  проектов стал быстрее от <strong>2</strong> до <strong>5</strong> раз <span class="ipsEmoji">🔥</span>(кроме старта с нуля, что обуславливается долгой сборкой главной <strong>so</strong>-библиотеки приложения, которая целиком и полностью зависит от компилятора и линкера).
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3784" data-unique="ve8o5bei2" style="width: 600px; height: auto;" width="982" src="https://forum.fgx-native.com/uploads/monthly_2022_10/image.png.210596c3b4657183b4d97c4f5974d3b1.png" loading="lazy" height="235.68"></p>

<p>
	Давайте разберем результаты подробнее.
</p>

<p>
	<strong><span style="font-size:16px;">Старт после изменений</span></strong>
</p>

<p style="text-align: justify;">
	Данный замер является самым часто используемым. Вы вносите изменения в проект и запускаете приложение для тестирования и отладки. Практически - это основной сценарий работы разработчика. В целом прирост скорости составляет от <strong>2 </strong>до <strong>5 </strong>раз на тестируемой выборке проектов <span class="ipsEmoji">🚀</span>. Важно отметить, что при этом новая система сборки проделывает гораздо большую работу по сравнению со стандартной, даже если брать в расчёт только внедрение дополнительных ресурсов от используемых библиотеки. Количество ресурсов может исчисляться сотнями, и, если добавлять их все через <strong>Deployment Manager</strong>, то разница в результатах будет еще больше (не в пользу стандартной системы сборки). 
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3786" data-unique="jzrxtbt2h" style="width: 600px; height: auto;" width="858" src="https://forum.fgx-native.com/uploads/monthly_2022_10/image.png.a531f994ed76f5b3d95bf6826458a394.png" loading="lazy" height="446.16"></p>

<p>
	<span style="font-size:16px;"><strong>Повторный старт</strong></span>
</p>

<p style="text-align: justify;">
	Данный вариант используется реже, когда вы пытаетесь воспроизвести какую-то ситуацию без изменений кода и у вас не получается ее поймать с первого раза. В этом случае вы просто запускаете приложение из <strong>IDE </strong>повторно. 
</p>

<p style="text-align: justify;">
	В этом случае показатели скорости просто ошеломительные. Прирост составляет в ~<span style="font-size:20px;">5 раз </span>на текущей выборке и практически он является постоянной. Если в стандартной системе сборке повторный запуск зависит от количества ресурсов и размера приложения, то для <strong>FGX Native</strong> это постоянная величина.
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3787" data-unique="6kc2z38ma" style="width: 600px; height: auto;" width="853" src="https://forum.fgx-native.com/uploads/monthly_2022_10/image.png.a635e657a055aabc36bd5eaf92117350.png" loading="lazy" height="452.09"></p>

<p>
	<strong><span style="font-size:16px;">Старт с нуля</span></strong>
</p>

<p style="text-align: justify;">
	Данный тест "Старт с нуля" актуален только для первичной сборки, когда вы скачали проект и выполняете первую сборку. Это самый редкий сценарий запуска, т.к., как правило, при последующих запусках используется "кэш", полученный на предыдущих итерациях. В дальнейшем используется вариант внесения изменений и повторного старта. Сюда не относится вариант с полной пересборкой проекта.
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3785" data-unique="jqhbeoasp" style="width: 600px; height: auto;" width="863" src="https://forum.fgx-native.com/uploads/monthly_2022_10/image.png.3ed1b4573c5013db737ecc150e072309.png" loading="lazy" height="448.76"></p>

<p>
	<span style="font-size:20px;">3. Технологическое отставание от требований Google</span>
</p>

<p>
	Мы не "изобретаем велосипед" в сборке <strong>Android </strong>приложений, а берем проверенное официальное решение от <strong>Google</strong>, которое поддерживается <strong>Google</strong>. А это значит:
</p>

<ol><li>
		Соответствование всем новым требованиям со стороны <strong>Google</strong>
	</li>
	<li>
		Легкое/моментальное обновление системы сборки до последней версии, без необходимости обновления <strong>Delphi</strong>
	</li>
</ol><p>
	<strong><span style="font-size:22px;">Использование</span></strong>
</p>

<p style="text-align: justify;">
	<span style="font-size:20px;">Первая сборка</span>
</p>

<p style="text-align: justify;">
	При первом открытии <strong>FGX Native</strong> проекта, начиная с <strong>1.15.0.0 </strong>автоматически будет выполнена миграция настроек проекта, в рамках которой будет предложено обновить шаблон манифеста <strong>Android </strong>приложения и файл стилей <strong>styles.xml</strong>. Если вы не вносили никаких правок, просто подтвердите замену. Если же вы вносили правки, то необходимо перенести их  вручную в правую часть редактора.
</p>

<p style="text-align: justify;">
	При обновлении в корень проекта автоматически сохраняется старый файл шаблона. Данное поведение можно отключить при помощи чекбокса, расположенного в левом нижнем углу.
</p>

<p style="text-align: justify;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="3794" href="https://forum.fgx-native.com/uploads/monthly_2022_10/image.png.62a8c694d6e5964a036e236598e9387c.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3794" data-unique="qz390xf5x" style="width: 800px; height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2022_10/image.thumb.png.2e7a3ffecc8d8a68283a5970915ab551.png" loading="lazy" height="590"></a>
</p>

<p style="text-align: justify;">
	При первой сборке <strong>FGX Native</strong> проекта начиная с <strong>1.15.0.0</strong> в корне проекта автоматически будет создана директория "<strong>.android-build</strong>". Этот каталог содержит всё необходимое для сборки вашего проекта. Его не нужно добавлять в систему контроля версии, он может быть большого размера, так как там сохраняются промежуточные результаты сборки, при необходимости его можно удалять. Все файлы внутри данной директории являются автогенерируемыми, поэтому не пытайтесь вносить ручные правки, они будут проигнорированы. 
</p>

<p style="text-align: justify;">
	<span style="color:#e74c3c;"><strong>Первая сборка может занять длительное время, так как при ней загружаются с интернета (требуется наличие активного интернет соединения!) все необходимые компоненты сборки. Однако последующие сборки будут проходить намного быстрее. Во время первой сборки среда может визуально "подвисать", это связано с тем, что интеграция с msbuild в IDE не умеет выполняться полностью параллельно.</strong></span>
</p>

<p style="text-align: justify;">
	<span style="font-size:20px;">Ошибки сборки</span>
</p>

<p style="text-align: justify;">
	Если в результате сборки появляется ошибка, то подробную информацию можно найти на нижней вкладке "<strong>Output</strong>", а не в "<strong>Build</strong>", как раньше.
</p>

<p style="text-align: justify;">
	<strong>Например</strong>, все ошибки упаковки на панели "<strong>Build</strong>" будут сводиться к такой.
</p>

<p style="text-align: justify;">
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3788" data-unique="d2qav3te6" style="width: 500px; height: auto;" width="984" src="https://forum.fgx-native.com/uploads/monthly_2022_10/image.png.eef317c575e4f5a15650e41c5ae549bd.png" loading="lazy" height="354.24"></p>

<p style="text-align: justify;">
	Подробности можно найти на вкладке "<strong>Output</strong>". По тексту ошибки становится ясно, что в проекте используется <strong>TargetApiVersion </strong>ниже 33.
</p>

<p style="text-align: justify;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="3792" href="https://forum.fgx-native.com/uploads/monthly_2022_10/image.png.9293f864c2afad2874b0f87588423f4e.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3792" data-unique="d490v3jhi" style="width: 500px; height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2022_10/image.thumb.png.5e38e65669004d14e4ba168177588cee.png" loading="lazy" height="390"></a>
</p>

<p style="text-align: justify;">
	<strong><span style="font-size:22px;">Требования</span></strong>
</p>

<ol><li>
		Для успешной сборки требуется свежая версия <strong>Java JDK</strong> (не ниже 18). Можно использовать ту, что идет в поставке с <strong>Delphi</strong>.
	</li>
	<li>
		Требуется наличие интернета для первой сборки приложения, так как при ней скачиваются необходимые компоненты сборки.
	</li>
	<li>
		Теперь все <strong>FGX Native</strong> под <strong>Android </strong>используют <strong>TargetAPILevel = 33</strong>. Мы полностью перешли на использование последней версии <strong>Android</strong>. Поэтому понижать версию теперь нельзя.
	</li>
</ol><p>
	<span style="font-size:22px;"><strong>Когда планируется релиз?</strong></span>
</p>

<p>
	Поскольку релиз <strong>1.15.0.0</strong> является очень крупным и затрагивает критические важные моменты, мы хотим быть уверены, что он не испортит ваши проекты. Поэтому внедрение будет происходить постепенно. На первом этапе мы отдали некоторым нашим клиентам сборку на предварительное тестирования на больших проектах, получили обратную связь и устраняем найденные недочеты.  Далее на этой неделе мы планируем выпустить экспериментальную версию <strong>1.15.0.0 </strong>для широкого круга пользователей. По сути - это полноценная версия и вы сможете опробовать её для перехода на <strong>Android 13</strong>, сравнить скорость сборки и тд. Однако, если вы столкнетесь с какими-то серьезными проблемами для вашего проекта, вы всегда сможете откатиться на стабильную версию <strong>1.14.6.0</strong>. На текущий момент, практически все большие собранные проекты на <strong>1.15.0.0</strong> успешно запускаются и работают.
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3796" data-unique="sz19lswv9" style="height: auto;" width="602" src="https://forum.fgx-native.com/uploads/monthly_2022_10/image.png.6aba6258a329bdc284181a0353dab702.png" loading="lazy" height="72.24"> 
</p>

<p>
	Если при тестировании вы столкнетесь с проблемами, просьба сообщить нам о них, и мы постараемся их оперативно поправить.
</p>

<p>
	Всем спасибо за внимание и хорошей продуктивной недели!
</p>
]]></description><guid isPermaLink="false">52</guid><pubDate>Tue, 01 Nov 2022 08:07:44 +0000</pubDate></item><item><title>&#x410;&#x43D;&#x43E;&#x43D;&#x441; 1.15.0.0, &#x443;&#x441;&#x43A;&#x43E;&#x440;&#x435;&#x43D;&#x438;&#x435; &#x437;&#x430;&#x43F;&#x443;&#x441;&#x43A;&#x430; Android &#x43F;&#x440;&#x438;&#x43B;&#x43E;&#x436;&#x435;&#x43D;&#x438;&#x44F; &#x438; &#x443;&#x43B;&#x443;&#x447;&#x448;&#x435;&#x43D;&#x438;&#x44F; &#x432; Java2Delphi</title><link>https://forum.fgx-native.com/blogs/entry/51-%D0%B0%D0%BD%D0%BE%D0%BD%D1%81-11500-%D1%83%D1%81%D0%BA%D0%BE%D1%80%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B7%D0%B0%D0%BF%D1%83%D1%81%D0%BA%D0%B0-android-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D1%83%D0%BB%D1%83%D1%87%D1%88%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B2-java2delphi/</link><description><![CDATA[<p>
	Продолжаем освещать новинки обновления <strong>1.15.0.0</strong>. И в этот раз речь пойдет про оптимизации старта приложения и новые возможности нашей утилиты <strong>Java2Delphi</strong>.
</p>

<p>
	<strong><span style="font-size:22px;">Ускорение запуска FGX Native приложения на Android</span></strong>
</p>

<p>
	Одним из важных изменений в области работы <strong>Java</strong>-<strong>Delphi</strong> мосту - является ускорение запуска <strong>FGX Native</strong> приложения на <strong>Android</strong>. До <strong>1.15.0.0</strong> холодный старт пустого приложения мог занимать пару секунд. В <strong>1.15.0.0</strong> мы реализовали отложенную инициализацию <strong>Java</strong> оберток, в результате чего это позволило нам ускорить старт пустого приложения до <strong>~2-х раз</strong>.
</p>

<p>
	<strong><span style="font-size:22px;">Улучшения в Java2Delphi</span></strong>
</p>

<p>
	<span style="font-size:20px;">Поддержка AAR</span>
</p>

<p>
	В новой версии <strong>Java2Delphi</strong> теперь можно использовать <strong>AAR </strong>библиотеки. Для этого их нужно указать в конфигурационном файле в ветке "<strong>aars</strong>".
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7103_37" style=""><span class="pln">    "aars": [
        "$(FGX)\\Libs\\Android\\fgx.admob.aar"
    ],</span></pre>

<p>
	<span style="font-size:20px;">Deprecated/Introduced для полей</span>
</p>

<p style="text-align: justify;">
	<strong>Android API</strong> меняется от версии к версии. Какие-то типы объявляются устаревшими, какие-то удаленными, а какие-то новыми. Глядя на заголовочный файл тяжело понять, какой метод в какой версии <strong>Android</strong> доступен. Ранее мы вносили специальные пометки в заголовочные файлы для методов. В этом релизе мы  генерируем аналогичные пометки их и для полей. Так что, теперь можно открыв заголовочный файл, сразу понять в какой версии был добавлен тот или иной элемент, а когда он помечен, как устаревший.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7103_39" style=""><span class="pln">    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';
    </span></pre>

<p>
	<span style="font-size:20px;">Умная генерация параметров при зависимостях</span>
</p>

<p style="text-align: justify;">
	Одним из главных отличий <strong>Java</strong> от <strong>Delphi </strong>является разная реализация пространств имен и доступов к типам. В <strong>Delphi </strong>по умолчанию два модуля не могут использовать друг друга в интерфейсной части. Появляется так называется циклическая зависимость. В то же время в <strong>Java</strong> в рамках одного пакета все классы могут использовать друг друга. Получается, что заголовочные обертки для всех классов одного пакета в Java должны были быть объявлены в одном <strong>Delphi </strong>модуле. Это в свою очередь приводило к значительному росту заголовочного файла. Так как нельзя размещать взаимно используемые классы в разных модулях.
</p>

<p style="text-align: justify;">
	В этом релизе мы так же улучшили это. Теперь вы можете раскидывать классы по разным модулям, даже если они взаимно используют друг друга. Чтобы избежать циклической зависимости, класс в одном из модулей заменяется на общий <strong>JObject</strong>. 
</p>

<p>
	<strong>Например:</strong>
</p>

<p>
	Мы выделяем все типы, связанные с анимацией в модуль <strong>Android.Api.Animations</strong>. Эти типы используют JView, который объявлен в  "<strong>Android.Api.ActivityAndView</strong>". Часть типов анимации используются в классе <strong>Android.Api.ActivityAndView.JView</strong>. Так геттер <strong>getAnimation</strong> должен вернуть объект <strong>JAnimation</strong>. Однако, данный тип, объявлен в <strong>Android.Api.Animations</strong>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7103_43" style=""><span class="pln">JView = interface(JObject)
  // 
  function getAnimation: JAnimation;
  //
end;</span></pre>

<p>
	Получается циклическая зависимость. И раньше такой код не мог быть скомпилирован. Сейчас же такая зависимость заменяется генератором на такой код с указанием оригинального класса в фигурных скобках:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7103_46" style=""><span class="pln">JView = interface(JObject)
  // 
  function getAnimation: JObject {JAnimation};
  //
end;</span></pre>

<p>
	Чтобы при использовании получить объект <strong>JAnimation</strong>, достаточно написать такой код:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7103_49" style=""><span class="pln">var
  Animation: JAnimation;

Animation := TJAnimation.Wrap(View.getAnimation);</span></pre>
]]></description><guid isPermaLink="false">51</guid><pubDate>Sun, 30 Oct 2022 18:07:00 +0000</pubDate></item><item><title>FGX Native &#x43F;&#x435;&#x440;&#x435;&#x445;&#x43E;&#x434;&#x438;&#x442; &#x43D;&#x430; AndroidX &#x441; 1.15.0.0</title><link>https://forum.fgx-native.com/blogs/entry/50-fgx-native-%D0%BF%D0%B5%D1%80%D0%B5%D1%85%D0%BE%D0%B4%D0%B8%D1%82-%D0%BD%D0%B0-androidx-%D1%81-11500/</link><description><![CDATA[<p>
	Добрый день пользователи <strong>FGX Native</strong>.
</p>

<p>
	Сегодня мы хотим рассказать про переход <strong>Android</strong> части библиотеки <strong>FGX Native</strong> на <strong>AndroidX</strong>. О том, что это, зачем это нужно и как это влияет на разработчиков мы поговорим в этой статье.
</p>

<p>
	<strong><span style="font-size:22px;">Что такое AndroidX?</span></strong>
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3773" data-unique="n6kuc28yn" style="height: auto;" width="503" src="https://forum.fgx-native.com/uploads/monthly_2022_10/image.png.0d2bc3629b3448ffe09c809a29e8c138.png" loading="lazy" height="281.68"></p>

<p style="text-align: justify;">
	Среди всех проблем <strong>Android</strong> - наверное, главной для разработчика является проблема адаптации мобильного приложения под все версии <strong>Android</strong>. Очень часто, в старых версиях <strong>Android</strong> просто невозможно реализовать тот или иной функционал, потому что операционная система не предоставляет для этого API. С выпуском новых версий, постепенно <strong>Google</strong> добавляет пропущенное <strong>API</strong>. Однако, при использовании такового, вы не можете запустить такое приложение на старых версиях <strong>Android</strong>, потому что оно просто упадет из-за отсутствия нужного <strong>API</strong>. Поэтому разработчикам нужно иногда писать по две реализации одного и того же функционала на разном <strong>API</strong>.
</p>

<p style="text-align: justify;">
	Для того, чтобы это решить, <strong>Google </strong>стала выпускать набор библиотек, которые содержат универсальное <strong>API</strong>, работающее на всех версиях <strong>Android</strong>. Такая библиотека раньше называлась <strong><a href="https://developer.android.com/topic/libraries/support-library" rel="external nofollow">Android Google Support Library</a></strong>, а затем Google объявила ее устаревшей и заменил ее на новую <strong>AndroidX</strong>.
</p>

<p style="text-align: justify;">
	<strong><a href="https://developer.android.com/jetpack/androidx" rel="external nofollow">AndroidX</a></strong> - Это набор библиотек от <strong>Google</strong>, в которых они расширяют стандартные скудные возможности <strong>Android</strong> и дают широкий набор нового функционала, доступный среди всех версий <strong>Android</strong>. Она включает в себя большое число разных библиотеки, начиная от реализации базовых компонентов <strong>Android OS</strong>, продолжая облегченной работой с камерой и заканчивая продвинутыми компонентами <a href="https://m2.material.io/components" rel="external nofollow">Material Design</a>. 
</p>

<p>
	До версии <strong>FGX Native 1.15.0.0</strong> используется "<strong>Android Google Support Library</strong>".
</p>

<p>
	<span style="font-size:22px;"><strong>Зачем переходить на AndroidX?</strong></span>
</p>

<p style="text-align: justify;">
	Главная необходимость заключается в том, что многие другие современные сторонние библиотеки <strong>Android</strong> уже используют <strong>AndroidX</strong>. Например, <strong>Firebase</strong>, <strong>AdMob</strong>, <strong>Google Maps </strong>и тд. А это значит, что если мы хотим добавить новый функционал в <strong>TfgMap</strong> из свежих версий <strong>GoogleMap</strong> или добавить возможность отправки push-уведомления с картинкой из <strong>Firebase</strong>, то мы не сможем это сделать, пока не перейдем на <strong>AndroidX</strong>.
</p>

<p style="text-align: justify;">
	Помимо внутренних потребностей для развития <strong>FGX Native</strong> на <strong>Android</strong> платформе нужно не забывать, что разработчик с <strong>FGX Native</strong> может использовать сторонние <strong>jar </strong>библиотеки, сгенерировать для них заголовочные файлы при помощи <strong>Java2Delphi</strong> утилиты (входит в поставку <strong>FGX Native</strong>) и использовать в вашем приложении вами любимый язык <strong>Delphi</strong>. Будь-то "<a href="https://forum.fgx-native.com/topic/398-appmetrica-sdk-%D0%BA%D0%B0%D0%BA-%D0%BF%D0%BE%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B8%D1%82%D1%8C-%D0%B2-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5/#comment-1550" rel="">Яндекс.AppMetrica</a>" или <strong>WebRTC</strong> компоненты или UI компоненты, рисующие графики, <strong>FGX Native</strong> позволяет это сделать. Однако, опять же многие новые свежие версии сторонних Android библиотек уже используют AndroidX. А это значит, что их нельзя использовать, пока нет поддержки <strong>AndroidX</strong>.
</p>

<p>
	<strong><span style="font-size:22px;">Почему переход на AndroidX не был выполнен ранее?</span></strong>
</p>

<p>
	Как уже было сказано ранее <strong>FGX Native</strong> до <strong>1.15.0.0 </strong>использует "<strong>Android Google Support Library</strong>". И эта библиотека считается официально устаревшей с Июля 2017. Так почему же, мы до сих пор используем устаревшую версию?
</p>

<p>
	Перед тем, как ответить на этот вопрос, познакомимся, что технически означает "добавление <strong>Android </strong>библиотеки в приложение". Упрощенно, <strong>FGX Native Android</strong> приложение состоит из четырех частей:
</p>

<ol><li>
		"<strong>SO-Библиотека</strong>" с нативным кодом вашего приложения. Это именно то, что получается в результате компиляции ваших форм, модулей и тд.
	</li>
	<li>
		"<strong>classes.dex</strong>" - Это байт код, который является стартовым для любого <strong>Android </strong>приложения. Именно эта часть загружает делфи библиотеку и передает ей управление.
	</li>
	<li>
		"<strong>Набор ресурсов</strong>" - иконки приложения, заставки, графические ресурсы, ассеты, шрифты, ресурсы локализации и тд, все то, что доступно для вашего приложения.
	</li>
	<li>
		"<strong>Манифест приложения</strong>" - это по сути описание содержимого вашего приложения, что оно может делать, а что нет. Именно он является определяющим файлом на предмет выдачи прав доступа, запуска других приложений и тд.
	</li>
</ol><p>
	Все это упаковывается и на выходе вы получаете пакет приложения <strong>APK</strong> или более сложный формат <strong>AAB</strong>.
</p>

<p style="text-align: justify;">
	<strong>Android</strong> библиотека по сути имеет практически такое же содержание, как и <strong>Android </strong>приложение. Оно так же может иметь в своем составе нативные библиотеки, наборы ресурсов, манифест или же байт-код в jar-библиотеке.
</p>

<p style="text-align: justify;">
	Поэтому чтобы добавить <strong>Android</strong>-библиотеку в приложение, необходимо все, что есть в библиотеке добавить в приложение. И выполнить хитрые манипуляции по совмещению данных из разных библиотеки (сливание манифестов, компиляция ресурсов, слияние байт кода в один <strong>classes.dex</strong>.
</p>

<p style="text-align: justify;">
	<span style="font-size:20px;">Ресурсы, манифесты</span>
</p>

<p style="text-align: justify;">
	Так вот причина задержки в переходе на <strong>AndroidX </strong>кроется в механизме поддержки <strong>Android </strong>библиотек на уровне <strong>RAD Studio/Delphi</strong>. Добавление сторонних <strong>jar</strong> библиотек всегда было частью системы сборки <strong>Delphi</strong>, в которой мы увы не можем менять со стороны. Поддержка <strong>Android</strong> библиотек в <strong>Delphi</strong> ограничивается только добавлением байт кода в итоговый <strong>classes.dex</strong>. А это значит, что <strong>Delphi</strong> не умела и до сих пор не умеет сливать манифесты, добавлять  и компилировать ресурсы, внедрять <strong>so</strong>-библиотеки автоматически и тд. Поэтому круг использования сторонних <strong>Android </strong>библиотек в <strong>Delphi</strong> довольно узкий - это библиотеки, которые не используют ресурсы и по части не работают с UI. Как вы понимаете, таких библиотек в мире Android довольно мало. Потому что даже обычная не <strong>UI</strong> библиотека выделяет строковые ресурсы в "набор ресурсов" для возможности локализации разработчиком.
</p>

<p style="text-align: justify;">
	Поэтому, чтобы выполнить миграцию на <strong>AndroidX </strong>нужно вначале реализовать полноценную поддержку <strong>Android</strong>-библиотек в <strong>Delphi</strong>. Поскольку это часть системы сборки <strong>Delphi</strong>, у нас нет возможностей для внесения изменений в не наш код. Осложняется еще и тем, что <strong>Delphi Deployment Manager</strong> заточен только на FMX и не любит никаких отклонений от "нормы" <strong>FireMonkey </strong>приложения. Поэтому <strong>IDE </strong>всячески пытается удалить, изменить, обновить элементы "<strong>Deployment Manager"</strong> и сводит практически на нет любые кастомизации.
</p>

<p style="text-align: justify;">
	<strong>AndroidX</strong> является набором огромного количества маленьких библиотек, каждая из которых содержит свой набор ресурсов (изображения, стили, локализации, файлы настроек и тд). И именно по этому на нее не возможно перейти даже обходными путями.
</p>

<p>
	К сожалению, за прошедшие 5 лет выпуска <strong>Delphi</strong> больших изменений в области деплоя и сборки для <strong>Android </strong>не было. Главным изменением можно считать добавление поддержки <strong>MultiDex</strong> в <strong>Delphi 11</strong>.
</p>

<p>
	<span style="font-size:20px;">MultiDex и Delphi 11</span>
</p>

<p style="text-align: justify;">
	Если на пальцах объяснить, что такое <strong>MultiDex</strong>, то когда байт код из разных <strong>Android </strong>библиотек сливается в <strong>classes.dex</strong>, то может возникнуть ситуация, что все не влезает в один файл (ограничение накладывается на общее количество типов, методов и т.п., которое может поместиться в одном файле. Это связано с архитектурой выполнения байт кода в <strong>Android</strong>). Когда все не помещается в один файл, то остальное помещается в следующий файл <strong>classes2.dex</strong> и так далее, пока все не будет раскинуто по файлам. В этом случае <strong>apk</strong> содержит ни один <strong>classes.dex</strong>, а не сколько. И именно поддержка этого добавлена в <strong>Delphi 11</strong>. 
</p>

<p style="text-align: justify;">
	По умолчанию, и <strong>FireMonkey </strong>и <strong>FGX Native</strong> приложение помещается в один <strong>classes.dex</strong>. Другими словами, прямой необходимости в поддержки <strong>MultiDex </strong>не требуется. Однако, чем больше сторонних <strong>Android </strong>библиотек вы используете, тем быстрее растет <strong>classes.dex</strong> и тем проще выйти за пределы <strong>SingleDex</strong> и перейти в <strong>MultiDex</strong>. 
</p>

<p style="text-align: justify;">
	<strong>AndroidX </strong>вводит большое число зависимых библиотек, поэтому добавление <strong>AndroidX </strong>также автоматически добавляет необходимость использовать <strong>MultiDex</strong>. И если в <strong>Delphi 11</strong>, такая поддержка есть. То пользователям старых версий <strong>Delphi</strong> делать в этом случае уже нечего. Поскольку мы считаем, что разработчики не должны быть сильно привязаны к версии IDE при использовании нашего продукта, мы не могли и не можем отказаться от поддержки старых <strong>Delphi </strong>до 11 версии.
</p>

<p style="text-align: justify;">
	<strong><span style="font-size:22px;">Delphi 11 и FireMonkey поддерживает же AndroidX, в чем секрет?</span></strong>
</p>

<p style="text-align: justify;">
	"<u><em>Delphi 11 официально же использует AndroidX</em></u>" - значит ли это, что проблем никаких нет? На самом деле, поддержка заканчивается только на уровне интеграции байт-кода в приложение. О чем я упомянул в предыдущем разделе. Это значит, что Delphi просто внедряет исполняемый байт код в приложение и так же не поставляет никакие ресурсы в <strong>FMX </strong>приложение. Как это отражается на приложении. Как только выполнение вашего приложения попробует обратиться к несуществующим ресурсам, то в этот момент оно может либо упасть, либо работать некорректно. Так же <strong>FMX </strong>содержит не весь <strong>AndroidX</strong>, а только минимально-необходимый набор библиотек. По большей части <strong>FMX </strong>минимально использует <strong>Android API</strong>, поэтому вы можете не наблюдать проблем с отсутствующими ресурсами. Однако, как только вы сделаете шаг в сторону и захотите расширить возможности добавлением <strong>Android</strong>-библиотеки, то вы поймете, что все использование ограничено и приложение не будет работать.
</p>

<p>
	<strong><span style="font-size:22px;">Почему теперь переход на AndroidX стал возможен?</span></strong>
</p>

<p style="text-align: justify;">
	Возможно, <strong>Embarcadero </strong>в будущем добавит полноценную поддержку <strong>Android</strong>-библиотек. Но пока ее нет, нам ничего не остается, как заменить систему сборки <strong>Android </strong>приложений на другую и добавить полноценную поддержку использования Android-библиотек. Последнее время мы плотно занимались этой работой. В результате чего мы полностью перешли с системы сборки <strong>Android </strong>приложения в <strong>Delphi </strong>на другую с полноценной поддержкой Android-библиотек. Данную поддержку вы увидите в обновлении <strong>1.15.0.0</strong>. Подробности перехода на новую систему сборки будут рассказаны в следующей статье. Однако, новая сборка помимо полноценной поддержки <strong>Android</strong>-библиотек так же значительно ускоряет запуск приложения на устройстве (даже при условии деплоя ресурсов) и дает эти возможности на любой версии <strong>Delphi</strong>. Это значит, что клиенты любых поддерживаемых версий <strong>Delphi</strong>, не зависимо от IDE получат все возможности по сборке приложений, включая <strong>MultiDex</strong> и добавление <strong>Android</strong>-библиотеки.  
</p>

<p>
	<strong><span style="font-size:22px;">Что дает нам AndroidX?</span></strong>
</p>

<p>
	<span style="font-size:20px;">Android 13 и новее</span>
</p>

<p>
	Переход на последнюю версию <strong>AndroidX</strong> дает нам полноценную поддержки последних версий <strong>Android</strong>. Начиная с версии <strong>FGX Native 1.15.0.0</strong> все приложения будут нацелены на <strong>Android 13</strong> (Api Level = 33). Все заголовочные файлы так же будут обновлены до <strong>Android 13</strong>. Старые заголовочные с классами "<strong>Support Library"</strong> будут удалены.
</p>

<p>
	<span style="font-size:20px;">Material Components</span>
</p>

<p>
	Помимо этого, теперь мы можем полноценно использовать компоненты из <strong>Material Design</strong>. И в будущем теперь нас ничто не сдерживает от добавления продвинутых различных реализаций вкладок, chips и т.д.
</p>

<p>
	<span style="font-size:20px;">Firebase</span>
</p>

<p>
	Поддержка последней версии <strong>Firebase</strong>, работающая на всех поддерживаемых версиях Андроида без проблем. Возможность передавать изображение в push-сообщениях.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="3774" href="https://forum.fgx-native.com/uploads/monthly_2022_10/image.png.96944367baf56e65d0170291dbe65a36.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3774" data-unique="qazqlz9hw" style="height: auto;" width="337" src="https://forum.fgx-native.com/uploads/monthly_2022_10/image.thumb.png.aa56bd9a713e990f47dfdf891d4ddcc9.png" loading="lazy" height="748.14"></a>
</p>

<p>
	<span style="font-size:20px;">Сканер штрихкодов</span>
</p>

<p>
	Обновленная реализация сканера штрихкодов, которая работает быстрее, стабильнее и лучше.
</p>

<p>
	<span style="font-size:20px;">Карты GoogleMap</span>
</p>

<p>
	Поддержка свежих версий карт.
</p>

<p>
	<span style="font-size:20px;">Реклама AdMob</span>
</p>

<p>
	Использование последних версий площадки по размещению рекламы.
</p>

<p>
	<span style="font-size:20px;">Прочее</span>
</p>

<p>
	Обновление Yandex.AppMetrica, Google SignIn, Billing, InAppPurchase и тд.
</p>

<p>
	<strong><span style="font-size:22px;">Что делать, если я не все понял в этой статье?</span></strong>
</p>

<p>
	Не расстраиваться! <strong>FGX Native</strong> команда делает все, чтобы вам не нужно было знать обо всем этом и вы могли сконцентрироваться на решении своих задач. Однако, нам приятно поделиться с вами действительно важными изменениями в <strong>FGX Native</strong>, которые позволят нашему продукту стать еще шире и добавить еще больше новых возможностей. У нас большой опыт в этой области, который позволяет нам реализовывать практически любые идеи. 
</p>

<p>
	Всем спасибо за внимание!
</p>
]]></description><guid isPermaLink="false">50</guid><pubDate>Sat, 29 Oct 2022 18:18:00 +0000</pubDate></item><item><title>&#x410;&#x43D;&#x43E;&#x43D;&#x441; 1.14.5.0 &#x438; &#x443;&#x43B;&#x443;&#x447;&#x448;&#x435;&#x43D;&#x438;&#x435; Android Log Viewer, iOS Simulator ARM 64-bit</title><link>https://forum.fgx-native.com/blogs/entry/49-%D0%B0%D0%BD%D0%BE%D0%BD%D1%81-11450-%D0%B8-%D1%83%D0%BB%D1%83%D1%87%D1%88%D0%B5%D0%BD%D0%B8%D0%B5-android-log-viewer-ios-simulator-arm-64-bit/</link><description><![CDATA[<p>
	Добрый день!
</p>

<p>
	Новый релиз <strong>1.14.5.0</strong> посвящен полноценной поддержке <strong>RAD Studio 11.2</strong> и новой платформе <strong>iOS Simulator ARM 64-bit</strong>. Помимо этого, мы немного улучшили средства просмотра Андроид логов и компонент <strong>TfgButton</strong>.
</p>

<p>
	<span style="font-size:22px;"><strong>iOS Simulator ARM 64-bit</strong></span>
</p>

<p>
	В этой версии добавлена поддержка <strong>iOS Simulator ARM 64-bit</strong>. Теперь вы можете запускать ваши <strong>FGX Native</strong> приложения на симуляторе. Однако, помните, что данный симулятор работает только на процессорах <strong>Apple</strong>. Так же компоненты авторизации через <strong>Facebook Login</strong> не поддерживаются в данный момент на симуляторе.
</p>

<p>
	<strong><span style="font-size:22px;">Улучшения Android Log Viewer</span></strong>
</p>

<p>
	В этой версии, мы почерпнули несколько интересных идей у <strong>Android Studio </strong>и реализовали продвинутую раскраску сообщений. Теперь сообщения одного одного процесса визуально выделяются одним и тем же цветом. Это улучшает визуальное разделение сообщений разных процессов.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="3654" href="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.a57c0abce723fe107692f41d0bde2da8.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3654" data-unique="0uf2lud8e" style="width: 500px; height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.thumb.png.895bb74f2f587356cb469508422de92c.png" loading="lazy" height="580"></a><a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="3656" href="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.0cbd52c883e2349dd7e9310c5e40fe2f.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3656" data-unique="4i34n5ltq" style="width: 500px; height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.thumb.png.bf7f32aeda1005568194953fab071eab.png" loading="lazy" height="580"></a>
</p>

<p>
	<strong><span style="font-size:22px;">Внутренние отступы TfgButton</span></strong>
</p>

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

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="3658" href="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.b77587b4e5977903f79c163402c92e77.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3658" data-unique="tvliblaim" style="width: 500px; height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.thumb.png.7d5fbdb30220fd3ec73e279bb7e08aa1.png" loading="lazy" height="610"></a>
</p>

<p>
	<strong><span style="font-size:22px;">RAD Studio 11.2 </span></strong>
</p>

<p>
	Новая версия <strong>RAD Studio 11.2</strong> сломала обратную совместимость некоторых пакетов дизайнера с <strong>11.0</strong> и <strong>11.1</strong>. В результате чего версия <strong>1.14.4.0 </strong>не работает на <strong>11.2</strong>, а <strong>1.14.4.1</strong> не работает на <strong>11.1</strong>. В этом релизе мы поставляем две версии дизайнера: отдельно для <strong>11.0-11.1 </strong>и <strong>11.2</strong>. При установке необходимо выбрать интересующую вас версию.
</p>

<p>
	Спасибо за внимание, <br>
	Ваша команда FGX Native
</p>
]]></description><guid isPermaLink="false">49</guid><pubDate>Mon, 26 Sep 2022 22:30:00 +0000</pubDate></item><item><title>&#x410;&#x43D;&#x43E;&#x43D;&#x441; 1.14.4.0</title><link>https://forum.fgx-native.com/blogs/entry/47-%D0%B0%D0%BD%D0%BE%D0%BD%D1%81-11440/</link><description><![CDATA[<p>
	Вот и прошло лето, а в месте с тем пришло время для крупного релиза, с которым мы вас с удовольствием познакомим.
</p>

<p>
	<span style="font-size:22px;"><strong>FlexBox дизайнер</strong></span>
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3560" data-unique="614ts1s4m" style="height: auto;" width="367" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.9220969edc6f7aba493897ada567906d.png" loading="lazy" height="440.4"></p>

<p style="text-align: justify;">
	Система разметки <strong>FlexBox</strong> - универсальный инструмент, предлагающий довольно большой ряд редактируемых параметров, разобраться с которыми при первом приближении довольно сложно. В этом релизе мы разработали визуальный редактор параметров для контейнеров <strong>FlexBox</strong>, наглядно отображающий разные режимы выравнивания. Редактор доступен у свойства <strong>TfgLayout.AlignmentChildren, </strong>достаточно нажать на кнопку "..." у значения свойства <strong>AlignmentChildren </strong>любого компонента-контейнера. Он не просто показывает работу опций, но так же и адаптирует их при смене ориентации и тд.
</p>

<p>
	<video class="ipsEmbeddedVideo" controls="" data-fileid="3559" data-unique="t3m5p838m" id="ips_uid_9986_8" src="https://forum.fgx-native.com/uploads/monthly_2022_09/FlexBoxDesigner.mp4.fa3fd3bd9129367f28613c726623cc0b.mp4.03fb59a5e1a8ba95e99bbd69c2d890de.mp4" data-controller="core.global.core.embeddedvideo" preload="metadata"><source type="video/mp4" src="https://forum.fgx-native.com/uploads/monthly_2022_09/FlexBoxDesigner.mp4.fa3fd3bd9129367f28613c726623cc0b.mp4.03fb59a5e1a8ba95e99bbd69c2d890de.mp4"><a class="ipsAttachLink" data-fileext="mp4" data-fileid="3559" href="https://forum.fgx-native.com/applications/core/interface/file/attachment.php?id=3559&amp;key=02fcf4e776ef96ef715a1110c031947f" rel="">FlexBoxDesigner.mp4.fa3fd3bd9129367f28613c726623cc0b.mp4</a>
	</source></video></p>

<p>
	<strong><span style="font-size:22px;">Переработанный дизайнер ресурсов</span></strong>
</p>

<p>
	В этом релизе мы полностью переработали дизайнер ресурсов, как внутри, так и снаружи. Добавили новые возможности и улучшили старые. Но обо всем по порядку.
</p>

<p>
	<span style="font-size:20px;">Автоматическое удаление "лишних" ресурсов</span>
</p>

<p>
	В старой версии дизайнера при добавлении ресурса цвета создавалось 5 одинаковых ресурсов цвета для каждого типа устройств (<strong>Universal</strong>, <strong>Phone</strong>, <strong>NormalTablet</strong>, <strong>LargeTablet</strong>, <strong>ExtraLargeTablet</strong>). Однако, как показала практика,  пользователи используют на всех устройствах один и тот же цвет. Поэтому генерация одинаковых цветов нецелесообразна и с точки зрения дублирования, и с точки зрения скорости загрузки приложения и поиска ресурсов. В связи с этим, теперь дизайнер автоматически определяет дубликаты и удаляет их.
</p>

<p>
	Было:
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3562" data-unique="i51c625dw" style="height: auto;" width="662" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.c63947b0fc03edb87d576c9c7338d3d6.png" loading="lazy" height="165.5"></p>

<p>
	Стало:
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3564" data-unique="bemuupbti" style="height: auto;" width="583" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.ace06769a13b4bcc82d88c29119e3770.png" loading="lazy" height="174.9"></p>

<p>
	<span style="font-size:20px;">Генерация изображений</span>
</p>

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

<p>
	Теперь можно сгенерировать изображение-заглушку по вашим параметрам и использовать его при проектировании приложения.
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3566" data-unique="70wkaky4b" style="height: auto;" width="741" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.634d8acc25194514e3acabeff3706b78.png" loading="lazy" height="422.37"></p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3568" data-unique="mi3dfge2e" style="height: auto;" width="809" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.27e214e938c6e877ae11bce12c875129.png" loading="lazy" height="307.42"></p>

<p>
	<span style="font-size:20px;">Яркость изображения</span>
</p>

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

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3570" data-unique="gbhe3l1bb" style="height: auto;" width="780" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.0a6f5475c0be73c67ccd0e26ce2b41f8.png" loading="lazy" height="140.4"></p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3572" data-unique="xneysr7rf" style="height: auto;" width="784" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.b5896e2c9a682bcc99df437bffbca6b4.png" loading="lazy" height="133.28"></p>

<p>
	<span style="font-size:20px;">Импорт изображений</span>
</p>

<p>
	Теперь можно перетащить папку с изображениями на дерево ресурсов и импортировать все вложенные изображения.
</p>

<p>
	<span style="font-size:20px;">Стандартизация редактирования ресурсов.</span>
</p>

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

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3574" data-unique="6us8v7ks3" style="height: auto;" width="756" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.c948c58854719b0d2b16e6284a10ca8d.png" loading="lazy" height="430.92"></p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3576" data-unique="58inyh687" style="height: auto;" width="725" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.d54eda0a705d24ac632341c64e90d06d.png" loading="lazy" height="319"></p>

<p>
	<span style="font-size:20px;">Умное отображение цвета</span>
</p>

<p>
	Если ресурс цвета содержит известный код цвета, то вместо кода отображается название цвета. При наведении курсора мыши на превью цвета, отображается <strong>ARGB </strong>раскладка цвета.<br><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3578" data-unique="1lloyq0xa" style="height: auto;" width="228" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.7ba9ddd99e05bebf39c6d29833d944b1.png" loading="lazy" height="198.36"></p>

<p>
	 
</p>

<p>
	<span style="font-size:20px;">Отображение превью</span>
</p>

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

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3580" data-unique="unrf0oyjh" style="height: auto;" width="589" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.c8f9717c519dc5af09f634f683366e4f.png" loading="lazy" height="335.73"></p>

<p>
	<strong><span style="font-size:22px;">Улучшения в TfgButton</span></strong>
</p>

<p>
	Добавлено верхнее и нижнее положение иконки относительно текста. Теперь можно делать кнопки для нижней панели навигации без дополнительных комбинация стандартных компонентов.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="3582" href="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.15189750dd7b35a13b4ebe147605f7c0.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3582" data-unique="f8mgkt9y4" style="height: auto;" width="713" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.thumb.png.4266cc08547a928f831b3fcbd5ada4d5.png" loading="lazy" height="748.65"></a>
</p>

<p>
	<video class="ipsEmbeddedVideo" controls="" data-fileid="3586" data-unique="r9v49up7r" id="ips_uid_9986_9" src="https://forum.fgx-native.com/uploads/monthly_2022_09/20220904_174816.mp4.28fb124a83f8c7697192964b48dbb934.mp4" style="max-width: 320px" data-controller="core.global.core.embeddedvideo" preload="metadata"><source type="video/mp4" src="https://forum.fgx-native.com/uploads/monthly_2022_09/20220904_174816.mp4.28fb124a83f8c7697192964b48dbb934.mp4"><a class="ipsAttachLink" data-fileext="mp4" data-fileid="3586" href="https://forum.fgx-native.com/applications/core/interface/file/attachment.php?id=3586&amp;key=a922406898b4e7c41858d665df754f18" rel="">20220904_174816.mp4</a>
	</source></video></p>

<p>
	<strong><span style="font-size:22px;">Многопоточный режим TfgPickerPhoto</span></strong>
</p>

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

<pre><code>  TfgPickerPhotoFactory.PickPhotosFromLibrary(btnTakePhotoFromLibrary,
    procedure(const AFileNames: TfgPhotoFiles)
    begin
      LoadImages(AFileNames);
    end,
    procedure(const AProgress: Single)
    begin
      ShowProgress(AProgress);
    end);</code></pre>

<p>
	<strong><span style="font-size:22px;">Поддержка Android 12</span></strong>
</p>

<p>
	Добавлена поддержка Android 12. Для корректной публикации приложений в "<strong>Google Play Market</strong>", необходимо обновить манифест Android приложения. При открытии старого приложения, IDE предложит обновить манифест автоматически. Если вы вносили ручные правки в шаблон манифеста приложения, то перед обновлением манифеста сделайте его копию и затем заново внесите ваши правки. 
</p>

<p>
	Если по каким-то причинам среда не предложила обновить манифест (если вы ранее отказались от обновления шаблона), то вы можете это сделать вручную. Для этого необходимо добавить атрибут `android:exported="true"` в узел `activity`.<br><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3587" data-unique="mxtt9qps3" style="height: auto;" width="730" src="https://forum.fgx-native.com/uploads/monthly_2022_09/image.png.bf7979e3bfeb5c70d4df74fce4a65fd6.png" loading="lazy" height="116.8"></p>

<p>
	<span style="font-size:22px;"><strong>Delphi 11 Update 2</strong></span>
</p>

<p>
	Добавлена поддержка Delphi 11 Update 2. Из-за критических изменений на стороне IDE, перестали собираться приложения FGX Native из-за нарушения целостности в Deployment Manager. Данный релиз устраняет эту проблему.
</p>

<p>
	Надеемся, что новый функционал придется вам по душе и облегчит процесс разработки. Через релиз мы выпустим поддержку стилей, которые значительно упростят процесс верстки интерфейса вашего приложения в дизайнере.
</p>
]]></description><guid isPermaLink="false">47</guid><pubDate>Wed, 07 Sep 2022 01:09:10 +0000</pubDate></item><item><title>&#x410;&#x43D;&#x43E;&#x43D;&#x441; 1.14.0.0</title><link>https://forum.fgx-native.com/blogs/entry/42-%D0%B0%D0%BD%D0%BE%D0%BD%D1%81-11400/</link><description><![CDATA[<p>
	Здравствуйте, уважаемые разработчики.
</p>

<p>
	В этом анонсе мы хотим познакомить вас с теми нововведениями, которые появятся в версии <strong>1.14.0.0</strong>.
</p>

<p>
	<span style="font-size:22px;"><strong>Лицензии и коды активации</strong></span>
</p>

<p style="text-align: justify;">
	Начиная с версии <strong>1.14.0.0</strong> библиотека будет содержать систему защиты, которая построена на кодах активации и файлах лицензий. Каждому клиенту с активной подпиской был выслан индивидуальный код активации на email, привязанный к его учетной записи. Если по какой-то причине вы не получили свой код активации - свяжитесь с нами любым удобным для вас способом.
</p>

<p style="text-align: justify;">
	При старте <strong>Delphi </strong>с неактивированной версией библиотеки вам будет предложено ввести индивидуальный код активации.
</p>

<p style="text-align: center;">
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3229" data-unique="zfowlpl0g" style="height: auto;" width="529" src="https://forum.fgx-native.com/uploads/monthly_2022_04/image.png.6c4b5be8c3ca144476b44d9fc1d2273a.png" loading="lazy" height="317.4"></p>

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

<p style="text-align: center;">
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3232" data-unique="ma033jkoz" style="height: auto;" width="692" src="https://forum.fgx-native.com/uploads/monthly_2022_04/image.png.ab0e56619bf3ce5d28bb7619241685af.png" loading="lazy" height="519"></p>

<p>
	<span style="font-size:16px;"><strong>Важные сведения, связанные с активацией библиотеки:</strong></span>
</p>

<ul><li>
		Допускается <span style="color:#c0392b;"><strong>3 (три)</strong></span><span style="color:#c0392b;"> </span>активации библиотеки на разных физических машинах, исходя из усредненной схемы использования: домашний, рабочий компьютеры и одна активация на случай смены физических комплектующих вашего компьютера. Однако, если по каким-то объективным причинам у вас будет потребность в дополнительных активациях, вы всегда можете связаться с нами любым удобным для вас способом. Не используйте активацию на чужих/ненужных компьютерах.
	</li>
	<li>
		Активацию необходимо производить <span style="color:#c0392b;"><strong>каждый раз</strong></span> после установки <strong><span style="color:#c0392b;">новой версии</span></strong> библиотеки. При этом каждая активация библиотеки <span style="color:#c0392b;"><strong>на одной и той же</strong></span> машине <span style="color:#c0392b;"><strong>не считается</strong></span> за отдельную активацию.
	</li>
	<li>
		При <span style="color:#c0392b;"><strong>обновлении</strong></span> продукта или <span style="color:#c0392b;"><strong>приобретении </strong></span>новой подписки, вам будет выслан <span style="color:#c0392b;"><strong>новый код активации</strong></span>, который действует на новый срок. При этом старый код <span style="color:#c0392b;"><strong>продолжает действовать</strong></span> для <span style="color:#c0392b;"><strong>старых версий </strong></span>библиотеки, как и ранее.
	</li>
</ul><p>
	<span style="font-size:22px;"><strong>Увеличенные сроки действия подписки </strong></span>
</p>

<p>
	В ближайшее время мы планируем расширить тарифные планы путем добавления подписок на 6 месяцев и 1 год. Детали о тарифах будут опубликованы позднее.
</p>

<p>
	<span style="font-size:22px;"><strong>Идентификация через сервис Google Sign in</strong></span>
</p>

<p style="text-align: justify;">
	Мы продолжаем пополнять поддержку новых сервисов идентификации клиентов. В версии <strong>1.14.0.0</strong> предлагаем новый компонент <strong>TfgGoogleSignInAuthenticationClient </strong>для идентификации клиента через сервис "<strong>Google Sign in"</strong>. На текущий момент компонент реализован для <strong>Android</strong> платформы.
</p>

<p>
	<strong><span style="font-size:22px;">TfgCollectionView и ручное выделение </span></strong>
</p>

<p style="text-align: justify;">
	<strong>TfgCollectionView </strong>поддерживает разные режимы выделения элементов. Ранее при выделении элемента происходило визуальное отображение заднего фона всего элемента, согласно настройкам цвета <strong>SelectionColorName</strong>/<strong>SelectionColor</strong>. Однако, если вы используете в качестве элементов <strong>TfgCardPanel</strong> или другие виды контейнеров, то часто нужно выполнять изменение цвета не всего элемента, а только вложенного контейнера:
</p>

<p>
	<video class="ipsEmbeddedVideo" controls="" data-fileid="3230" data-unique="69qryg8rl" id="ips_uid_5811_8" src="https://forum.fgx-native.com/uploads/monthly_2022_04/Advanced_animation.mp4.1f5461e85ffcf2d14b43e8518ef918c3.mp4.cb85b1f01861f96316cfdf06ea7d0559.mp4" style="max-width: 320px" data-controller="core.global.core.embeddedvideo" preload="metadata"><source type="video/mp4" src="https://forum.fgx-native.com/uploads/monthly_2022_04/Advanced_animation.mp4.1f5461e85ffcf2d14b43e8518ef918c3.mp4.cb85b1f01861f96316cfdf06ea7d0559.mp4"><a class="ipsAttachLink" data-fileext="mp4" data-fileid="3230" href="https://forum.fgx-native.com/applications/core/interface/file/attachment.php?id=3230&amp;key=721fe3c48d430309ffd4690e75525175" rel="">Advanced_animation.mp4.1f5461e85ffcf2d14b43e8518ef918c3.mp4</a>
	</source></video></p>

<p style="text-align: justify;">
	В версии <strong>1.14.0.0</strong> мы добавили возможность управлять внешним видом выделения элементов в ручном режиме, что открывает практически безграничные возможности по кастомизации. Новое свойство <strong>TfgCollectionView.SelectionOptions.DisplayingMode</strong> позволяет указать каким способом нужно отображать выделение. Доступно два способа отображения:
</p>

<ol><li style="text-align: justify;">
		<strong>Auto</strong> - обычный (старый) режим. Компонент берет на себя ответственность по изменению внешнего вида выделенных элементов путем изменения цвета заднего фона элемента. (<strong>по умолчанию</strong>)
	</li>
	<li style="text-align: justify;">
		<strong>Manual</strong> - ручной режим. В этом режиме компонент делегирует разработчику работу по изменению внешнего вида выделенных элементов. О необходимости выделить/сбросить элемент компонент сообщает с помощью нового события <strong>OnUpdateItemSelectionAppearance</strong>.
	</li>
</ol><p style="text-align: justify;">
	В ручном режиме вам необходимо выполнить визуальное выделение или сброс выделения у переданного элемента в событии <strong>OnUpdateItemSelectionAppearance</strong>. Это событие вызывается каждый раз, когда списку необходимо обновить состояние элемента. Среди аргументов события передается информация о:
</p>

<ul><li style="text-align: justify;">
		<strong>AItem</strong> - обертка для работы с элементом.
	</li>
	<li style="text-align: justify;">
		<strong>AIsSelected </strong>- признак состояния выделения элемента.
	</li>
	<li style="text-align: justify;">
		<b>AInitiator </b>- Кто инициатор обновления выделения элемента. Если вы хотите добавить анимации в процесс выделения элемента, то ориентируйтесь на этот флаг. Если пользователь нажимает на элемент, то в этом параметре будет значение "<strong>User</strong>", в противном случае "<strong>Control</strong>".
	</li>
</ul><p style="text-align: justify;">
	Типичный код ручного выделения может выглядеть так:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7888_11" style=""><span class="pln">procedure TFormMain.fgCollectionView1UpdateItemSelectionAppearance(Sender: TObject; const AItem: TfgItemWrapper; const AIsSelected: Boolean; const AInitiator: TfgItemSelectionInitiator);
var
  BackgroundPanel: TfgCardPanel;
  PrimaryLabel: TfgLabel;
begin
  // Извлекаем ссылку на фон и текстовую метку в элементе
  BackgroundPanel := AItem.GetControlByLookupName</span><span class="tag">&lt;TfgCardPanel&gt;</span><span class="pln">('background');
  PrimaryLabel := AItem.GetControlByLookupName</span><span class="tag">&lt;TfgLabel&gt;</span><span class="pln">('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;</span></pre>

<p style="text-align: justify;">
	Добавлен новый демонстрационный пример: "Компоненты" -&gt; "TfgCollectionView" -&gt; "Ручное отображение выделения".
</p>

<p>
	<strong><span style="font-size:22px;">TfgControlEnumerators</span></strong>
</p>

<p>
	Теперь доступны два энумератора по обходу дерева компонентов с возможностью управлять обходом. Оба энумератора доступы в классе <strong>TfgControlEnumerators</strong>.
</p>

<ul><li>
		<strong>TfgControlEnumerators.Enum</strong> - Корень -&gt; First..Last child
	</li>
	<li>
		<strong>TfgControlEnumerators.ReverseEnum</strong> - Корень -&gt; Last..First child
	</li>
</ul><p>
	Например, обход по всем <strong>TfgEdit </strong>может выглядеть так:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9201_15" style=""><span class="pln">TfgControlEnumerators.Enum(Form,
  procedure (const AChild: TfgControl; var AAction: TfgEnumControlsAction)
  begin
    if AChild is TfgEdit then
      TfgLog.Debug(AChild.ToString);
  end);</span></pre>

<p>
	Помимо обычного обхода есть возможность делать контролируемый обход. Например, поиск поля ввода:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_9201_17" style=""><span class="pln">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);</span></pre>

<p>
	Через параметр <strong>AAction</strong> анонимной функции можно передать дальнейшее направление действия по обходу компонентов:
</p>

<ul><li>
		<strong>Continue </strong>- Перейти к следующему компоненту;
	</li>
	<li>
		<strong>Discard</strong> - Перейти к соседнему компоненту;
	</li>
	<li>
		<strong>Stop </strong>- Остановить обход.
	</li>
</ul><p>
	<strong><span style="font-size:22px;">Маленькие приятности</span></strong>
</p>

<p>
	Теперь компоненты из групп "<strong>FGX: Standard</strong>" и "<strong>FGX: Layout</strong>" имеют свои оригинальные иконки, которые позволяют проще находить нужные компоненты в палитре компонентов.
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3233" data-unique="ijbvqmomp" style="height: auto;" width="240" src="https://forum.fgx-native.com/uploads/monthly_2022_04/image.png.70a7e885ad954a347a14d0dee8c86460.png" loading="lazy" height="393.6"><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3234" data-unique="0uxpvibhj" style="height: auto;" width="198" src="https://forum.fgx-native.com/uploads/monthly_2022_04/image.png.e4fa3ae69a5063baa606e8c9624efb7d.png" loading="lazy" height="243.54"></p>

<p>
	 
</p>
]]></description><guid isPermaLink="false">42</guid><pubDate>Sat, 09 Apr 2022 20:02:00 +0000</pubDate></item><item><title>&#x410;&#x43D;&#x43E;&#x43D;&#x441; 1.13.5.0 &#x438; Lottie &#x430;&#x43D;&#x438;&#x43C;&#x430;&#x446;&#x438;&#x44F;</title><link>https://forum.fgx-native.com/blogs/entry/39-%D0%B0%D0%BD%D0%BE%D0%BD%D1%81-11350-%D0%B8-lottie-%D0%B0%D0%BD%D0%B8%D0%BC%D0%B0%D1%86%D0%B8%D1%8F/</link><description><![CDATA[<p style="text-align: justify;">
	В этом году нас ждет большое количество новых компонентов и возможностей в библиотеке <strong>FGX Native</strong>: начиная о завершении добавления <strong>iOS</strong> платформы в библиотеки, продолжая всевозможными интеграциями мобильных сервисов (оплата, идентификация, встроенные покупки и тд) и заканчивая разработкой новых визуальных компонентов. 
</p>

<p style="text-align: justify;">
	В последнем релизе <strong>1.13.4.0</strong> мы уже анонсировали добавление сервисов идентификации пользователя в сторонних сервисах. Сервисы идентификации позволяют получить информацию о пользователе используя его учетную запись в других сервисах, таких как <strong>GoogleId</strong>, <strong>AppleID</strong>, <strong>Facebook</strong>, <strong>VKontakte </strong>и тд. В релизе <strong>1.13.4.0</strong> мы разработали низкоуровневую кроссплатформенную архитектуру сервисов идентификации, которая позволяет нам и вам добавлять реализации любых сервисов идентификации пользователя. Первым таким сервисом стала реализация <strong>AppleID </strong>(<strong>TfgAppleIdAuthenticationClient</strong>). На подходе <strong>Facebook</strong> и другие сервисы. Детально о том, как установить и использовать разработанные компоненты мы поговорим в отдельных статьях.
</p>

<p style="text-align: justify;">
	В этой статье нам хотелось бы поделиться одним очень мощным и полезным новым компонентом, которые позволит легко оживить ваше приложение и добавить в него сложные анимации. Речь пойдет о поддержке анимации <strong>Airbnb Lottie</strong> (<a href="https://airbnb.io/lottie/#/" ipsnoembed="true" rel="external nofollow">https://airbnb.io/lottie</a>)
</p>

<p style="text-align: justify;">
	<img alt="95171-colors.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="3091" data-unique="2g06ddpzj" style="width: 320px; height: auto;" width="640" src="https://forum.fgx-native.com/uploads/monthly_2022_02/95171-colors.gif.eb86673f45731130ad30b2ea87d2a101.gif" loading="lazy" height="640"><img alt="84872-disconnected.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="3092" data-unique="ruurxdjov" style="width: 320px; height: auto;" width="640" src="https://forum.fgx-native.com/uploads/monthly_2022_02/84872-disconnected.gif.c476e9da2424c1d9a3d5c0452ddceb36.gif" loading="lazy" height="640"></p>

<p style="text-align: justify;">
	 
</p>

<p style="text-align: justify;">
	<strong><span style="font-size:22px;">Немного о Lottie</span></strong>
</p>

<p style="text-align: justify;">
	<strong>Lottie </strong>- это библиотека с открытым кодом от компании <strong>Airbnb </strong>для проигрывания анимации, созданной в приложении <a href="https://www.adobe.com/ru/products/aftereffects.html" rel="external nofollow">Adobe After Effects</a>.
</p>

<p style="text-align: justify;">
	Впервые дизайнеры могут создавать и доставлять красивые анимации без того, чтобы разработчик кропотливо воссоздавал их вручную.
</p>

<p style="text-align: justify;">
	Анимация представляет собой текстовый файл в формате JSON, в котором содержится описание построения векторного изображения с анимацией. Благодаря чему, файл анимация весит очень мало при этом не теряя в качестве. 
</p>

<p style="text-align: justify;">
	В библиотеку добавлен новый компонент <strong>TfgLottieImage</strong>, который позволяет отобразить <strong>Lottie </strong>анимацию.
</p>

<p style="text-align: justify;">
	<strong><span style="font-size:22px;">Как использовать?</span></strong>
</p>

<p style="text-align: justify;">
	1. Для начала надо раздобыть файл анимации. Можно поискать готовые анимации от дизайнеров на ресурсе <a href="https://lottiefiles.com/" ipsnoembed="true" rel="external nofollow">https://lottiefiles.com/</a> .
</p>

<p style="text-align: justify;">
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3093" data-unique="am13qqhbn" style="height: auto;" width="818" src="https://forum.fgx-native.com/uploads/monthly_2022_02/image.png.c9c5f9462240054f9af5ea9bb8cf89cb.png" loading="lazy" height="556.24"></p>

<p style="text-align: justify;">
	Помимо этого ресурса, есть еще и другие. Например, ресурс по встраиванию анимированных иконок: <a href="https://lordicon.com/" ipsnoembed="true" rel="external nofollow">https://lordicon.com/</a> 
</p>

<p style="text-align: justify;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="3094" href="https://forum.fgx-native.com/uploads/monthly_2022_02/image.png.29c1352d8d136f398c58f65a8df2b0bc.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3094" data-unique="1g7xzoa8u" style="height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2022_02/image.thumb.png.1f76a1319a6ec155ed4c364f6e5d9a97.png" loading="lazy" height="380"></a>
</p>

<p style="text-align: justify;">
	После выбора интересуемой анимации, скачиваем анимацию в формате <strong>Lottie JSON</strong>. Например, такая анимация ракеты весит всего 25 КБ:
</p>

<p style="text-align: justify;">
	<video class="ipsEmbeddedVideo" controls="" data-fileid="3095" data-unique="gf7z9sg7l" id="ips_uid_4549_6" src="https://forum.fgx-native.com/uploads/monthly_2022_02/2022-02-15-00-47-28.mp4.35454c901f0705693d8fbf79d56f2946.mp4" style="max-width:320px" data-controller="core.global.core.embeddedvideo" preload="metadata"><source type="video/mp4" src="https://forum.fgx-native.com/uploads/monthly_2022_02/2022-02-15-00-47-28.mp4.35454c901f0705693d8fbf79d56f2946.mp4"><a class="ipsAttachLink" data-fileext="mp4" data-fileid="3095" href="https://forum.fgx-native.com/applications/core/interface/file/attachment.php?id=3095&amp;key=250c84dc459ec7311d4bcb4d88ec5f72" rel="">2022-02-15-00-47-28.mp4</a>
	</source></video></p>

<p>
	2. После этого добавляем этот файл анимации в дизайнер ресурсов <strong>FGX Native</strong>. Добавлен новый тип ресурса "<strong>Lottie Анимация</strong>":
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3096" data-unique="euxrosy9x" style="height: auto;" width="726" src="https://forum.fgx-native.com/uploads/monthly_2022_02/image.png.9fa0363ed23416e792040abb8b305061.png" loading="lazy" height="421.08"></p>

<p>
	После создания нового ресурса, загружаем скаченный ранее файл. В результате чего дизайнер отобразит вам ваш файл анимации. Укажите ресурсу понятное имя, например "<strong>Animations\Red Rocket</strong>".
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3097" data-unique="phahysfb9" style="height: auto;" width="606" src="https://forum.fgx-native.com/uploads/monthly_2022_02/image.png.b1b083c5504e0422284a75d76b9bab6e.png" loading="lazy" height="145.44"></p>

<p>
	Разместив на форме новый компонент <strong>TfgLottieImage,</strong> укажите ресурс анимации через свойство <strong>AnimationName</strong>. 
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="3098" data-unique="vihy7f3k4" style="height: auto;" width="771" src="https://forum.fgx-native.com/uploads/monthly_2022_02/image.png.e1cbc20327a7ed0cd7f458426436a179.png" loading="lazy" height="516.57"></p>

<p>
	Это все, что требуется, чтобы запустить ракету в космос. Запустив приложение на <strong>Android </strong>или <strong>iOS </strong>вы увидите летящую ракету.
</p>

<p>
	<video class="ipsEmbeddedVideo" controls="" data-fileid="3099" data-unique="sp8voa5sw" id="ips_uid_4549_7" src="https://forum.fgx-native.com/uploads/monthly_2022_02/Lottie-Demo-Sample.mp4.666bf68c84eed5fb76042e54a385ab9a.mp4" style="max-width:300px" data-controller="core.global.core.embeddedvideo" preload="metadata"><source type="video/mp4" src="https://forum.fgx-native.com/uploads/monthly_2022_02/Lottie-Demo-Sample.mp4.666bf68c84eed5fb76042e54a385ab9a.mp4"><a class="ipsAttachLink" data-fileext="mp4" data-fileid="3099" href="https://forum.fgx-native.com/applications/core/interface/file/attachment.php?id=3099&amp;key=5d9327f43f7b59071a61d155a3c5ae21" rel="">Lottie-Demo-Sample.mp4</a>
	</source></video></p>

<p>
	<strong><span style="font-size:22px;">Демонстрационный пример</span></strong>
</p>

<p>
	В поставку включен новый демо-пример "<strong>Компоненты</strong>" -&gt; "<strong>TfgLottieImage</strong>" -&gt; "<strong>Проигрыватель Lottie анимации</strong>".
</p>

<p>
	<strong><span style="font-size:22px;">Настройки </span></strong>
</p>

<p style="text-align: justify;">
	Компонент предлагает базовые настройки.
</p>

<ul><li style="text-align: justify;">
		<strong>ImageMode</strong> - Режим отображения изображения (растянуть, вписать, заполнить).
	</li>
	<li style="text-align: justify;">
		<strong>Loop </strong>- нужно ли запускать анимацию по кругу.
	</li>
	<li style="text-align: justify;">
		<strong>Speed</strong> - коэффициент скорости. Например: 2 - проигрывать анимацию в два раза быстрее, 0.5 - в два раза медленнее.
	</li>
	<li style="text-align: justify;">
		<strong>Duration </strong>- длительность анимации в мсек (без учета <strong>Speed</strong>).
	</li>
</ul><p style="text-align: justify;">
	Помимо этого, вы можете проверить проигрывается ли сейчас анимация <strong>IsAnimating</strong> или управлять воспроизведением через:
</p>

<ul><li style="text-align: justify;">
		<strong>Play </strong>- начать воспроизведение с начала
	</li>
	<li style="text-align: justify;">
		<strong>Stop </strong>- остановить (Progress сбрасывается на начало).
	</li>
	<li style="text-align: justify;">
		<strong>Pause </strong>- приостановить
	</li>
	<li style="text-align: justify;">
		<strong>Resume </strong>- продолжить с текущего места.
	</li>
	<li style="text-align: justify;">
		<strong>Progress</strong> - установить текущее место воспроизведения. Коэффициент из диапазона [0..1], где 0 - это начало, 1 - конец.
	</li>
</ul><p style="text-align: justify;">
	<strong><span style="font-size:22px;">Итоги</span></strong>
</p>

<p style="text-align: justify;">
	Уверены, данная новинка найдет свое применение в ваших проектах и добавит им изюминки. 
</p>
]]></description><guid isPermaLink="false">39</guid><pubDate>Mon, 14 Feb 2022 21:30:00 +0000</pubDate></item><item><title>&#x410;&#x43D;&#x43E;&#x43D;&#x441; 1.13.3.0 &#x438; GooglePay</title><link>https://forum.fgx-native.com/blogs/entry/38-%D0%B0%D0%BD%D0%BE%D0%BD%D1%81-11330-%D0%B8-googlepay/</link><description><![CDATA[<p>
	Поздравляем вас с наступающим Новым годом!
</p>

<p>
	Мы благодарим вас за доверие и спасибо, что в этом году вы были с нами. В течении всего года мы прислушивались к вашим пожеланиям и старались сделать все возможное, чтобы наш продукт раз от раза становился удобнее и мощнее.
</p>

<p>
	В ближайшее время выйдет новый релиз <strong>1.13.3.0</strong>. Традиционно в этом релизе вас ждет несколько полезных новинок и улучшений.
</p>

<p>
	<strong><span style="font-size:22px;">GooglePay - TfgGooglePayClient </span></strong>
</p>

<p>
	Первая новинка - это новый компонент <strong>TfgGooglePayClient</strong> оплаты покупок в вашем приложении через платежную систему <strong>GooglePay</strong>.
</p>

<p>
	<span style="font-size:22px;">Настройка </span>
</p>

<p>
	Для того, чтобы добавить возможность оплаты покупок в вашем приложении, вам необходимо выполнить первичную настройку на стороне <strong>Google </strong>- <a href="https://developers.google.com/pay/api/web/guides/setup?hl=ru" ipsnoembed="true" rel="external nofollow">https://developers.google.com/pay/api/web/guides/setup?hl=ru</a>
</p>

<p>
	В результате этой настройки вы получите идентификатор продавца <strong>Google </strong>- <strong>MerchantId</strong>.
</p>

<p>
	<span style="font-size:20px;">Настройка приложения FGX Native</span>
</p>

<p>
	Для того, чтобы иметь возможность использовать <strong>GooglePay</strong> в <strong>FGX Native</strong> приложении, необходимо добавить в манифест <strong>Android </strong>приложения следующие строчки в любое место внутрь тега <strong>&lt;application&gt;</strong>:
</p>

<p>
	 1. Версию <strong>GooglePlay</strong> сервисов. <span style="color:#c0392b;"><strong>ТОЛЬКО</strong></span>, если вы не используете "<strong>Firebase PushNotification"</strong>, <strong>Maps</strong> или <strong>AdMob</strong>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4767_16" style=""><span class="tag">&lt;meta-data</span><span class="pln"> </span><span class="atn">android:name</span><span class="pun">=</span><span class="atv">"com.google.android.gms.version"</span><span class="pln"> </span><span class="atn">android:value</span><span class="pun">=</span><span class="atv">"12451000"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<p>
	2. Включить доступ приложения к кошельку:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4767_18" style=""><span class="tag">&lt;meta-data</span><span class="pln">
    </span><span class="atn">android:name</span><span class="pun">=</span><span class="atv">"com.google.android.gms.wallet.api.enabled"</span><span class="pln">
    </span><span class="atn">android:value</span><span class="pun">=</span><span class="atv">"true"</span><span class="pln"> </span><span class="tag">/&gt;</span></pre>

<p>
	3. Указать идентификатор продавца в свойстве "<strong>TfgGooglePayClient.MerchantName"</strong>, полученный на предыдущем шаге.
</p>

<p>
	<span style="font-size:20px;">Проверка возможности оплаты через GooglePay</span>
</p>

<p>
	<strong>GooglePay </strong>может быть недоступен на устройстве пользователя, поэтому, перед инициированием процесса оплаты, необходимо узнать текущий статус. Это можно сделать через асинхронный метод "<strong>TfgGooglePayClient.IsReadyToPayAsync"</strong>:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4767_24" style=""><span class="pln">uses
  FGX.Payments.GooglePay.Types;

if gpClient.IsSupported then
  gpClient.IsReadyToPayAsync(False, procedure (const AStatus: TfgGooglePayStatus)
    begin
      // Отображаем/Скрываем кнопку оплаты через GooglePay
      btnPay.Visible := AStatus = TfgGooglePayStatus.Available;
    end);</span></pre>

<p>
	<span style="font-size:20px;">Оплата через GooglePay</span>
</p>

<p style="text-align: justify;">
	Для инициации оплаты необходимо заполнить информацию о проводимой транзакции и воспользоваться асинхронным методом оплаты "<strong>TfgGooglePayClient.PayAsync</strong>". Минимально необходимая информация в транзакции - это код валюты и цена.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4767_27" style=""><span class="pln">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;</span></pre>

<ol></ol><p>
	<span style="color:#27ae60;">Описание полей транзакции, смотрите в исходном коде или </span><a href="https://developers.google.com/pay/api/android/reference/request-objects#TransactionInfo" rel="external nofollow"><span style="color:#27ae60;">на сайте GooglePay</span></a><span style="color:#27ae60;">.</span>
</p>

<p>
	По результатам обработки запроса, будет вызвано одно из событий:
</p>

<ol><li>
		"<strong>OnPaymentError</strong>" - в ходе оплаты произошла ошибка.
	</li>
	<li>
		"<strong>OnPaymentComplete</strong>" - пользователь выполнил оплату, токен для проведения оплаты передается в параметрах события.
	</li>
	<li>
		"<strong>OnPaymentCancelled</strong>" - пользователь отменил оплату.
	</li>
</ol><p>
	Если платеж прошел успешно, то в событии <strong>OnPaymentComplete </strong>будет передан <a href="https://developers.google.com/pay/api/android/reference/response-objects#PaymentData" rel="external nofollow">JSON ответ</a>, из которого вы можете извлечь необходимую информацию согласно документации:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4767_29" style=""><span class="pln">procedure TFormMain.gpClientPaymentComplete(Sender: TObject; const AResponse: TJSONValue);
begin
  mLog.Lines.Add(Format('Completed: AResponse="%s"', [AResponse.Format]));
end;</span></pre>

<p>
	После извлечения платежного токена, вам необходимо провести транзакцию на вашем сервере через ваш банк.
</p>

<p>
	Если же оплата по каким-то причинам не прошла, вы можете получить информацию об ошибке через событие <strong>OnPaymentError</strong>. В параметрах передается код ошибки и ее описание. Обратите внимание, что данный код и описание выдается самой системой. Поэтому иногда описание может отсутствовать или содержать неполную информацию (это нормально).
</p>

<ul></ul><p>
	<span style="font-size:20px;">Диагностика и отладка</span>
</p>

<p style="text-align: justify;">
	Все детальные ошибки настройки интеграции с <strong>GooglePay</strong> обычно выводятся в лог. Именно там можно узнать, почему платеж не запускается или не проходит. Обратите внимание, что чаще всего ошибки в лог попадают не от имени приложения, а от системы. Поэтому при поиске проблем, нужно это учитывать (не фильтровать сообщения вашим приложением).
</p>

<p style="text-align: justify;">
	Все свойства компонента полностью соответствуют оберткам в документации <a href="https://developers.google.com/pay/api/android/reference/request-objects" rel="external nofollow">Google Pay</a>. Компонент формирует JSON запрос, который отправляется в нативное <strong>API</strong>. Вы можете проверить корректность формирования <strong>JSON </strong>запроса через лог. Для этого необходимо включить расширенное логирование в вашем приложении:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4767_39" style=""><span class="pln">TfgLog.MinimumLevel := TfgLogLevel.Trace;</span></pre>

<p>
	Полезные ссылки:
</p>

<ul><li>
		<a href="https://developers.google.com/pay/api/android/guides/brand-guidelines?hl=ru" rel="external nofollow">Руководство по использованию бренда GooglePay.</a>
	</li>
	<li>
		<a href="https://developers.google.com/pay/api/android/guides/ux-best-practices?hl=ru" rel="external nofollow">Советы UX по интеграции GooglePay.</a>
	</li>
	<li>
		<a href="https://developers.google.com/pay/api/android/guides/test-and-deploy/integration-checklist?hl=ru" rel="external nofollow">Чек лист по настройке GooglePay.</a>
	</li>
	<li>
		<a href="https://developers.google.com/pay/api/web/support/troubleshooting?hl=ru" rel="external nofollow">Диагностика проблем.</a>
	</li>
</ul><p>
	<strong><span style="font-size:22px;">TfgApplicationEvents</span></strong>
</p>

<p style="text-align: justify;">
	При разработке <strong>Android </strong>приложений и при использовании <strong>Android API</strong> очень часто требуется отправить запрос другим активностям и получить от них результат. Раньше это решалось через подписку на широковещательные сообщения  <strong>FGX.Platform.Android.TfgActivityResultMessage</strong> и <strong>TfgActivityNewIntentMessage </strong>и требовало написать следующий код:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4767_7" style=""><span class="pln">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;</span></pre>

<p style="text-align: justify;">
	Сейчас же мы добавили два новых события "<strong>TfgApplicationEvents.OnActivityResult</strong>" и "<strong>TfgApplicationEvents.OnActivityNewIntent</strong>", которые позволяют значительно сократить код и сконцентрироваться только на реализации. 
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_4767_9" style=""><span class="pln">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;</span></pre>

<p>
	<strong><span style="font-size:22px;">TfgCollectionView</span></strong>
</p>

<p style="text-align: justify;">
	Мы провели улучшение контроллера выделения элементов и предоставили больше гибкости в точной настройке поведения. Раньше при режиме выделения  "<strong>TfgCollectionViewSelectionMode = SingleSelect</strong>" мы не позволяли сбросить выделение элемента повторным нажатием. Это было сделано для возможности реализации меню с отображением текущего выбранного раздела. Однако, для некоторых пользователей такое поведение компонента было нежелательным.
</p>

<p style="text-align: justify;">
	Теперь мы предлагаем вам самостоятельно решить, как должно работать выделение при помощи новых событий  "<strong>TfgCollectionView.OnItemCanSelect</strong>" и "<strong>TfgCollectionView.OnItemCanDeselect</strong>". Данные события вызываются непосредственно до момента установки или снятия выделения и позволяют отменить действие при помощи передаваемого параметра <strong>AAllow</strong>.
</p>

<p style="text-align: justify;">
	Так же мы исправили ряд ошибок выделения на платформе <strong>iOS</strong>, так что теперь процесс выделения работает одинаково на всех платформах.
</p>

<p style="text-align: justify;">
	<strong><span style="color:#e74c3c;">ВАЖНО!</span></strong> Теперь по умолчанию компонент позволяет сбросить выделение элемента в режиме <strong>SingleSelect</strong>. 
</p>

<p style="text-align: justify;">
	<span style="font-size:22px;">Заключении</span>
</p>

<p style="text-align: justify;">
	Желаем вам свершения всего задуманного, интересных проектов и амбициозных целей!
</p>

<p style="text-align: justify;">
	Спасибо, что вы с нами!
</p>
]]></description><guid isPermaLink="false">38</guid><pubDate>Thu, 30 Dec 2021 17:32:00 +0000</pubDate></item><item><title>&#x410;&#x43D;&#x43E;&#x43D;&#x441; 1.13.0.0 &#x438; Delphi 11</title><link>https://forum.fgx-native.com/blogs/entry/36-%D0%B0%D0%BD%D0%BE%D0%BD%D1%81-11300-%D0%B8-delphi-11/</link><description><![CDATA[<p>
	Добрый день,
</p>

<p>
	В ближайшее время выйдет релиз <strong>FGX Native</strong> <strong>1.13.0.0</strong> с полноценной поддержкой <strong>Delphi 11</strong>. Обо всех нововведениях по порядку.
</p>

<p>
	<strong><span style="font-size:22px;">Delphi 11</span></strong>
</p>

<p>
	Начиная с версии <strong>1.13.0.0</strong> мы включили поддержку <strong>Delphi 11</strong>. В то же время, мы исключили поддержку <strong>10.3</strong> из инсталлятора на основании результатов голосования:
</p>
<iframe allowfullscreen="" class="ipsEmbed_finishedLoading" data-embedauthorid="1" data-embedcontent="" data-embedid="embed2769212841" id="ips_uid_259_6" scrolling="no" src="https://forum.fgx-native.com/topic/1175-%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D0%B0-%D0%BA%D0%B0%D0%BA%D0%B8%D1%85-%D0%B2%D0%B5%D1%80%D1%81%D0%B8%D0%B9-delphi-%D0%B4%D0%BE%D0%BB%D0%B6%D0%BD%D0%B0-%D0%B1%D1%8B%D1%82%D1%8C-%D0%B2-fgx-native/?do=embed" style="overflow: hidden; height: 392px; max-width: 502px;" loading="lazy"></iframe>

<p>
	Мы переработали все формы дизайнера и добавили полноценную поддержку HiDPI.
</p>

<p>
	<strong><span style="font-size:22px;">Дизайнер форм</span></strong>
</p>

<p>
	Добавлен новый режим позволяющий отключать пунктирную рамку компонентов.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="2938" href="https://forum.fgx-native.com/uploads/monthly_2021_10/image.png.081251dc37754b39930161b8fc6de956.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2938" data-unique="rtxxsgpna" style="height: auto;" width="478" src="https://forum.fgx-native.com/uploads/monthly_2021_10/image.thumb.png.2978e6fc8724d634e482d7a6387389ec.png" loading="lazy" height="745.68"></a><a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="2939" href="https://forum.fgx-native.com/uploads/monthly_2021_10/image.png.77bb2e1e2875c49b7f6672c9fa8a58ac.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2939" data-unique="48fhy6fsv" style="height: auto;" width="508" src="https://forum.fgx-native.com/uploads/monthly_2021_10/image.thumb.png.45b9234b4ad1aef4c38882f60546dac9.png" loading="lazy" height="746.76"></a>
</p>

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

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="2940" href="https://forum.fgx-native.com/uploads/monthly_2021_10/image.png.cfaec96030f4ce30cfe082383228a0b0.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2940" data-unique="1q5n5eh2a" style="height: auto;" width="539" src="https://forum.fgx-native.com/uploads/monthly_2021_10/image.thumb.png.c50542761bf1e414415b4eb3e80829b0.png" loading="lazy" height="749.21"></a>
</p>

<p>
	<span style="font-size: 22px;"><b>Обновления TfgDatePicker и TfgTimePicker</b></span>
</p>

<p style="text-align: justify;">
	В этом релизе мы добавили несколько небольших улучшений этих компонентов. Теперь вы можете указать формат ввода времени: 12 или 24 часовой формат. За это отвечает новое свойство <strong>TfgTimePicker.Is24HoursMode = (LocaleDependent, True, False)</strong>. Теперь при старте компонента на платформе <strong>Android </strong>он по умолчанию выбирает часовой формат на основании текущей локали устройства.
</p>

<p>
	<img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2937" data-unique="ugzcar32m" style="height: auto;" width="255" src="https://forum.fgx-native.com/uploads/monthly_2021_10/image.png.cddb3fc2879a7e2fff703b870720f3c6.png" loading="lazy" height="316.2"> <img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2936" data-unique="gic5n2tzs" style="height: auto;" width="285" src="https://forum.fgx-native.com/uploads/monthly_2021_10/image.png.a5c0c652868c8b48d1cac2d42e229fda.png" loading="lazy" height="330.6"></p>

<p>
	Помимо этого мы добавили режим автоматического расчета размера для этих компонентов <strong>AutoSize</strong>, который включен по умолчанию. Поэтому, если вам необходимо, чтобы компоненты растягивались по ширине, нужно исключить значение <strong>AutoSize.Width</strong>.
</p>

<p>
	Так же, теперь вы можете отдельно указывать задний фон для этих компонентов при помощи свойства <strong>BackgroundName</strong>.
</p>

<p>
	 
</p>
]]></description><guid isPermaLink="false">36</guid><pubDate>Thu, 21 Oct 2021 21:30:56 +0000</pubDate></item><item><title>&#x410;&#x43D;&#x43E;&#x43D;&#x441; 1.12.0.0 &#x438; &#x43D;&#x43E;&#x432;&#x43E;&#x435; &#x440;&#x430;&#x441;&#x448;&#x438;&#x440;&#x435;&#x43D;&#x438;&#x435; &#x434;&#x43B;&#x44F; &#x433;&#x435;&#x43D;&#x435;&#x440;&#x430;&#x446;&#x438;&#x44F; &#x448;&#x442;&#x440;&#x438;&#x445;&#x43A;&#x43E;&#x434;&#x43E;&#x432; (Zint)</title><link>https://forum.fgx-native.com/blogs/entry/35-%D0%B0%D0%BD%D0%BE%D0%BD%D1%81-11200-%D0%B8-%D0%BD%D0%BE%D0%B2%D0%BE%D0%B5-%D1%80%D0%B0%D1%81%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B4%D0%BB%D1%8F-%D0%B3%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D1%8F-%D1%88%D1%82%D1%80%D0%B8%D1%85%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2-zint/</link><description><![CDATA[<p>
	Рады поделиться новинками будущего релиза <strong>1.12.0.0</strong>. 
</p>

<p>
	Очень часто при разработке мобильных приложений разработчики сталкиваются с одними и теми же задачами. Большинство решений, которые есть в интернете, ориентированы под <strong>FMX</strong>. Однако, зачастую из-за зависимостей в <strong>RTL </strong>на <strong>FMX Java</strong> код, эти решения нельзя просто добавить в <strong>FGX Native</strong> как есть и использовать.
</p>

<p>
	Поэтому мы решили по мере возможностей предлагать вам решения этих задач в виде расширений для <strong>FGX Native</strong>. Расширение будет включать необходимую обвязку/компоненты для <strong>FGX Native</strong> для сторонних <strong>OpenSource</strong> проектов. Первым таким расширением будет реализация нового компонента генерации штрихкода <strong>TfgBarcode</strong> на основе библиотеки <a href="https://github.com/landrix/Zint-Barcode-Generator-for-Delphi" rel="external nofollow">Zint</a> (<a href="https://www.zint.org.uk/" ipsnoembed="true" rel="external nofollow">https://www.zint.org.uk/</a>).
</p>

<p>
	<strong><span style="font-size:22px;">Отображение штрихкодов</span></strong>
</p>

<p>
	Новый пакет расширения <strong>FMXNative.Extension.Zint</strong> включен в поставку <strong>1.11.8.0</strong>. Пакет содержит новый компонент <strong>TfgBarcode</strong>, поддерживающий отображение огромного числа типов штрихкодов. 
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="2869" href="https://forum.fgx-native.com/uploads/monthly_2021_09/image.png.baf967f4635d4e058cdac3bc5f47aff2.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2869" data-unique="f4bgiszjs" style="height: auto;" width="759" src="https://forum.fgx-native.com/uploads/monthly_2021_09/image.thumb.png.8a1785ce9c0eeda4a3ff5f973378eabd.png" loading="lazy" height="743.82"></a>
</p>

<p>
	Свойство <strong>Symbology</strong> позволяет выбрать тип отображаемого штрихкода. Через свойство <strong>Data</strong> указываются кодируемые данные. А через группу свойств <strong>Appearance</strong> вы можете настроить визуальное отображение штрихкода.
</p>

<p>
	<strong><span style="font-size:22px;">Новое правило именования пакетов FGX Native</span></strong>
</p>

<p>
	Мы пересмотрели правила именований пакетов библиотеки <strong>FGX Native</strong>. Поэтому, если вы создаете свои пакеты расширений на основе <strong>FGX Native</strong>, вам необходимо переименовать зависимости на пакеты.
</p>

<ul><li>
		<strong>FGXNative.Core</strong> &lt;- fgx
	</li>
	<li>
		<strong>FGXNative.Design</strong> &lt;- fgx_design
	</li>
	<li>
		<strong>FGXNative.Registration</strong> &lt;-fgx_reg
	</li>
	<li>
		<strong>FGXNative.Extension.Translator</strong> &lt;- FGXTranslatorD
	</li>
	<li>
		<strong>FGXNative.Externals</strong> &lt;- fgx_externals
	</li>
</ul><p>
	Так же, если вы используется наш компонент локализации, необходимо:
</p>

<ul><li>
		После установки новой версии библиотеки запустить среду
	</li>
	<li>
		Среда отобразит ошибку при загрузке пакета <strong>FGXTranslatorD</strong>. Необходимо отвечать <strong>Yes </strong>во всех диалогах про этот пакет.
	</li>
	<li>
		Затем открыть список компонентов среды: "<strong>Components" </strong>-&gt; "<strong>Install Packages..."</strong>
	</li>
	<li>
		В списке найти строчку, соответствующую <strong>FGXTranslatorD </strong>и удалить ее при помощи кнопки "<strong>Remove</strong>".
	</li>
	<li>
		Данный компонент мы теперь регистрируем автоматически при установке <strong>FGX Native</strong>.
	</li>
</ul><p>
	<strong><span style="font-size:22px;">Календарь под iOS</span></strong>
</p>

<p>
	В новой версии так же появится реализация компонента <strong>TfgCalendar </strong>для <strong>iOS</strong>. <strong>iOS </strong>не имеет родной реализации календаря. Поэтому мы с нуля реализуем данный компонент.
</p>

<p>
	<strong><span style="font-size:22px;">Заключение</span></strong>
</p>

<p>
	Если у вас есть потребность в миграции некоторых невизуальных компонентов из <strong>FMX</strong>, пожалуйста, отпишитесь здесь в комментариях:
</p>

<ul><li>
		Ссылку на стороннюю библиотеку с наличием исходных кодов/<strong>OpenSource</strong>. Без доступа к исходным кодам мы не сможем выполнить адаптацию под <strong>FGX Native</strong>.
	</li>
	<li>
		Описание для чего данный компонент нужен.
	</li>
	<li>
		Если кто-то из участников уже озвучил в комментариях нужный вам компонент, просьба отметить такое сообщение реакцией (лайком).
	</li>
</ul><p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="2868" href="https://forum.fgx-native.com/uploads/monthly_2021_09/image.png.caa52ab5ccf13cda4fca5953b8209a08.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2868" style="height: auto;" width="385" src="https://forum.fgx-native.com/uploads/monthly_2021_09/image.png.caa52ab5ccf13cda4fca5953b8209a08.png" loading="lazy" height="138.6"></a>
</p>
]]></description><guid isPermaLink="false">35</guid><pubDate>Tue, 21 Sep 2021 21:35:00 +0000</pubDate></item><item><title>&#x41D;&#x43E;&#x432;&#x43E;&#x435; &#x441;&#x440;&#x435;&#x434;&#x441;&#x442;&#x432;&#x43E; &#x43F;&#x440;&#x43E;&#x441;&#x43C;&#x43E;&#x442;&#x440;&#x430; Android &#x43B;&#x43E;&#x433;&#x43E;&#x432; &#x432; FGX Native</title><link>https://forum.fgx-native.com/blogs/entry/34-%D0%BD%D0%BE%D0%B2%D0%BE%D0%B5-%D1%81%D1%80%D0%B5%D0%B4%D1%81%D1%82%D0%B2%D0%BE-%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%D0%B0-android-%D0%BB%D0%BE%D0%B3%D0%BE%D0%B2-%D0%B2-fgx-native/</link><description><![CDATA[<p style="text-align: justify;">
	Здравствуйте.
</p>

<p style="text-align: justify;">
	В этой статье мы поговорим о новинке, которая появится в релизе <strong>1.11.6.0</strong>, а именно о встроенном средстве просмотра логов устройств работающих под управлением операционной системы <strong>Android</strong>. <br>
	Общие данные о том, что такое логи, их ценность при отладке и тд вы можете прочитать в статье касающейся логирования в контексте <strong>iOS</strong>
</p>
<iframe allowfullscreen="" class="ipsEmbed_finishedLoading" data-embedauthorid="2" data-embedcontent="" data-embedid="embed1080359964" id="ips_uid_1334_6" scrolling="no" src="https://forum.fgx-native.com/blogs/entry/32-%D1%81%D0%B1%D0%BE%D1%80%D0%BA%D0%B0-%D0%B8-%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7-%D0%BB%D0%BE%D0%B3%D0%BE%D0%B2-%D0%B4%D0%BB%D1%8F-ios-%D1%81-%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E-%D1%83%D1%82%D0%B8%D0%BB%D0%B8%D1%82%D1%8B-console/.?do=embed" style="overflow: hidden; height: 233px; max-width: 502px;" loading="lazy"></iframe>

<p style="text-align: justify;">
	<span style="font-size:24px;"><strong>Общие сведения.</strong></span>
</p>

<p>
	Для просмотра логов под <strong>Android </strong>используется утилита командной строки <strong><a href="https://developer.android.com/studio/command-line/logcat" rel="external nofollow">logcat</a></strong>. Вы можете использовать ее как напрямую, управляя через параметры командной строки, так и воспользоваться <strong>Android Studio</strong> в которой есть одноименное <strong><a href="https://developer.android.com/studio/debug/am-logcat" rel="external nofollow">окно logcat</a></strong>.<br>
	Второй вариант предпочтительней, т. к. имеет графический интерфейс, но, естественно, он требует установки самой <strong>Android Studio</strong>.<br>
	Итак, новая утилита <strong>FGX Android Log Viewer</strong> (далее <strong>логвьювер</strong>) призвана упростить просмотр логов за счет удобной интеграции в <strong>IDE</strong>, графического интерфейса и гибкой системы фильтрации.
</p>

<p>
	<span style="font-size:24px;"><strong>Внешний вид.</strong></span>
</p>

<p>
	Запустить логвьювер можно из меню <strong>Project </strong>-&gt; <strong>FGX Android Log Viewer</strong>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="2824" href="https://forum.fgx-native.com/uploads/monthly_2021_09/1.png.45abd67eaa2121c857792ed32f35c2cd.png" rel=""><img alt="1.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2824" data-unique="u3qyqt462" style="height: auto;" width="1000" src="https://forum.fgx-native.com/uploads/monthly_2021_09/1.thumb.png.7bb18207758ff23ea9ba2b8010f2361d.png" loading="lazy" height="600"></a>
</p>

<ol><li>
		Левую горизонтальную часть окна занимает тулбар с основными органами управления, такими как: запуск/остановка захвата логов, очистка списка, экспорт и тд.
	</li>
	<li>
		Верхний тулбар содержит выбор активного устройства, выбор приложения, для которого будут собираться логи (либо для всех приложений) и быстрый фильтр.
	</li>
	<li>
		Основную часть окна занимает список логов, представленный в виде таблицы.
	</li>
	<li>
		Внизу располагается статус бар, отображающий количество элементов списка, в тч отфильтрованных, а так же, текущий статус захвата логов.
	</li>
	<li>
		Опциональное окно детальной информации о событии.
	</li>
</ol><p>
	Логвьювер поддерживает докинг форм, следовательно может быть как плавающим окном, так и быть закреплен в любом удобном для вас месте в <strong>IDE</strong>.
</p>

<p>
	<span style="font-size:24px;"><strong>Отправка сообщений в лог.</strong></span>
</p>

<p style="text-align: justify;">
	Для начала работы выберите устройство в верхнем тулбаре (в нашем случае это <strong>Redmi Note 7</strong>) и нажмите кнопку старта захвата логов. Список будет постепенно наполняться записями. Для просмотра детальной информации о записи можно два раза кликнуть по самой записи в списке, либо выделить запись и нажать соответствующую кнопку в левом тулбаре.
</p>

<p style="text-align: justify;">
	Теперь создадим тестовое приложение, запустим его и отправим несколько записей в лог.<br>
	Для этого воспользуемся кодом из предыдущей статьи:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3537_9" style=""><span class="pln">uses
  System.SysUtils, FGX.Application, FGX.Dialogs, FGX.Log;

procedure TFormMain.fgButton1Tap(Sender: TObject);
begin
  TfgLog.Debug('Hello from TfgLog.Debug');
end;

procedure TFormMain.fgButton2Tap(Sender: TObject);
begin
  TfgLog.Info('Hello from TfgLog.Info');
end;</span></pre>

<p style="text-align: justify;">
	Наши сообщения отправлены и встаёт вопрос, как их найти среди огромного списка других сообщений. <br>
	Есть два варианта решения задачи:
</p>

<ol><li style="text-align: justify;">
		Изначально собирать сообщения только от нашего приложения, выбрав его перед захватом лога в верхнем тулбаре (в этом случае количество попадаемых в лог сообщений значительно сократится, но так можно пропустить важные сообщения, в т.ч. падения, от самой <strong>Android </strong>и/или её компонентов)
	</li>
	<li style="text-align: justify;">
		Воспользоваться фильтрацией, которая представлена в логвьювере в двух вариантах: быстром и расширенном.
	</li>
</ol><p style="text-align: justify;">
	Воспользуемся вариантом 2.
</p>

<p style="text-align: justify;">
	<span style="font-size:24px;"><strong>Варианты фильтрации списка событий.</strong></span>
</p>

<p style="text-align: justify;">
	Окно быстрой фильтрации находится в правой части верхнего тулбара (вариант по-умолчанию):
</p>

<p style="text-align: center;">
	<img alt="2.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2825" data-unique="uil1uingy" style="height: auto;" width="968" src="https://forum.fgx-native.com/uploads/monthly_2021_09/2.png.8ae265d816f25728b9703019941607c5.png" loading="lazy" height="135.52"></p>

<p style="text-align: justify;">
	Фильтрация осуществляется по всем столбцам списка без учёта регистра. Можно указывать несколько значений, разделённых пробелом. В итоговую выборку попадут события, которые соответствуют хотя бы одной подчасти фильтра (<strong>OR</strong>).
</p>

<p style="text-align: justify;">
	Для включения расширенного фильтра воспользуйтесь кнопкой на левом тулбаре. После включения верхний тулбар приобретёт следующий вид:
</p>

<p style="text-align: center;">
	<img alt="3.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2826" data-unique="nko099krq" style="height: auto;" width="968" src="https://forum.fgx-native.com/uploads/monthly_2021_09/3.png.6bcb7ea33646e0eba9e1e9dfd0e74d67.png" loading="lazy" height="135.52"></p>

<p style="text-align: justify;">
	Каждое окно ввода "привязано" к одноименному столбцу списка. В итоговую выборку попадут события, которые соответствуют всем заполненным окнам фильтра (<b>AND</b>).
</p>

<p style="text-align: justify;">
	<span style="font-size:24px;"><strong>Просмотр событий.</strong></span>
</p>

<p style="text-align: justify;">
	Итак, чтобы найти отправленные ранее сообщения, для начала укажем в окне быстрого фильтра слово "<strong>FGX</strong>" - этим тегом помечаются все сообщения, отправленные с помощью <strong>TfgLog</strong>. Как видно на скриншоте, в списке остались только относящиеся к <strong>FGX </strong>записи, среди которых не составит труда увидеть и искомые записи.
</p>

<p style="text-align: center;">
	<img alt="4.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2829" data-unique="3zty7ucqz" style="height: auto;" width="968" src="https://forum.fgx-native.com/uploads/monthly_2021_09/4.png.8d2184e7679f910988b936a6f834ccb2.png" loading="lazy" height="551.76"></p>

<p>
	Альтернативный вариант - поиск по<strong> Process Id</strong> (<strong>PID</strong>), который можно узнать из окна <strong>IDE Events </strong>(в нашем случае <strong>25505</strong>)
</p>

<p style="text-align: center;">
	<img alt="5.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2833" data-unique="831n1e0u6" style="height: auto;" width="698" src="https://forum.fgx-native.com/uploads/monthly_2021_09/5.png.d9580e981dbcbf1aeea460ee38ffbab0.png" loading="lazy" height="216.38"></p>

<p>
	В результате значений будет уже больше, т.к. в итоговую выборку попадают все сообщения, относящиеся к процессу, а не только сообщения, отправленные непосредственно <strong>FGX</strong>. Но, даже так, найти наши записи не составляет особого труда.
</p>

<p style="text-align: center;">
	<img alt="6.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2834" data-unique="as8mx1jlh" style="height: auto;" width="968" src="https://forum.fgx-native.com/uploads/monthly_2021_09/6.png.40389d76d59071ae6908602f927f2124.png" loading="lazy" height="551.76"></p>

<p>
	Либо вы можете отфильтровать список непосредственно по части отправленной записи:
</p>

<p style="text-align: center;">
	<img alt="7.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2835" data-unique="ph8q1t7rf" style="height: auto;" width="968" src="https://forum.fgx-native.com/uploads/monthly_2021_09/7.png.46dfb6112dd6ccb9e4cfa1017b08a8dd.png" loading="lazy" height="551.76"></p>

<p>
	Состав и количество фильтров огранивается только вашей фантазией.
</p>

<p>
	 
</p>

<p>
	Надеемся, что вам понравится опыт работы с новым средством просмотра логов <strong>FGX Android Log Viewer</strong>. 
</p>

<p>
	Спасибо за внимание и удачной отладки!
</p>

<p>
	 
</p>

<p>
	 
</p>

<p>
	 
</p>
]]></description><guid isPermaLink="false">34</guid><pubDate>Fri, 03 Sep 2021 22:37:00 +0000</pubDate></item><item><title>&#x41D;&#x43E;&#x432;&#x44B;&#x435; &#x432;&#x43E;&#x437;&#x43C;&#x43E;&#x436;&#x43D;&#x43E;&#x441;&#x442;&#x438; TfgBitmap</title><link>https://forum.fgx-native.com/blogs/entry/30-%D0%BD%D0%BE%D0%B2%D1%8B%D0%B5-%D0%B2%D0%BE%D0%B7%D0%BC%D0%BE%D0%B6%D0%BD%D0%BE%D1%81%D1%82%D0%B8-tfgbitmap/</link><description><![CDATA[<p>
	Здравствуйте.
</p>

<p>
	Еще одним нововведением в релизе <strong>1.11.2.0</strong>, помимо <strong>TfgPopup</strong>,<strong> </strong>является работа с пикселями ("сырыми данными") <strong>TfgBitmap</strong>. Доступ к пикселям открывает практически неограниченные возможности для обработки и анализа изображений. Так же в новом релизе будет добавлена возможность поворота изображения.
</p>

<p>
	 
</p>

<p>
	<span style="font-size:24px;"><strong>Воможность работы с пикселями TfgBitmap.</strong></span>
</p>

<p>
	<span style="font-size:20px;">Общие сведения.</span>
</p>

<p>
	Обращение к сырым данным возможно только между парными вызовами <strong>TfgBitmap.MapData</strong> и <strong>TfgBitmap.UnmapData</strong>, которые могут быть знакомы пользователям <strong>FMX</strong>. Однако, важным отличием от <strong>FMX</strong>, является отсутствие уровня доступа (только чтение/только запись/чтение и запись). Это сделано с целью ускорения доступа, т. к. работа осуществляется непосредственно с данными нативного изображения без создания промежуточного буфера.
</p>

<p>
	В результате вызова <strong>TfgBitmap.MapData </strong>вы получаете<strong> </strong>интерфейс <strong>IFGXBitmapData </strong>(более подробно рассмотрен ниже), который предоставляет доступ к пикселям изображения.
</p>

<p>
	<span style="color:#c0392b;"><strong>Важно!</strong></span> Актуальность объекта <strong>IFGXBitmapData </strong>гарантирована только между вызовами <strong>TfgBitmap.MapData</strong> и <strong>TfgBitmap.UnmapData</strong>, т.к. используется "натуральный" интерфейс без подсчета ссылок.
</p>

<p>
	<span style="color:#c0392b;"><strong>Важно!</strong></span> Во время доступа к сырым данным<strong> </strong>операции по изменению<strong> TfgBitmap </strong>запрещены (например загрузка из различных источников, изменение размера, масштаба, поворота и тд).
</p>

<p>
	<span style="font-size:20px;">Типичный пример работы с сырыми данными изображения:</span>
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_1024_7" style=""><span class="pln">var
  LBitmapData: IFGXBitmapData;
begin  
  if LBitmap.MapData(LBitmapData) then
    try
      // Работа с пикселями изображения.
    finally
      LBitmap.UnmapData;
    end;
end;</span></pre>

<p>
	<span style="color:#c0392b;"><strong>Важно!</strong></span> Всегда проверяйте результат выполнения <strong>TfgBitmap.MapData </strong>во избежание непредвиденных последствий. Повторный вызов <strong>TfgBitmap.MapData </strong>для уже спроецированных данных вернет ложь.
</p>

<p>
	<span style="font-size:20px;">Интерфейс IFGXBitmapData.</span>
</p>

<p>
	Интерфейс <strong>IFGXBitmapData </strong>предоставляет информацию об изображении (<strong>Info</strong>, <strong>Width</strong>, <strong>Height</strong>), а так же позволяет манипулировать пикселями изображения (<strong>RawData, Scanlines, Pixels, Colors</strong>).
</p>

<p>
	Информация о битмапе <strong>TfgBitmapInfo</strong>:
</p>

<ol><li>
		<strong>BitsPerPixel </strong>— количество бит на один пиксель изображения. К примеру, для одного из самых распространенных вариантов <strong>ARGB, </strong>этот параметр будет равен 32-ум битам.
	</li>
	<li>
		<strong>BytesPerRow </strong>— количество байт на одну строку изображения. Обычно это <strong>Width </strong>* <strong>BitsPerPixel</strong>, но, в случае применения выравнивания для ускорения доступа к данным, значение может быть иным.
	</li>
	<li>
		<strong>PixelFormat</strong> — формат пикселя изображения. В отличии от фиксированного формата <strong>ARGB</strong> присущего стандартному типу <strong>TAlphaColor</strong>, нативные изображения могут иметь различный состав и порядок следования цветовых компонентов. Возможные комбинации этих параметров отражает тип <strong> TfgBitmapPixelFormat.</strong>
		<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8757_14" style=""><span class="pln">TfgBitmapPixelFormat = (Unknown, Alpha, Gray, ARGB, RGBA, RGB, RGB24);</span></pre>
	</li>
	<li>
		<strong>IsAlphaPremultiplied</strong> — флаг, показывающий являются ли компоненты пикселя предварительно помноженными на компоненту прозрачности.
	</li>
</ol><p>
	Интерфейс <strong>IFGXBitmapData </strong>содержит несколько вариантов доступа к самим данным, которые отличаются по степени абстракции:
</p>

<ol><li>
		<strong>RawData </strong>— самый низкий уровень. Возвращает указатель на начало данных. Размер данных можно узнать из свойства <strong>RawDataSize</strong>.
	</li>
	<li>
		<strong>Scanlines</strong> — указатель на переданную в аргументе строку. Размер данных строки в байтах можно получить из <strong>Info.BytesPerRow</strong>, количество пикселей в строке — <strong>Width</strong>.
	</li>
	<li>
		<strong>Pixels </strong>— указатель на пиксель. В аргументах передаются координаты пикселя. Размер пикселя в битах можно получить из <strong>Info.BitsPerPixel</strong>.
	</li>
	<li>
		<strong>Colors</strong> — цвет пикселя в стандартном формате <strong>TAlphaColor</strong>. В аргументах передаются координаты пикселя.
	</li>
</ol><p>
	Как правило, для достижения максимальной скорости при последовательном сканировании пикселей изображения, вместо индексного доступа (<strong>Pixels, Colors</strong>) используют инкрементный перебор начиная с некой точки отсчёта (начало изображения <strong>RawData</strong>, начало определенной строки<strong> Scanlines[Y]</strong>, определенный пиксель<strong> Pixelsх[X, Y]</strong>)<strong> </strong>. В этом случае вы получаете указатель, вместо привычного <strong>TAlphaColor</strong>.  Для преобразования данных по указателю в тип <strong>TAlphaColor </strong>вам могут пригодиться готовые варианты для конвератции, которые находятся в хэлпере <strong>TAlphaColorHelper </strong>из модуля <strong>FGX.Types.Color</strong>.
</p>

<p>
	Для формирования <strong>TAlphaColor </strong>из сырых данных используйте перегруженный конструктор:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8534_12" style=""><span class="pln">constructor Create(const APixel: PByte; const APixelFormat: TfgBitmapPixelFormat; const AIsAlphaPremultiplied: Boolean); overload;</span></pre>

<p>
	Для обратной операции подойдет метод:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8534_16" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Записывает текущий цвет по адресу </span><span class="tag">&lt;c&gt;</span><span class="pln">APixel</span><span class="tag">&lt;/c&gt;</span><span class="pln"> с учетом опций </span><span class="tag">&lt;c&gt;</span><span class="pln">APixelFormat</span><span class="tag">&lt;/c&gt;</span><span class="pln"> и </span><span class="tag">&lt;c&gt;</span><span class="pln">AIsAlphaPremultiplied</span><span class="tag">&lt;/c&gt;</span><span class="pln">.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
procedure ToPixel(const APixel: PByte; const APixelFormat: TfgBitmapPixelFormat; const AIsAlphaPremultiplied: Boolean);</span></pre>

<p>
	<span style="font-size:20px;">Реальный пример работы с сырыми данными.</span>
</p>

<p>
	Ниже приведен кусок кода из нового демонстрационного примера<strong> "Графика" -&gt; "TfgBitmap - работа с "сырыми" данными"</strong> в котором<strong> </strong>изображение преобразуется из цветного в оттенки серого.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8757_16" style=""><span class="pln">uses
  FGX.Types.Color, FGX.Canvas.Types, FGX.Canvas.Types, FGX.Assets, FGX.Assets.BitmapSet;

procedure TFormMain.fgButton1Tap(Sender: TObject);
var
  LBitmapSet: TfgAssetBitmapSet;
  LBitmap: TfgBitmap;
  LBitmapData: IFGXBitmapData;
  I, J: Integer;
begin
  if not TfgAssetsManager.Current.Find</span><span class="tag">&lt;TfgAssetBitmapSet&gt;</span><span class="pln">('Image', LBitmapSet) then
    Exit;
  LBitmap := LBitmapSet.GetBitmap;
  if LBitmap.MapData(TfgBitmapDataAccessMode.ReadWrite, LBitmapData) then
    try
      for J := 0 to LBitmap.Height - 1 do
        for I := 0 to LBitmap.Width - 1 do
          LBitmapData.Colors[I, J] := LBitmapData.Colors[I, J].ToGrayscale;
    finally
      LBitmap.UnmapData;
    end;
  fgPaintBox1.Invalidate;
end;</span></pre>

<p>
	<strong><span style="font-size:24px;">Повороты изображения.</span></strong>
</p>

<p>
	Благодаря добавлению работы с сырыми данными появилась возможность с легкостью вращать изображения.
</p>

<p>
	Поворот осуществляется с помощью метода <strong>TfgBitmap.Rotate:</strong>
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8534_20" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Поворачивает изображение на указанный угол.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
procedure Rotate(const AAngle: TfgRotation);</span></pre>

<p>
	В качестве аргумента передается одно из предустановленных значений угла поворота.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_8534_22" style=""><span class="pln">TfgRotation = (Rotation0 = 0, Rotation90 = 90, Rotation180 = 180, Rotation270 = 270);</span></pre>

<p>
	Поворот осуществляется по часовой стрелке.
</p>

<p>
	 
</p>

<p>
	Благодарим за внимание и приятного коддинга <span class="ipsEmoji">🙂</span>.
</p>
]]></description><guid isPermaLink="false">30</guid><pubDate>Wed, 16 Jun 2021 18:48:27 +0000</pubDate></item><item><title>&#x412;&#x44B;&#x43F;&#x430;&#x434;&#x430;&#x44E;&#x449;&#x438;&#x435; &#x43E;&#x43A;&#x43D;&#x430; TfgPopup</title><link>https://forum.fgx-native.com/blogs/entry/29-%D0%B2%D1%8B%D0%BF%D0%B0%D0%B4%D0%B0%D1%8E%D1%89%D0%B8%D0%B5-%D0%BE%D0%BA%D0%BD%D0%B0-tfgpopup/</link><description><![CDATA[<p>
	Доброго дня!
</p>

<p>
	В ближайшем релизе <strong>1.11.2.0 </strong>всех нас ждет появление поддержки выпадающих окон <strong>TfgPopup</strong>. Если вам необходимо отобразить содержимое в виде выпадающего окна, то эта возможность непременно вам пригодится.
</p>

<p>
	<strong><span style="font-size:22px;">Создание</span></strong>
</p>

<p>
	В качестве содержимого выпадающего окна можно использовать как любой визуальный компонент так и форму. Удобнее всего использовать форму, поскольку она позволяет создать содержимое выпадающего окна прямо в дизайнере. При создании формы важно указать:
</p>

<ul><li>
		Отключить полноэкранный режим формы <strong>TfgForm.FullScreen = False</strong>.
	</li>
	<li>
		Опционально сделать фон прозрачным через <strong>TfgForm.Transparent = True</strong><span id="cke_bm_1781C" style="display: none;"> </span>.
	</li>
</ul><p>
	В качестве начинки окна, я сделал форму с <strong>TfgCollectionView</strong>, используемым для отображения содержимого 
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="2510" href="https://forum.fgx-native.com/uploads/monthly_2021_06/image.png.6e31595d4c05194ed19c7d30f3abf38c.png" rel=""><img alt="image.png" class="ipsImage ipsImage_thumbnailed" data-fileid="2510" data-unique="89odgj2qh" style="height: auto;" width="774" src="https://forum.fgx-native.com/uploads/monthly_2021_06/image.thumb.png.2938daa1b809d9ea20759e5def2c20e9.png" loading="lazy" height="743.04"></a>
</p>

<p>
	Чтобы создать выпадающее окно нужно обязательно иметь содержимое, которое вы планируете показать в этом выпадающем окне. Создание выполняется через фабрику <strong>FGX.Popup.TfgPopupFactory</strong>, как и тосты, пикеры, диалоги и тд.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5789_9" style=""><span class="pln">var
  FPopup: TfgPopup;
  FPopupContent: TFrameList;

FPopupContent := TFrameList.Create(nil);
FPopup := TfgPopupFactory.CreatePopup(FPopupContent);</span></pre>

<p>
	После создания <strong>TfgPopup</strong> становится владельцем вашего содержимого. Это значит, что содержимое будет уничтожено, как только <strong>TfgPopup</strong> будет удален. Если вы хотите сами контролировать время жизни содержимого, вы можете передать вторым параметром значение <strong>False</strong>. В этом случае, после уничтожения <strong>TfgPopup</strong>, ваше содержимое останется жить.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5789_12" style=""><span class="pln">FPopup := TfgPopupFactory.CreatePopup(FPopupContent, False);</span></pre>

<p>
	После создания необходимо указать размер выпадающего окна при помощи свойства <strong>TfgPopup.Size</strong>. Например, если выпадающее окно прикреплено к кнопке. то имеет смысл в качестве ширины брать ширину кнопки:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5789_16" style=""><span class="pln">FPopup.Size := TSizeF.Create(fgButton1.Width, 200);</span></pre>

<p>
	<strong><span style="font-size:22px;">Отображение</span></strong>
</p>

<p>
	Для отображения выпадающего окна существует два одноименных метода <strong>TfgPopup.DropDown</strong>, оба которых привязывают отображение окна к указанному компоненту.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5789_27" style=""><span class="pln">    /// </span><span class="tag">&lt;summary&gt;</span><span class="pln">
    ///   Открывает выпадающее окно, прикрепленное к указанному компоненту </span><span class="tag">&lt;c&gt;</span><span class="pln">AAnchor</span><span class="tag">&lt;/c&gt;</span><span class="pln"> со смещением </span><span class="tag">&lt;c&gt;</span><span class="pln">AOffset</span><span class="tag">&lt;/c&gt;</span><span class="pln">.
    /// </span><span class="tag">&lt;/summary&gt;</span><span class="pln">
    procedure DropDown(const AAnchor: TfgControl; const AOffset: TPointF); overload; virtual; abstract;

    /// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Открывает выпадающее окно, прикрепленное к указанному компоненту </span><span class="tag">&lt;c&gt;</span><span class="pln">AAnchor</span><span class="tag">&lt;/c&gt;</span><span class="pln">.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
    procedure DropDown(const AAnchor: TfgControl); overload;</span></pre>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5789_18" style=""><span class="pln">FPopup.DropDown(fgButton1);</span></pre>

<p>
	Если вам необходимо выполнить отображение выпадающего окна со смещением, то вы можете передать это смещение вторым параметром:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5789_21" style=""><span class="pln">FPopup.DropDown(fgButton1, TPointF.Create(0, 8));</span></pre>

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

<p>
	Для закрытия окна используйте метод <strong>Close</strong>.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5789_29" style=""><span class="pln">    /// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Закрывает выпадающее окно.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
    procedure Close; virtual; abstract;</span></pre>

<p>
	<strong><span style="font-size:22px;">Настройка внешнего вида</span></strong>
</p>

<p>
	По умолчанию <strong>TfgPopup </strong>выглядит, как <strong>TfgCardPanel</strong> с тенью и рамкой. Однако, если вы хотите сделать свой внешний вид окна, то вы можете отключить  отображение по умолчанию через свойство <strong>TfgPopup.IsTransparent</strong>. В этом случае содержимое будет отображено прямо под привязанным компонентом.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5789_23" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Прозрачное выпадающее окно или нет?</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
property IsTransparent: Boolean read FIsTransparent write SetIsTransparent;</span></pre>

<p>
	Если вы используете в своих приложениях темы, то вы можете использовать темы и для содержимого выпадающего окна. Для этого необходимо указать название темы в свойстве <strong>TfgPopup.ThemeName</strong>. Таким образом можно добавить поддержку темной темы и детальнее настроить внешний вид попапов.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5789_25" style=""><span class="pln">/// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Название темы, используемой для содержимого выпадающего окна.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
property ThemeName: TfgThemeName read FThemeName write SetThemeName;</span></pre>

<p>
	<video class="ipsEmbeddedVideo" controls="" data-fileid="2512" data-unique="vgk66jmnn" id="ips_uid_9167_6" src="https://forum.fgx-native.com/uploads/monthly_2021_06/ios.mp4.fd36500b55a93eee332c19671a08f90a.mp4" style="max-width:200px" data-controller="core.global.core.embeddedvideo" preload="metadata"><source type="video/mp4" src="https://forum.fgx-native.com/uploads/monthly_2021_06/ios.mp4.fd36500b55a93eee332c19671a08f90a.mp4"><a class="ipsAttachLink" data-fileext="mp4" data-fileid="2512" href="https://forum.fgx-native.com/applications/core/interface/file/attachment.php?id=2512" rel="">ios.mp4</a>
	</source></video><video class="ipsEmbeddedVideo" controls="" data-fileid="2514" data-unique="b4pijgjfs" style="max-width:200px" data-controller="core.global.core.embeddedvideo" preload="metadata"><source type="video/mp4" src="https://forum.fgx-native.com/uploads/monthly_2021_06/android.mp4.b3ebf7ebaaa2ce6bf59bfc4b05e87cdf.mp4"><a class="ipsAttachLink" href="https://forum.fgx-native.com/applications/core/interface/file/attachment.php?id=2514" data-fileid="2514" data-fileext="mp4" rel="">android.mp4</a>
	</source></video><span id="cke_bm_5962C" style="display: none;"> </span>
</p>

<p>
	<span style="font-size:22px;"><strong>События</strong></span>
</p>

<p>
	В <strong>TfgPopup </strong>поддерживается два типа событий, <strong>OnOpened </strong>и <strong>OnClosed</strong>, вызываемые при открытии и закрытии выпадающего окна соответственно. Так же мы предлагаем две версии каждого события для использования совместно с анонимными функциями и событиями.
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_5789_31" style=""><span class="pln">    /// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Вызывается, когда выпадающее окно отображается на экране.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
    property OnOpened: TNotifyEvent read FOnOpened write FOnOpened;

    /// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Вызывается, когда выпадающее окно отображается на экране.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
    property OnOpenedCallback: TfgCallback read FOnOpenedCallback write FOnOpenedCallback;

    /// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Вызывается, когда выпадающее окно скрывается с экрана.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
    property OnClosed: TNotifyEvent read FOnClosed write FOnClosed;

    /// </span><span class="tag">&lt;summary&gt;</span><span class="pln">Вызывается, когда выпадающее окно скрывается с экрана.</span><span class="tag">&lt;/summary&gt;</span><span class="pln">
    property OnClosedCallback: TfgCallback read FOnClosedCallback write FOnClosedCallback;</span></pre>

<p>
	 
</p>
]]></description><guid isPermaLink="false">29</guid><pubDate>Thu, 10 Jun 2021 21:44:00 +0000</pubDate></item></channel></rss>
