如何让FMX ListBox的ScrollToItem方法在窗体创建或激活时生效
问题原因
调用ScrollToItem不生效的核心原因是:OnCreate、OnShow、OnActivate这几个事件触发时,TListBox还未完成最终的布局计算,滚动视口的尺寸、列表项的实际位置参数都还没有初始化完成,此时执行滚动操作没有正确的坐标依据,所以会失效。
解决方法
方法1:使用TThread.Queue延迟执行滚动操作
把滚动逻辑放到UI消息队列的末尾,等窗体和控件的所有初始化布局完成后再执行,修改后的FormCreate代码如下:
procedure TForm5.FormCreate(Sender: TObject); var i: Integer; lbi: TListBoxItem; TargetItem: TListBoxItem; begin for i := 1 to 50 do begin lbi := TListBoxItem.Create(ListBox1); lbi.Text := 'item ' + IntToStr(i); ListBox1.AddObject(lbi); end; ListBox1.ItemIndex := ListBox1.Items.IndexOf('item 48'); TargetItem := ListBox1.Selected; // 将滚动操作投递到UI队列末尾,等待布局完成后执行 TThread.Queue(nil, procedure begin ListBox1.ScrollToItem(TargetItem); end ); end;
该方法兼容性最好,不需要额外修改事件绑定逻辑,适配所有版本的FMX,同时支持Windows、移动端等全平台。
方法2:先强制更新控件布局再滚动
如果不想用异步调用,可以在滚动前先手动触发ListBox的布局更新,确认所有参数计算完成后再执行滚动:
procedure TForm5.FormCreate(Sender: TObject); var i: Integer; lbi: TListBoxItem; begin for i := 1 to 50 do begin lbi := TListBoxItem.Create(ListBox1); lbi.Text := 'item ' + IntToStr(i); ListBox1.AddObject(lbi); end; ListBox1.ItemIndex := ListBox1.Items.IndexOf('item 48'); // 先强制更新ListBox的布局参数 ListBox1.Realign; ListBox1.UpdateStyle; ListBox1.UpdateLayout; // 此时再调用滚动即可生效 ListBox1.ScrollToItem(ListBox1.Selected); end;
注意:该方法在部分低版本FMX中可能存在兼容问题,优先推荐使用方法1。
内容的提问来源于stack exchange,提问作者PABEIER
相关产品推荐
相关产品推荐

