Jump to content

Новые компоненты-контейнеры пагинации вложенных компонентов TfgVirtualPagerLayout и TfgPagerLayout


Yaroslav Brovin

491 views

 Share

Добрый вечер,

Мы плотно работаем над новой версией библиотеки FGX Native, в которую войдут новые компоненты-контейнеры и многие другие улучшения. В этой статье мы хотели бы поделиться двумя новыми компонентами-контейнерами TfgVirtualPagerLayout и TfgPagerLayout, которые появятся в релизе 1.13.1.0

TfgVirtualPagerLayout

Это базовый компонент, который предназначен для динамической загрузки/выгрузки страниц по мере их необходимости. В отличии от привычных подходов с добавлением вложенных компонентов заранее в дизайнере, этот компонент запрашивает загрузку/выгрузку страницы через события OnLoadPage и OnUnloadPage по мере их необходимости. Это значит, что фактически вместо загрузки 10-20 страниц, он загружает только видимую и еще 1-2 смежных в зависимости от текущего состояния компонента и, как следствие, ускоряет загрузку приложения.

На базе данного компонента можно легко сделать оптимизированный слайдер изображений. Например вот такой:

Компонент не хранит все страницы у себя и работает по 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;

В результате получим:

 

Пул страниц

В этом примере вы можете обратить внимание, что если страницы по структуре одинаковые, то смысла удалять страницу и создавать заново особо не имеет смысла. Поэтому для этого случая, можно написать простой пул объектов, который не будет удалять вкладку, как только она не нужна, а складывать ее в список для дальнейшего повторного использования. Для реализации пула страниц создадим два списка:

  1. Список используемых страниц в компоненте в текущий момент времени - FAcquiredPages.
  2. Список использованных страниц, которые уже не используются в текущий момент времени - 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 сам осуществляет их выравнивание и переключение.
 

  • Like 11
  • Thanks 1
 Share

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...