Jump to content

Yaroslav Brovin

Administrators
  • Posts

    2,567
  • Joined

  • Last visited

  • Days Won

    647

Everything posted by Yaroslav Brovin

  1. Download: The distributive is available by request only. Release date: 31 December 2021 Attention 🚨 Now, when changing the selection mode TfgCollectionView.SelectionMode, the existing selection of elements will be absolutely discarded without triggering any events. Now, in the single selection mode TfgCollectionViewSelectionMode.SingleSelect, deselection from the selected element is not blocked. New ✨ Google Pay The new component TfgGooglePayClient was added. It allows to provide payments in your applications via Google Pay. The component is crossplatform. However Google Pay is supported only on Android platform. Details. TfgApplicationEvents The new two events OnActivityResult and OnActivityNewIntent were added. This events work only in Android platform. The OnActivityResult is being invoked, when Android activity receives result of invoking another activity. The OnActivityNewIntent is being invoked, when Android activity receives intent from another activity. The each event has argument of TfgAndroidIntent type, which in fact is Android.Api.ActivityAndView.JIntent type in Андроиде and TObject on another platforms. So typical sample of usage these events can look like: procedure TFormMain.fgApplicationEvents1ActivityResult(Sender: TObject; const ARequestCode, AResultCode: Integer; const AIntent: TfgAndroidIntent); begin {$IFDEF ANDROID} // Work with AIntent, ARequestCode, AResultCode {$ENDIF} end; iOS/Android API The new headers API files were added for usage in application purchases: iOS.Api.StoreKit and Android.Api.Billing. The new iOS headers were added: iOS.Api.PassKit, iOS.Api.AddressBook and iOS.Api.AddressBookUI. Improvements 🙌 The new demo sample was added, which shows how to use "Share" service for iOS: "iOS Api" -> "Sharing data". FGX-152 Implement taking control's screenshot (iOS). THe target version of *Android API* was increased for new FGX Native applications to Android 11 (API 30). TfgCollectionView New property TfgCollectionView.SelectionController.SelectionCount for getting the number of selected list items. New events to control the selection of elements TfgCollectionView: OnItemCanSelect and OnItemCanDeselect Bug Fixes 🐛 FGX-153 TfgDateEdit Date is not passed to Picker on the first call. FGX-155 Property value TfgCameraPreview.DisplayMode was ignored on first run (iOS). The OnZoom didn't work (Android).
  2. Скачать: Релиз доступен только по запросу. Дата релиза: 30 декабря 2021 Внимание 🚨 Теперь при изменении режима выделения TfgCollectionView.SelectionMode существующее выделение элементов будет безусловно сброшено без вызова каких-либо событий. Теперь в режиме единичного выделения TfgCollectionViewSelectionMode.SingleSelect не блокируется снятие выделения с выделенного элемента (Android). Новое ✨ Google Pay Добавлен новый компонент TfgGooglePayClient, позволяющий подключить оплату в вашем мобильном приложении через Google Pay. Компонент кроссплатформенный, но поскольку Google Pay предназначении только для Android, то компонент реализован только для Android. Детали. TfgApplicationEvents Добавлены два новых события OnActivityResult и OnActivityNewIntent, работающие только на Android. Событие OnActivityResult вызывается только в Android, когда активити приложение получает результат вызова другого активити. Событие OnActivityNewIntent вызывается только в Android, когда активити приложение получает новое намерение от других активити. В параметрах событий передается намерение типа TfgAndroidIntent, которое по факту является Android.Api.ActivityAndView.JIntent типом в Андроиде и TObject на остальных платформах. Поэтому типовой пример использования может выглядеть так: procedure TFormMain.fgApplicationEvents1ActivityResult(Sender: TObject; const ARequestCode, AResultCode: Integer; const AIntent: TfgAndroidIntent); begin {$IFDEF ANDROID} // Work with AIntent, ARequestCode, AResultCode {$ENDIF} end; iOS/Android API Добавлены заголовочный файлы для использования нативного API по использованию встроенных покупок: iOS.Api.StoreKit и Android.Api.Billing. Добавлены заголовочные файлы iOS.Api.PassKit, iOS.Api.AddressBook и iOS.Api.AddressBookUI. Улучшения 🙌 Добавлен новый демонстрационный проект по реализации сервиса "Поделиться" для iOS: "iOS Api" -> "Сервис поделиться". FGX-152 Реализовать screenshot экрана (iOS). Поднята целевая версия Android API для новых приложений до Android 11 (API 30). TfgCollectionView Новое свойство TfgCollectionView.SelectionController.SelectionCount для получения количества выделенных элементов списка. Новые события для контроля за выделением элементов TfgCollectionView: OnItemCanSelect и OnItemCanDeselect. Исправление ошибок 🐛 FGX-153 TfgDateEdit Не передается дата в Picker при первом вызове. FGX-155 При первом запуске игнорировалось значение свойства TfgCameraPreview.DisplayMode (iOS). Не работал жест OnZoom (Android).
  3. Релиз сегодня будет, чуть попозже.
  4. Там будет просто TObject. type {$IFDEF ANDROID} TfgAndroidIntent = JIntent; {$ELSE} TfgAndroidIntent = type TObject; {$ENDIF}
  5. Поздравляем вас с наступающим Новым годом! Мы благодарим вас за доверие и спасибо, что в этом году вы были с нами. В течении всего года мы прислушивались к вашим пожеланиям и старались сделать все возможное, чтобы наш продукт раз от раза становился удобнее и мощнее. В ближайшее время выйдет новый релиз 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. Заключении Желаем вам свершения всего задуманного, интересных проектов и амбициозных целей! Спасибо, что вы с нами!
  6. Добрый вечер, Как я уже говорил, я не смог воспроизвести проблему. Пробовал разные проекты, все на месте, там где хит тест не был указан, он и не загружается. Где был указан, все так же и загрузилось. Я специально грузил большие проекты, где много компонентов, чтобы поймать этот кейс. Но все штатно. Опять же, если бы вы мне дали проект или показали, где видно, что свойство слетает, то можно было бы предметно поговорить. В 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. В демке пустая форма. Ничего больше нет на форме.
  7. 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).
  8. Скачать: Релиз доступен только по запросу. Дата релиза: 20 декабря 2021 Исправление ошибок 🐛 У компонентов TfgImage и TfgProgressBar не работали корректно события OnTap и OnLongTap (Android).
  9. Hello Sally, We have already this helper. Look at the FGX.Picker.Time.TfgPickerTimeFactory and FGX.Picker.Date.TfgPickerDateFactory.
  10. Хорошо, Проверю еще разок. Понял. Как выясню, выпущу хотфикс.
  11. Проверил, В это я с трудом верю. Последнее задание значения False по умолчанию было сделано 2018.07.14, о чем свидетельствует лог в гите: Так же при открытии старого проекта, я не вижу, чтобы слетало значение HitTest у TfgImage. Если есть шаги для воспроизведения, буду рад. Подтверждаю. Это касается TfgImage и еще я обнаружил такую же проблему у TfgProgressBar. На каком компоненте наблюдается такое поведение?
  12. 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).
  13. Скачать: Релиз доступен только по запросу. Дата релиза: 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).
  14. Проблему вижу и подтверждаю. В следующем релизе будет исправлено.
  15. Добрый вечер, Извините, сейчас посмотрю.
  16. Извиняюсь, забегался с реализацией GooglePay. Но рад слышать, что вопрос со сплитером решился. Да, все верно. Нужно обязательно использовать координаты формы, как и в FMX, кстати. Потому что касания приходят в локальной системе координат и при выравнивании происходит легкие скачкообразные изменения, что и видно на видео. Поэтому надо выполнять преобразование локальных координат в систему координат формы, чтобы исключить из расчета эти изменения.
  17. Добрый день, О какой платформе идет речь?
  18. 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.
  19. Скачать: Релиз доступен только по запросу. Дата релиза: 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 всегда указывает на главную форму.
  20. Добрый вечер, Мы плотно работаем над новой версией библиотеки 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 сам осуществляет их выравнивание и переключение.
  21. Данное решение предложено для использования в связке FGX Native. И это работает отлично.
  22. В большинстве случаев - эта порезка связана с FMX и его использованием каких-то тех или иных java библиотек. Поэтому даже, если в Delphi 11 написано, что минимальная поддержка Android 8.1. Обычно не означает, что ограничение для всех приложений в принципе. Это ограничение пишется обычно на базе FMX. А поскольку FGX Native не имеет зависимости от FMX, то это ограничение я бы еще проверил.
  23. Добрый вечер, Сама библиотека FGX Native поддерживает Android с 5.0. У нас нету никаких ограничений в библиотеке на использование Android 5.0. Однако, ограничение накладывает сама IDE поэтому в каждой версии это ограничение свое, это ограничение вводится на уровне RTL, на которое мы повлиять никак не можем. Если верить документации, то 10.4 поддерживает минимально Android 5.1. Но проверить я это не могу, так как у меня нет устройства на базе Android 5.*.
×
×
  • Create New...