Delphi XE5 - прокрутка TPaintBox слишком медленная при использовании TListBox на машинах с Android

Я создаю мобильное приложение Firemonkey на Delphi XE5. Я хотел бы использовать компонент TPaintBox для отображения текста (более 2000 слов со специальными символами, таблицы). Я создал форму с TListBox и специальным TListBoxItem type TListBoxItemPaintBox = Class(TListBoxItem) содержащий TPaintBox внутри. Идея очень проста - на TPaintBox я буду рисовать данные, а TListBox позаботится о прокрутке.

Когда это приложение скомпилировано под Win32, все работает отлично, прокрутка происходит быстро. Но когда я компилирую это приложение на своем телефоне с Android, приложение становится бесполезным - прокрутка невероятно ss-ll-oooo-www.

Вот полный код моего приложения (упрощенная, но рабочая версия)

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Layouts,
  FMX.ListBox, FMX.StdCtrls, FMX.Objects, System.UIConsts;

type
  TListBoxItemPaintBox = Class(TListBoxItem)
    public
      pbMain: TPaintBox;
      List: TStringList;
      constructor Create(AOwner: TComponent); override;
      procedure pbMainOnPaint(Sender: TObject; Canvas: TCanvas);
  end;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    lbMain: TListBox;
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
{TListBoxItemPaintBox}
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
constructor TListBoxItemPaintBox.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  self.Height := 200;
  self.Text := '';

  pbMain := TPaintBox.Create( self );
  pbMain.Parent := self;
  pbMain.Align := TAlignLayout.alClient;
  pbMain.OnPaint := pbMainOnPaint;
end;

procedure TListBoxItemPaintBox.pbMainOnPaint(Sender: TObject; Canvas: TCanvas);
// pbMain.OnPaint := pbMainOnPaint;
var
  i, vertPos: Integer;
  s: String;
  rect: TRectF;
begin
  vertPos := 0;

  Canvas.BeginScene;
  Canvas.Clear(claWhite);

  Canvas.Fill.Color := claBlack;
  Canvas.Font.Style := [];
  Canvas.Font.Size := 12;

  for i := 0 to List.Count-1 do
    begin
      s := List[i];
      rect.Create(0,
                  vertPos,
                  Canvas.TextWidth(s),
                  vertPos+Canvas.TextHeight(s));
      Canvas.FillText(rect, s, false, 255, [], 
                    TTextAlign.taLeading ,TTextAlign.taCenter);
      vertPos := vertPos + 15;
    end;

  self.Height := vertPos;
  pbMain.Canvas.EndScene;
end;

//%%%%%%%%%%%%%%%%%%%%%
{TForm1}
//%%%%%%%%%%%%%%%%%%%%%
procedure TForm1.Button1Click(Sender: TObject);
var
  ListTemp: TStringList;
  aListBoxItem: TListBoxItemPaintBox;
  i: Integer;
begin
  ListTemp := TStringList.Create;
  for i := 0 to 80 do
    ListTemp.Add(IntToStr(i));

  aListBoxItem := TListBoxItemPaintBox.Create( lbMain );
  aListBoxItem.List := ListTemp;
  lbMain.AddObject(aListBoxItem);
end;

end.

У кого-нибудь есть идеи, как заставить это работать на Android? Есть ли более подходящий способ использования TPaintBox или я должен использовать совершенно другой компонент?

1 ответ

Решение

ListBox не является правильным контейнером для того, чтобы иметь так много записей, поскольку он очень медленный, но он действительно намного более настраиваемый, чем другие. Вам придется использовать компонент ListView для достижения скорости и нормальной прокрутки. Будет немного больно, чтобы он отображал все, что вы хотите, потому что он как бы ограничен от своих собственных. Вам нужно будет создать свой собственный стиль, который будут прослушивать элементы при создании кода.

Вот действительно очень полезное видео о том, как этого добиться от Рэя Конопки.

http://www.youtube.com/watch?v=XRj3qjUjBlc&list=PLwUPJvR9mZHiaYvH9Xr7WuFCVYugC4d0w&index=23

Другие вопросы по тегам