Everything posted by Yaroslav Brovin
-
Анонс 1.13.3.0 и GooglePay
Там будет просто TObject. type {$IFDEF ANDROID} TfgAndroidIntent = JIntent; {$ELSE} TfgAndroidIntent = type TObject; {$ENDIF}
-
Анонс 1.13.3.0 и GooglePay
Поздравляем вас с наступающим Новым годом! Мы благодарим вас за доверие и спасибо, что в этом году вы были с нами. В течении всего года мы прислушивались к вашим пожеланиям и старались сделать все возможное, чтобы наш продукт раз от раза становился удобнее и мощнее. В ближайшее время выйдет новый релиз 1.13.3.0. Традиционно в этом релизе вас ждет несколько полезных новинок и улучшений. GooglePay - TfgGooglePayClient Первая новинка - это новый компонент TfgGooglePayClient оплаты покупок в вашем приложении через платежную систему GooglePay. Настройка Для того, чтобы добавить возможность оплаты покупок в вашем приложении, вам необходимо выполнить первичную настройку на стороне Google - https://developers.google.com/pay/api/web/guides/setup?hl=ru В результате этой настройки вы получите идентификатор продавца Google - MerchantId. Настройка приложения FGX Native Для того, чтобы иметь возможность использовать GooglePay в FGX Native приложении, необходимо добавить в манифест Android приложения следующие строчки в любое место внутрь тега <application>: 1. Версию GooglePlay сервисов. ТОЛЬКО, если вы не используете "Firebase PushNotification", Maps или AdMob. <meta-data android:name="com.google.android.gms.version" android:value="12451000" /> 2. Включить доступ приложения к кошельку: <meta-data android:name="com.google.android.gms.wallet.api.enabled" android:value="true" /> 3. Указать идентификатор продавца в свойстве "TfgGooglePayClient.MerchantName", полученный на предыдущем шаге. Проверка возможности оплаты через GooglePay GooglePay может быть недоступен на устройстве пользователя, поэтому, перед инициированием процесса оплаты, необходимо узнать текущий статус. Это можно сделать через асинхронный метод "TfgGooglePayClient.IsReadyToPayAsync": uses FGX.Payments.GooglePay.Types; if gpClient.IsSupported then gpClient.IsReadyToPayAsync(False, procedure (const AStatus: TfgGooglePayStatus) begin // Отображаем/Скрываем кнопку оплаты через GooglePay btnPay.Visible := AStatus = TfgGooglePayStatus.Available; end); Оплата через GooglePay Для инициации оплаты необходимо заполнить информацию о проводимой транзакции и воспользоваться асинхронным методом оплаты "TfgGooglePayClient.PayAsync". Минимально необходимая информация в транзакции - это код валюты и цена. procedure TFormMain.btnPayTap(Sender: TObject); var TransactionInfo: TfgTransactionInfo; begin TransactionInfo := TfgTransactionInfo.Create; try { Информация о покупке } TransactionInfo.SetCurrencyCode('RUB') .SetTotalPrice(100.12); gpClient.PayAsync(TransactionInfo); finally TransactionInfo.Free; end; end; Описание полей транзакции, смотрите в исходном коде или на сайте GooglePay. По результатам обработки запроса, будет вызвано одно из событий: "OnPaymentError" - в ходе оплаты произошла ошибка. "OnPaymentComplete" - пользователь выполнил оплату, токен для проведения оплаты передается в параметрах события. "OnPaymentCancelled" - пользователь отменил оплату. Если платеж прошел успешно, то в событии OnPaymentComplete будет передан JSON ответ, из которого вы можете извлечь необходимую информацию согласно документации: procedure TFormMain.gpClientPaymentComplete(Sender: TObject; const AResponse: TJSONValue); begin mLog.Lines.Add(Format('Completed: AResponse="%s"', [AResponse.Format])); end; После извлечения платежного токена, вам необходимо провести транзакцию на вашем сервере через ваш банк. Если же оплата по каким-то причинам не прошла, вы можете получить информацию об ошибке через событие OnPaymentError. В параметрах передается код ошибки и ее описание. Обратите внимание, что данный код и описание выдается самой системой. Поэтому иногда описание может отсутствовать или содержать неполную информацию (это нормально). Диагностика и отладка Все детальные ошибки настройки интеграции с GooglePay обычно выводятся в лог. Именно там можно узнать, почему платеж не запускается или не проходит. Обратите внимание, что чаще всего ошибки в лог попадают не от имени приложения, а от системы. Поэтому при поиске проблем, нужно это учитывать (не фильтровать сообщения вашим приложением). Все свойства компонента полностью соответствуют оберткам в документации Google Pay. Компонент формирует JSON запрос, который отправляется в нативное API. Вы можете проверить корректность формирования JSON запроса через лог. Для этого необходимо включить расширенное логирование в вашем приложении: TfgLog.MinimumLevel := TfgLogLevel.Trace; Полезные ссылки: Руководство по использованию бренда GooglePay. Советы UX по интеграции GooglePay. Чек лист по настройке GooglePay. Диагностика проблем. TfgApplicationEvents При разработке Android приложений и при использовании Android API очень часто требуется отправить запрос другим активностям и получить от них результат. Раньше это решалось через подписку на широковещательные сообщения FGX.Platform.Android.TfgActivityResultMessage и TfgActivityNewIntentMessage и требовало написать следующий код: constructor TFormMain.Create(AOwner: TComponent); begin inherited; TMessageManager.DefaultManager.SubscribeToMessage(TfgActivityResultMessage, ActivityResultHandler); TMessageManager.DefaultManager.SubscribeToMessage(TfgActivityNewIntentMessage, ActivityNewIntentHandler); end; destructor TFormMain.Destroy; begin TMessageManager.DefaultManager.Unsubscribe(TfgActivityNewIntentMessage, ActivityNewIntentHandler); TMessageManager.DefaultManager.Unsubscribe(TfgActivityResultMessage, ActivityResultHandler); inherited; end; procedure TFormMain.ActivityNewIntentHandler(const Sender: TObject; const M: TMessage); var Message: TfgActivityNewIntentMessage; begin TfgAssert.IsClass(M, TfgActivityNewIntentMessage); Message := TfgActivityNewIntentMessage(M); TfgToast.Show(Format('Получен новый интент: intent=%s', [JStringToString(Message.Value.toString)])); end; procedure TFormMain.ActivityResultHandler(const Sender: TObject; const M: TMessage); var Message: TfgActivityResultMessage; begin TfgAssert.IsClass(M, TfgActivityResultMessage); Message := TfgActivityResultMessage(M); // Intent is available in Message.Data TfgToast.Show(Format('Получен результат из другого приложения: requestCode=%d, resultCode=%d', [Message.RequestCode, Message.ResultCode])); end; Сейчас же мы добавили два новых события "TfgApplicationEvents.OnActivityResult" и "TfgApplicationEvents.OnActivityNewIntent", которые позволяют значительно сократить код и сконцентрироваться только на реализации. procedure TFormMain.fgApplicationEvents1ActivityNewIntent(Sender: TObject; const AIntent: TfgAndroidIntent); begin {$IFDEF ANDROID} TfgToast.Show(Format('Получен новый интент: intent=%s', [JStringToString(AIntent.toString)])); {$ENDIF} end; procedure TFormMain.fgApplicationEvents1ActivityResult(Sender: TObject; const ARequestCode, AResultCode: Integer; const AIntent: TfgAndroidIntent); begin {$IFDEF ANDROID} TfgToast.Show(Format('Получен результат из другого приложения: requestCode=%d, resultCode=%d', [ARequestCode, AResultCode])); {$ENDIF} end; TfgCollectionView Мы провели улучшение контроллера выделения элементов и предоставили больше гибкости в точной настройке поведения. Раньше при режиме выделения "TfgCollectionViewSelectionMode = SingleSelect" мы не позволяли сбросить выделение элемента повторным нажатием. Это было сделано для возможности реализации меню с отображением текущего выбранного раздела. Однако, для некоторых пользователей такое поведение компонента было нежелательным. Теперь мы предлагаем вам самостоятельно решить, как должно работать выделение при помощи новых событий "TfgCollectionView.OnItemCanSelect" и "TfgCollectionView.OnItemCanDeselect". Данные события вызываются непосредственно до момента установки или снятия выделения и позволяют отменить действие при помощи передаваемого параметра AAllow. Так же мы исправили ряд ошибок выделения на платформе iOS, так что теперь процесс выделения работает одинаково на всех платформах. ВАЖНО! Теперь по умолчанию компонент позволяет сбросить выделение элемента в режиме SingleSelect. Заключении Желаем вам свершения всего задуманного, интересных проектов и амбициозных целей! Спасибо, что вы с нами!
-
1.13.2.1 Русский
Добрый вечер, Как я уже говорил, я не смог воспроизвести проблему. Пробовал разные проекты, все на месте, там где хит тест не был указан, он и не загружается. Где был указан, все так же и загрузилось. Я специально грузил большие проекты, где много компонентов, чтобы поймать этот кейс. Но все штатно. Опять же, если бы вы мне дали проект или показали, где видно, что свойство слетает, то можно было бы предметно поговорить. В 1.13.2.0 был изменен подход в обработки жеста OnTap, чтобы поправить проблему не консистентности срабатывания жестов OnTap и OnLongTap. Проблема в том, что в Андроиде есть жесты Tap, DoubleTap, LongTap и др, а есть понятие Click/LongClick. Жест Tap можно представить в виде следующих шагов: Пользователь опустил палец на экран Через короткое время, пользователь поднял палец с экрана. Если через короткий промежуток времени пользователь не начал делать второе касание, это Tap, если начал, то это возможно Double Tap. Click же состоит из: Пользователь опустил палец на экран Пользователь может перемещать палец по экрану (Время не ограничено). Если пользователь поднял палец в рамках действия компонента, на который он опустил палец, то срабатывает Click. То есть основные отличия - это: Время жеста Возможность перемещения пальца между опусканием и поднятием пальца Все усугубляется тем, что Click никак не коррелирует с жестами Tap, DoubleTap, LongTap. Это значит, что если срабатывает Click, то спокойно может сработать любой жест Tap. В 1.13.2.0 для кастомных компонентов (TfgImage, TfgLayout и тд. То есть те, что не имеют логики обработки касаний по умолчанию) я сделал полноценные жесты, избавившись от Click. И теперь у них полноценно работают жесты. Однако, с учетом того, что штатные компоненты типа кнопки, чек боксов, полей ввода и тд, построены именно на использовании Click полноценно сделать поддержку и жестов и Click не получится в виду ограничений самой реализации системы обработки жестов, касаний в Андроиде. Поэтому для таких компонентов используется эмуляция жеста OnTap на базе Click. Именно с учетом отличий, я вас и спрашивал на каких компонентах для вас это важно. Поскольку первоначально речь шла об TfgImage, то для него, я как раз включил новую реализацию жестов (без эмуляции на базе Click). Кнопка является отдельным компонентом, где отказывать от клика нельзя иначе будет нарушена привычная логика обработки нажатия, поэтому на ней и идет микс жестов, которые могут конфликтовать. Есть только один вариант относительно нормального решения - это ввод нового события OnClick дополнительно к OnTap. Именно новое событие OnClick будет работать, как раньше работал OnTap, а событие OnTap будет полноценным тап жестов, как это принято на всех платформах в принципе. Жест Tap станет опциональным и добавится к множеству GestureKinds. В этом случае все будет более менее предсказуемым с точки зрения работы жестов. Но, как вы понимаете, это ломает совместимость. Потому что OnTap - это базовый жест, который использует каждый. Поэтому введение OnClick потребует от всех клиентов перелопатить все проекты и перекинуть обработчики на OnClick. Это был звук, который работал на Click. В демке пустая форма. Ничего больше нет на форме.
-
1.13.2.1 English
Download: The distributive is available by request only. Release date: 20 December 2021 Bug Fixes 🐛 The OnTap and OnLongTap events didn't work for TfgImage and TfgProgressBar (Android).
-
1.13.2.1 Русский
Скачать: Релиз доступен только по запросу. Дата релиза: 20 декабря 2021 Исправление ошибок 🐛 У компонентов TfgImage и TfgProgressBar не работали корректно события OnTap и OnLongTap (Android).
-
Request. Native date and timec picker for android
Hello Sally, We have already this helper. Look at the FGX.Picker.Time.TfgPickerTimeFactory and FGX.Picker.Date.TfgPickerDateFactory.
-
1.13.2.0 Русский
Хорошо, Проверю еще разок. Понял. Как выясню, выпущу хотфикс.
-
1.13.2.0 Русский
Проверил, В это я с трудом верю. Последнее задание значения False по умолчанию было сделано 2018.07.14, о чем свидетельствует лог в гите: Так же при открытии старого проекта, я не вижу, чтобы слетало значение HitTest у TfgImage. Если есть шаги для воспроизведения, буду рад. Подтверждаю. Это касается TfgImage и еще я обнаружил такую же проблему у TfgProgressBar. На каком компоненте наблюдается такое поведение?
-
1.13.2.0 Русский
Сейчас проверю...
-
1.13.2.0 English
Download: The distributive is available by request only. Release date: 21 November 2021 New ✨ TfgCamera The new implementation of TfgCamera for iOS was added. TfgCameraPreview The new implementation of TfgCameraPreview for iOS was added. TfgBarcodeScanner The new implementation of TfgBarcodeScanner for iOS was added. Improvements 🙌 TfgCamera Added the ability to request the permissions required for the camera to work using the component itself TfgCamera.RequestPermission. Checking the current status of permissions TfgCamera.AuthorizationStatus. Typical use case: procedure TFormMain.fgFormCreate(Sender: TObject); begin fgCamera1.RequestPermission; end; procedure TFormMain.CameraPermissionRequest(const APermissionInfo: TfgPermissionInfo); begin if APermissionInfo.CheckResult = TfgPermissionCheckResult.Granted then fgCamera1.Active := True else // Processing errors. end; TfgCanvas Added new properties DefaultScale, PhysicalWidth, PhysicalHeight. Bug Fixes 🐛 Sizes TfgBitmap.Canvas.Width and TfgBitmap.Canvas.Height were returned in physical values instead of logical ones (iOS). FGX-150 The OnTap and OnLongTap events are being invoked simultaneously (Android). FGX-151 Two bugs is in showing popup form "..FGX Native\Samples\Popup - Base\PopupBaseDemo.dpr" (Android). The system status bar defined wrong content style in automatic mode (iOS). FGX-143 CameraZoom doesn't work for TfgMap (iOS). FGX-148 Automatically moving TfgDrawerLayout.Drawer panel from right to left side, when something forces alignment of nested components (iOS). FGX-149 Spontaneous reset offset in the TfgCollectionView after hiding/showing (iOS).
-
1.13.2.0 Русский
Скачать: Релиз доступен только по запросу. Дата релиза: 10 декабря 2021 Новое ✨ TfgCamera Добавлена реализация TfgCamera для iOS. TfgCameraPreview Добавлена реализация TfgCameraPreview для iOS. TfgBarcodeScanner Добавлена реализация TfgBarcodeScanner для iOS. Улучшения 🙌 TfgCamera Добавлена возможность запросить разрешения, необходимые для работы камеры, с помощью самого компонента TfgCamera.RequestPermission. Проверка текущего статуса разрешений TfgCamera.AuthorizationStatus. Типичный вариант применения: procedure TFormMain.fgFormCreate(Sender: TObject); begin fgCamera1.RequestPermission; end; procedure TFormMain.CameraPermissionRequest(const APermissionInfo: TfgPermissionInfo); begin if APermissionInfo.CheckResult = TfgPermissionCheckResult.Granted then fgCamera1.Active := True else // Processing errors. end; TfgCanvas Добавлены новые свойства DefaultScale, PhysicalWidth, PhysicalHeight. Исправление ошибок 🐛 Размеры TfgBitmap.Canvas.Width и TfgBitmap.Canvas.Height возвращались в физических величинах вместо логических (iOS). FGX-150 События OnTap и OnLongTap срабатывают одновременно (Android). FGX-151 Две ошибки отображения всплывающего окна на примере демо-проекта "..FGX Native\Samples\Popup - Base\PopupBaseDemo.dpr" (Android). Системный статус бар неправильно определяет цвет содержимого в автоматическом режиме (iOS). FGX-143 Не работает CameraZoom в TfgMap (iOS). FGX-148 Самостоятельное перемещение TfgDrawerLayout.Drawer панели справа налево при форсировании выравнивания вложенных компонентов (iOS). FGX-149 Самопроизвольный сброс смещения после выравнивания TfgCollectionView (iOS).
-
[OnTap и OnLongTap] Странное, неожиданное поведение
Исправлено в 1.13.2.0.
-
[OnTap и OnLongTap] Странное, неожиданное поведение
Проблему вижу и подтверждаю. В следующем релизе будет исправлено.
-
[OnTap и OnLongTap] Странное, неожиданное поведение
Добрый вечер, Извините, сейчас посмотрю.
-
[TfgSplitter] Не хватает такого компонента
Извиняюсь, забегался с реализацией GooglePay. Но рад слышать, что вопрос со сплитером решился. Да, все верно. Нужно обязательно использовать координаты формы, как и в FMX, кстати. Потому что касания приходят в локальной системе координат и при выравнивании происходит легкие скачкообразные изменения, что и видно на видео. Поэтому надо выполнять преобразование локальных координат в систему координат формы, чтобы исключить из расчета эти изменения.
-
[OnTap и OnLongTap] Странное, неожиданное поведение
Добрый день, О какой платформе идет речь?
-
1.13.1.0 English
Download: The distributive is available by request only. Release date: 21 November 2021 New ✨ We added two new components-container TfgVirtualPagerLayout and TfgPagerLayout. Both of them are intended for alignment children controls by pages. Switching pages is done by scrolling through the pages with your finger. TfgVirtualPagerLayout It's a basic component, which is designed to dynamically load/unload pages as needed. Unlike the usual approaches with the addition of nested components in advance in the designer, this component requests the loading/unloading of the page through the OnLoadPage and OnUnloadPage events as needed. This means that in fact, instead of loading 10-20 pages, it loads only the visible one and 1-2 more adjacent ones, depending on the current state of the component. Before using it, you need to write handlers for 3 events: OnGetPageCount - return the total number of pages in the component. OnLoadPage - it is necessary to return the page component (any descendant from the TfgControl). You can create a page in this event dynamically, or you can implement a pool of objects to reuse unloaded pages. OnUnloadPage - you can destroy the page or return the page to the page pool for further reuse. Thus, this component allows you to speed up the loading of the application by loading only the necessary pages, and not all at once. Based on this component, you can easily implement an image slider with a large number of images and much more. This component offers a wide range of optional events that allow you to fully control the process of changing tabs: OnChanged - It is called only when the tab is changed interactively, as soon as the component understands which tab the user is finally switching to. OnBeginDragging - Called when the user puts his finger on the screen and starts moving the content. OnEndDragging - Called when the user lifted his finger from the screen and finished moving the content. OnBeginScrolingAnimation - Called when the tab change animation has started. OnEndScrolingAnimation - Called when the tab change animation is over. All the details of the use can be found in the article: Demo sample: "Components" -> "TfgVirtualPagerLayout" -> "Basic Sample" Demo sample: "Components" -> "TfgVirtualPagerLayout" -> "Pages Pool" Demo sample: "Components" -> "TfgVirtualPagerLayout" -> "Photo Slider" Details. TfgPagerLayout This container component is built on the basis of TfgVirtualPagerLayout and unlike TfgVirtualPagerLayout aligns all components added to it by pages. It does not unload/load pages and is essentially an analogue of TfgPageControl. You add any components to it and TfgPagerLayout itself performs their alignment and switching. Details. System status bar Added the ability to change the hue of the contents of the system status bar using the new TfgForm.SystemStatusBar.ResultContentStyle property. Previously, on some customized versions of Android, the system status bar was completely transparent by default (for example, on MIUI), now the system status bar is always by default. Fixed the form layout when hiding the system status bar on Android 11. Improvements 🙌 The translation "android.content.SharedPreferences*" Java classes was added to "Android.Api.ActivityAndView" (Android). Bug Fixes 🐛 TLocationSensor didn't work in Delphi 11 (Android). The OnScroll event wasn't invoked in TfgScrollBox, TfgVerticalScrollBox and TfgHorizontalScrollBox (iOS). The TfgScrollBox, TfgVerticalScrollBox and TfgHorizontalScrollBox doesn't reset content offset after alignment (iOS). TfgLabel.MeasureSize returned control size without ContentPadding (iOS). FGX-144 TfgListMenu displays items in two columns on iPad (iOS). FGX-146 The Sender argument in TfgEdit.OnEnter and OnExit points on main form.
-
1.13.1.0 Русский
Скачать: Релиз доступен только по запросу. Дата релиза: 21 ноября 2021 Новое ✨ В этом релизе добавлены два новых компонента-контейнера TfgVirtualPagerLayout и TfgPagerLayout. Оба предназначены для выравнивания вложенных компонентов по страницам. Переключение страниц осуществляется при помощи пролистывания страниц пальцем. TfgVirtualPagerLayout Это базовый компонент, который предназначен для динамической загрузки/выгрузки страниц по мере их необходимости. В отличии от привычных подходов с добавлением вложенных компонентов заранее в дизайнере, этот компонент запрашивает загрузку/выгрузку страницы через события OnLoadPage и OnUnloadPage по мере их необходимости. Это значит, что фактически вместо загрузки 10-20 страниц, он загружает только видимую и еще 1-2 смежных в зависимости от текущего состояния компонента. Перед использованием, вам необходимо написать обработчики для 3-х событий: OnGetPageCount - вернуть общее количество страниц в компоненте. OnLoadPage - необходимо вернуть компонент страницы (любой наследник от TfgControl). Вы можете создавать страницу в этом событии динамически, а можете реализовать пул объектов, чтобы повторно использовать выгруженные страницы. OnUnloadPage - можно выполнить уничтожение страницы или вернуть страницу в пул страниц для дальнейшего повторного использования. Таким образом, этот компонент позволяет ускорить загрузку приложения за счет загрузки только необходимых страниц, а не всех сразу. На базе данного компонента можно легко реализовать слайдер изображение с большим количеством изображений и многое другое. Данный компонент предлагает широкий набор опциональных событий, позволяющих полностью контролировать процесс смены вкладок: OnChanged - Вызывается только при интерактивной смене вкладки, как только компонент понимает на какую вкладку окончательно переключается пользователь. OnBeginDragging - Вызывается, когда пользователь опустил палец на экран и начал двигать содержимое. OnEndDragging - Вызывается, когда пользователь поднял палец с экрана и закончил двигать содержимое. OnBeginScrolingAnimation - Вызывается, когда началась анимация смены вкладки. OnEndScrolingAnimation - Вызывается, когда анимация смены вкладки закончилась. Обо всех деталях использования можно узнать в статье: Демонстрационный пример: "Компоненты" -> "TfgVirtualPagerLayout" -> "Базовый пример" Демонстрационный пример: "Компоненты" -> "TfgVirtualPagerLayout" -> "Пул страниц" Демонстрационный пример: "Компоненты" -> "TfgVirtualPagerLayout" -> "Слайдер фотографий" Детали использования. TfgPagerLayout Этот компонент-контейнер построен на базе TfgVirtualPagerLayout и в отличии от TfgVirtualPagerLayout выравнивает все добавленные в него компоненты по страницам. Он не выгружает/загружает страницы и по сути является аналогом TfgPageControl. Вы добавляете в него любые компоненты и TfgPagerLayout сам осуществляет их выравнивание и переключение. Детали использования. Системный статус бар Добавлена возможность менять оттенок содержимого системного статус бара при помощи нового свойства TfgForm.SystemStatusBar.ResultContentStyle. Раньше на некоторых кастомизированных версиях Андроид, системный статус бар был полностью прозрачным по умолчанию (Например на MIUI), теперь же системный статус бар всегда по умолчанию. Исправлено отображение формы, при скрытии системного статус бара на Андроид 11. Улучшения 🙌 Добавлена трансляция класса "android.content.SharedPreferences*" в "Android.Api.ActivityAndView" (Android). Исправление ошибок 🐛 TLocationSensor не работал в Delphi 11 (Android). Событие OnScroll не вызывалось у TfgScrollBox, TfgVerticalScrollBox и TfgHorizontalScrollBox (iOS). Теперь после выравнивания TfgScrollBox, TfgVerticalScrollBox или TfgHorizontalScrollBox контент больше не сбрасывается на начало (iOS). TfgLabel.MeasureSize возвращал размер контента без учета ContentPadding (iOS). FGX-144 TfgListMenu отображал элементы в две колонки на iPad (iOS). FGX-146 В компоненте TfgEdit в событиях OnEnter, OnExit входящий параметр Sender всегда указывает на главную форму.
-
Новые компоненты-контейнеры пагинации вложенных компонентов TfgVirtualPagerLayout и TfgPagerLayout
Добрый вечер, Мы плотно работаем над новой версией библиотеки FGX Native, в которую войдут новые компоненты-контейнеры и многие другие улучшения. В этой статье мы хотели бы поделиться двумя новыми компонентами-контейнерами TfgVirtualPagerLayout и TfgPagerLayout, которые появятся в релизе 1.13.1.0. TfgVirtualPagerLayout Это базовый компонент, который предназначен для динамической загрузки/выгрузки страниц по мере их необходимости. В отличии от привычных подходов с добавлением вложенных компонентов заранее в дизайнере, этот компонент запрашивает загрузку/выгрузку страницы через события OnLoadPage и OnUnloadPage по мере их необходимости. Это значит, что фактически вместо загрузки 10-20 страниц, он загружает только видимую и еще 1-2 смежных в зависимости от текущего состояния компонента и, как следствие, ускоряет загрузку приложения. На базе данного компонента можно легко сделать оптимизированный слайдер изображений. Например вот такой: PhotoSlider.mp4 Компонент не хранит все страницы у себя и работает по cхожему c TfgCollectionView принципу, те запрашивает необходимую информацию у разработчика через набор событий. Перед использованием компонента, вам необходимо написать обработчики для 3-х событий: OnGetPageCount - вернуть общее количество страниц в компоненте. OnLoadPage - вернуть компонент страницы. Это может быть любой визуальный компонент. Вы можете создавать страницу в этом событии динамически, а можете реализовать пул объектов, чтобы повторно использовать выгруженные ранее страницы. OnUnloadPage - можно выполнить уничтожение страницы или вернуть страницу в пул объектов для дальнейшего повторного использования. Типичным примером реализации данных событий может быть такой код, создающий страницы с текстом на базе TfgLabel: procedure TFormMain.fgVirtualPagerLayout1GetPageCount(Sender: TObject; var ACount: Integer); begin // Сообщаем компоненту о количестве страниц. ACount := 100; end; procedure TFormMain.fgVirtualPagerLayout1LoadPage(Sender: TObject; const AItemIndex: Integer; var APage: TfgControl); var LPage: TfgLabel; begin // Создаем страницу на базе TfgLabel, которая будет отображать номер страницы. LPage := TfgLabel.Create(nil); LPage.Font.Size := 30; LPage.Text := Format('Page %d', [AItemIndex]); APage := LPage; end; procedure TFormMain.fgVirtualPagerLayout1UnloadPage(Sender: TObject; const AItemIndex: Integer; const APage: TfgControl); begin // Удаляем страницу. APage.Free; end; В результате получим: Basic_Text_Pages.mp4 Пул страниц В этом примере вы можете обратить внимание, что если страницы по структуре одинаковые, то смысла удалять страницу и создавать заново особо не имеет смысла. Поэтому для этого случая, можно написать простой пул объектов, который не будет удалять вкладку, как только она не нужна, а складывать ее в список для дальнейшего повторного использования. Для реализации пула страниц создадим два списка: Список используемых страниц в компоненте в текущий момент времени - FAcquiredPages. Список использованных страниц, которые уже не используются в текущий момент времени - FReleasedPages. Код по объявлению списков выглядит так: type TFormMain = class(TfgForm) private FAcquiredPages: TList<TfgLabel>; FReleasedPages: TObjsetList<TfgLabel>; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; end; var FormMain: TFormMain; implementation {$R *.xfm} uses System.SysUtils, FGX.Application, FGX.Dialogs, FGX.Log; { TFormMain } constructor TFormMain.Create(AOwner: TComponent); begin inherited; FAcquiredPages := TList<TfgLabel>.Create; FReleasedPages := TObjsetList<TfgLabel>.Create; end; destructor TFormMain.Destroy; begin FreeAndNil(FAcquiredPages); FreeAndNil(FReleasedPages); inherited; end; Теперь, когда компонент запрашивает страницу мы выполняем простые действия: Если страница есть в пуле, то мы ее извлекаем. Если свободной страницы в пуле нет, то создаем новую. Когда же страница выгружается компонентом, мы просто возвращаем ее в пул. procedure TFormMain.fgVirtualPagerLayout1GetPageCount(Sender: TObject; var ACount: Integer); begin ACount := 100; end; procedure TFormMain.fgVirtualPagerLayout1LoadPage(Sender: TObject; const AItemIndex: Integer; var APage: TfgControl); var Page: TfgLabel; begin if FReleasedPages.Count = 0 then begin // В пуле нету свободных страниц, создаем новую Page := TfgLabel.Create(nil); Page.Font.Size := 30; end else // В пуле есть свободная страница, берем ее Page := FReleasedPages.ExtractAt(0); // Переносим страницу в список используемых страниц. FAcquiredPages.Add(Page); // Задаем текст и возвращаем страницу Page.Text := Format('Page %d', [AItemIndex]); APage := Page; end; procedure TFormMain.fgVirtualPagerLayout1UnloadPage(Sender: TObject; const AItemIndex: Integer; const APage: TfgControl); begin TfgAssert.IsClass(APage, TfgLabel); // Возвращаем страницу в пул для повторного использования FAcquiredPages.Remove(APage as TfgLabel); FReleasedPages.Add(APage as TfgLabel); end; Теперь мы получили такое же приложение, как и без использования пула, но теперь страницы не пересоздаются по мере их пролистывания, а повторно используются. Тем самым мы ускоряем процедуру загрузки страниц. Таким образом, этот компонент позволяет ускорить загрузку приложения за счет загрузки только необходимых страниц, а не всех сразу. На базе данного компонента можно легко реализовать слайдер изображение с большим количеством изображений и многое другое. Динамическое изменение страниц Поскольку компонент запрашивает страницы и их количество у разработчика, то при любом изменении количества страниц, удаление/добавление страниц необходимо уведомить об этом компонент при помощи следующих методов: Reload - Уведомляет компонент о том, что список страниц изменился и надо заново его построить. NotifyPageInserted - Уведомляет компонент, что в список вставлены новые страницы по указанным индексам. NotifyPageRemoved - Уведомляет компонент, что из списка нужно удалить страницы по указанным индексам. Состав страниц нельзя менять в процессе переключения вкладок! Дополнительные события Данный компонент предлагает широкий набор дополнительных событий, позволяющих полностью контролировать процесс смены вкладок: OnChanged - Вызывается только при интерактивной смене вкладки, как только компонент понимает на какую вкладку окончательно переключается пользователь. OnBeginDragging - Вызывается, когда пользователь опустил палец на экран и начал двигать содержимое. OnEndDragging - Вызывается, когда пользователь поднял палец с экрана и закончил двигать содержимое. OnBeginScrolingAnimation - Вызывается, когда началась анимация смены вкладки. OnEndScrolingAnimation - Вызывается, когда анимация смены вкладки закончилась. TfgPagerLayout Этот компонент-контейнер построен на базе TfgVirtualPagerLayout и в отличии от TfgVirtualPagerLayout выравнивает все добавленные в него компоненты по страницам. Он не выгружает/загружает страницы и по сути является аналогом TfgPageControl. Вы добавляете в него любые компоненты и TfgPagerLayout сам осуществляет их выравнивание и переключение.
-
1.13.0.0 Русский
В большинстве случаев - эта порезка связана с FMX и его использованием каких-то тех или иных java библиотек. Поэтому даже, если в Delphi 11 написано, что минимальная поддержка Android 8.1. Обычно не означает, что ограничение для всех приложений в принципе. Это ограничение пишется обычно на базе FMX. А поскольку FGX Native не имеет зависимости от FMX, то это ограничение я бы еще проверил.
-
1.13.0.0 Русский
Добрый вечер, Сама библиотека FGX Native поддерживает Android с 5.0. У нас нету никаких ограничений в библиотеке на использование Android 5.0. Однако, ограничение накладывает сама IDE поэтому в каждой версии это ограничение свое, это ограничение вводится на уровне RTL, на которое мы повлиять никак не можем. Если верить документации, то 10.4 поддерживает минимально Android 5.1. Но проверить я это не могу, так как у меня нет устройства на базе Android 5.*.
-
1.13.0.0 English
Download: The distributive is available by request only. Release date: 22 October 2021 New ✨ Delphi 11 The Delphi 11 and HiDPI support were added. The Delphi 10.3 support was removed based on the survey results. Form Designer The new function was added, which allows to hide components dash-border. We also slightly improved the visual display of component areas by adding the display of areas of internal margins in pale green colors. This allows you to visually and quickly understand where you are using internal padding (Tagcontrol.Padding). Improvements 🙌 TfgTimePicker The autosize mode was added and enabled by default TfgDatePicker.Autosize. The BackgroundName property was published. FGX-142 There are no possibility to select 12/24-hours format. The new property Is24HoursMode was added. It allows to select 12/24 hours format. Now the component automatically selects the clock display mode based on the current phone locale setting (Android). In the previous version, it always used the am/pm format. TfgDatePicker The autosize mode was added and enabled by default TfgDatePicker.Autosize. The BackgroundName property was published. Android API Now you can easily and conveniently convert JString <-> Delphi string. We added new methods to JString type: var JavaString: JString; DelphiString: string; begin // Delphi string -> Java string JavaString := TJString.Create('Delphi string sample'); // Java string -> Delphi string DelphiString := JavaString.ToDelphiString; end; Als we added additional Android API headers Java.Api.Network from java.net package. Bug Fixes 🐛 Hiding and showing TfgCollectionView via Visible property led to application freeze (iOS). Dynamic changes ActionButtons of TfgNavigationBar led to Access Violation (iOS). TfgCanvas.FillColor didn't work correctlry with transparent colors (Android). The changing TfgBarcode data didn't lead to repainting control. The changing TfgBarcode data didn't clear previous barcode correctly. The appearance TfgTimePicker and TfgDatePicker was fixed in designer.
-
1.13.0.0 Русский
Скачать: Релиз доступен только по запросу. Дата релиза: 22 октября 2021 Новое ✨ Delphi 11 Добавлена поддержка Delphi 11.0 и HiDPI режима. Прекращена и убрана поддержка Delphi 10.3 на основании результатов опроса. Дизайнер формы Добавлена новая функция, позволяющая отключать отображение вспомогательной пунктирной рамки компонентов. Так же слегка улучшили функцию визуальное отображения областей компонентов, добавив отображение областей внутренних отступов бледно зеленым цветов. Это позволяет визуально и быстро понять, где вы используется внутренние отступы (TfgControl.Padding). Улучшения 🙌 TfgTimePicker Добавлен и включен по умолчанию режим автоматического задания размера TfgTimePicker.Autosize. Опубликовано свойство BackgroundName. FGX-142 Нет возможности указать 24-часовой формат выбора времени?. Добавлено новое свойство Is24HoursMode, позволяющее выбрать режим отображения часовой секции. Теперь компонент автоматически выбирает режим отображения часов на основании текущей настройки локали телефона (Android). В предыдущей версии он всегда использовал am/pm формат. TfgDatePicker Добавлен и включен по умолчанию режим автоматического задания размера TfgDatePicker.Autosize. Опубликовано свойство BackgroundName. Android API Теперь можно легко и удобно преобразовать JString <-> Delphi string туда и обратно при помощи вспомогательных методов в JString следующим образом: var JavaString: JString; DelphiString: string; begin // Delphi string -> Java string JavaString := TJString.Create('Delphi string sample'); // Java string -> Delphi string DelphiString := JavaString.ToDelphiString; end; Так же добавлены переводы части Java классов из "java.net" пакета в Java.Api.Network. Исправление ошибок 🐛 Скрытие и отображение TfgCollectionView через свойство Visible могло приводить к зависанию приложения (iOS). Динамическое изменение ActionButtons у панели навигации TfgNavigationBar могло приводить к ошибке (iOS). Заливка цветом TfgCanvas.FillColor не работала корректно для прозрачных цветов (Android). При смене кода в TfgBarcode, компонент не перерисовывался. При смене кода в TfgBarcode, компонент не корректно очищал предыдущий штрих код. Исправлено отображение компонентов TfgTimePicker и TfgDatePicker в дизайнере. Теперь они корректно центрируют секции и корректно отображают часы для режима am/pm.
-
Анонс 1.13.0.0 и Delphi 11
Добрый день, В ближайшее время выйдет релиз FGX Native 1.13.0.0 с полноценной поддержкой Delphi 11. Обо всех нововведениях по порядку. Delphi 11 Начиная с версии 1.13.0.0 мы включили поддержку Delphi 11. В то же время, мы исключили поддержку 10.3 из инсталлятора на основании результатов голосования: Мы переработали все формы дизайнера и добавили полноценную поддержку HiDPI. Дизайнер форм Добавлен новый режим позволяющий отключать пунктирную рамку компонентов. Так же несколько улучшили функцию визуального отображения областей компонентов, добавив отображение областей внутренних отступов бледно зеленым цветов. Это позволяет наглядно и быстро понять, где используются внутренние отступы (TfgControl.Padding). Обновления TfgDatePicker и TfgTimePicker В этом релизе мы добавили несколько небольших улучшений этих компонентов. Теперь вы можете указать формат ввода времени: 12 или 24 часовой формат. За это отвечает новое свойство TfgTimePicker.Is24HoursMode = (LocaleDependent, True, False). Теперь при старте компонента на платформе Android он по умолчанию выбирает часовой формат на основании текущей локали устройства. Помимо этого мы добавили режим автоматического расчета размера для этих компонентов AutoSize, который включен по умолчанию. Поэтому, если вам необходимо, чтобы компоненты растягивались по ширине, нужно исключить значение AutoSize.Width. Так же, теперь вы можете отдельно указывать задний фон для этих компонентов при помощи свойства BackgroundName.
-
Продление лицензии
Вы не первый, кто с этим сталкивается. На форуме за кулуарами есть понятие подписки, которая не совпадает с тем, что вы видите здесь. Я периодически меняю ссылку, чтобы не вводить пользователей в заблуждение. Но при каждом обновлении форума, обычно эта ссылка слетает...