Delphi /Firemonkey使列表框同步滚动效果更好

mhd8tkvw  于 2022-11-04  发布在  其他
关注(0)|答案(2)|浏览(336)

我有一个非常肮脏的方式有7个listboxses滚动同步,他们都有完全相同的高度,所以当我移动他们中任何一个的位置,其他6个也应该移动到该位置
我所做的是假设Listbox1被滚动并且**ViewportPositionChange()**被触发我说

Listbox2.ViewportPosition := NewViewportPosition;
Listbox3.ViewportPosition := NewViewportPosition;

这一切都工作,我只是添加这个代码到每个Listboxses ViewportPositionChange()事件,但它的可怕的不稳定和太慢的Andriod,我仍然需要能够滚动从任何一个列表框,但有没有一种方法来提高滚动的性能?
好吧,老实说,它不是很慢,但你可以感觉到它不完全是敏捷的,而且每个列表框可以有很多列表框,每个列表框也可以有一些控件和更多的控件在这些控件,所以很多重绘是做了我认为,这是什么使它不那么敏捷。

示例代码

首先在你的表单上放置一个网格面板布局,添加6列并添加一个列表框到每一列,每个列表框代表一天,其中列表框1是星期一,也对齐这些客户端。
全局变量

private Glistbox : array[0..6] of TListBox;

在表单创建时

Glistbox[0] := ListBox1;
Glistbox[1] := ListBox2;
Glistbox[2] := ListBox3;
Glistbox[3] := ListBox4;
Glistbox[4] := ListBox5;
Glistbox[5] := ListBox6;
Glistbox[6] := ListBox7;

现在在每个列表框上OnViewportPositionChange

//Note that this would be for Listbox1 so for listbox 2 it needs to be changed acordingly
ListBox2.ViewportPosition := NewViewportPosition;
ListBox3.ViewportPosition := NewViewportPosition;
ListBox4.ViewportPosition := NewViewportPosition;
ListBox5.ViewportPosition := NewViewportPosition;
ListBox6.ViewportPosition := NewViewportPosition;
ListBox7.ViewportPosition := NewViewportPosition;

然后使用以下代码添加一个按钮:

var
    mainlayout,item1,item2 : Tlayout;
    listboxitem : TListBoxItem;
    myrec,myrec2 : TRectangle;
    lbl1,lbl2 : TLabel;
    I: Integer;
begin
for I := 0 to 6 do
begin
    listboxitem := TListBoxItem.Create(nil);

    mainlayout := TLayout.Create(nil);
    mainlayout.Align := TAlignLayout.Client;
    mainlayout.Parent:= listboxitem;

    item1 := TLayout.Create(nil);
    item1.Align:= TAlignLayout.Left;
    item1.Parent := mainlayout;

    item2 := TLayout.Create(nil);
    item2.Align:= TAlignLayout.Right;
    item2.Parent := mainlayout;

    myrec := TRectangle.Create(nil);
    myrec.Align := TAlignLayout.Client;
    myrec.Parent := item1;

    myrec2 := TRectangle.Create(nil);
    myrec2.Align := TAlignLayout.Client;
    myrec2.Parent := item2;

    lbl1 := TLabel.Create(nil);
    lbl1.Align := TAlignLayout.Client;
    lbl1.TextAlign := TTextAlign.Center;
    lbl1.Text := '1';
    myrec.AddObject(lbl1);

    lbl2 := TLabel.Create(nil);
    lbl2.Align := TAlignLayout.Client;
    lbl2.TextAlign := TTextAlign.Center;
    lbl2.Text := '2';
    myrec2.AddObject(lbl2);

    Glistbox[I].AddObject(listboxitem);
    item2.Width:= mainlayout.Width/2;
end;

有时可能有更多的控件在一个列表框中,但一般来说,我认为这将是规范,现在添加一些项目,并尝试滚动

jmo0nnb3

jmo0nnb31#

FMX TListBox有很多开销,因为每个列表框项基本上都是一个插入滚动框的样式化组件。这有利于灵活性,但不利于速度。
在Windows和OSX中,有一些像ScrollWindowEx或NSView.scrollRect + NSView.setNeedsDisplayInRect这样的函数,它们可以通过滚动窗口的一部分而不发出绘制消息来帮助提高性能。所以你只需要使列表框的一部分无效。我可以想象Android也有类似的功能。但是你可能需要修补FMX才能使用它。这可以提高一点性能。但仍然不是一个获得高性能的神奇开关。类似的方法是将滚动框的内容缓存在位图中,然后在滚动时将部分位图复制到屏幕上。
如果你真的需要很好的列表框性能,那么你需要开发自己的列表框,优化速度。这是我必须做的OSX版本的应用程序,以获得我需要的性能。

vjrehmav

vjrehmav2#

此外,还有Firemonkey的TListView,当所有项目共享相同的视觉结构时,它比TListBox更好。Ray Konopka(2014年)的教程解释了每种视图的适用范围:https://www.youtube.com/watch?time_continue=934&v=XHYtwAu5fl4
要调整滚动行为(如果有帮助),请参阅:https://docwiki.embarcadero.com/RADStudio/Alexandria/en/FireMonkey_Layouts_Strategies#Smooth_Inertial_Scrolling

相关问题