【问题标题】:How to detect when FMX List View is scrolled to the bottom?如何检测 FMX 列表视图何时滚动到底部?
【发布时间】:2017-09-19 16:41:44
【问题描述】:

我正在使用 Firemonkey TListView 来显示搜索结果。此列表一次加载 25 个项目,但可能会显示数百个项目。

我需要检测用户何时向下滚动到底部,以便获取接下来的 25 个项目以显示在列表中。但是,我找不到合适的属性来确定这一点。

OnPullRefresh 事件,但这适用于滚动到列表顶部并将其拉下。我需要的是类似的,但是对于列表的 bottom 而不是 top

OnScrollViewChange 事件似乎很合适。还有ScrollViewPos 属性,它也很有用。但是,我无法弄清楚将该数字与什么进行比较 - 具体来说,ScrollViewPos 的最大可能值。我需要像ScrollViewMax 这样的东西。

但我找不到更多可以准确检测到用户已滚动到底部的信息。

如何检测用户何时滚动到 Firemonkey TListView 的底部,以便加载更多搜索结果?

编辑

如果由于某种原因无法做到这一点,则可以使用“加载更多...”按钮将虚拟项目添加到列表末尾。但我宁愿它是自动化的。

EDIT2

我忘了提及...我在此列表视图中显示了搜索框,并且项目可以具有可变高度。如果根据项目内容计算这是唯一的方法,那么这样的计算需要完美。我不想知道用户何时“接近”或“接近”底部,而是用户何时恰好到达列表的底部。

【问题讨论】:

  • 好的,接下来看看ScrollTo滚动到特定项目的方法的来源。

标签: listview delphi scroll firemonkey


【解决方案1】:

进一步调查我在

中发现了以下内容
function TListViewBase.GetItemRect(const AItemIndex: Integer): TRectF;

如果你更深入

function TListViewBase.GetItemRelRect(const Index: Integer; const LocRect: TRectF;
  const SideSpace: Integer = 0): TRectF;

那么你会发现最后一项的Top是

listview1.GetItemRect(listview1.ItemCount-1).top+listview1.ScrollViewPos-listview1.SideSpace-listview1.LocalRect.top

无论您的项目可变高度是多少。这表示FHeightSums[Index] 的值,它是一个列表,其中包含直到索引为Index 的项目的高度总和

现在问题来了: 您希望计算完美。你想触地得分。

就是这样

procedure TForm5.ListView1ScrollViewChange(Sender: TObject);
var
Tmp_top : single;
begin
Tmp_top := listview1.GetItemRect(listview1.ItemCount-1).top+listview1.ScrollViewPos-listview1.SideSpace-listview1.LocalRect.top;

if Tmp_top+listview1.GetItemRect(listview1.ItemCount-1).height-listview1.Height=listview1.ScrollViewPos-2*listview1.SideSpace then
    showmessage('touch down');

end;

编辑:如果你进一步简化这个公式,你最终会得到另一个答案,只需要很少的升级

 procedure TForm5.ListView1ScrollViewChange(Sender: TObject);
begin

if listview1.GetItemRect(listview1.ItemCount-1).bottom=listview1.Height-listview1.SideSpace then
    showmessage('touch down');

end;

现在这将涵盖填充、边距、边距、搜索框可见性和搜索框大小更改的任何更改。

【讨论】:

  • 如果有搜索框或项目高度可变(我两者都有),则无法正常工作。也不太确定边距/填充。这可能是一个更棘手的公式,因为我需要它完全匹配。
  • @JerryDodge 我刚刚测试了搜索框,公式不受影响。至于项目变量高度,问题中没有提到。我认为你应该补充一点。但是,我会尝试找到更好的东西并回复您
  • 我还没有机会尝试它,现在正在处理其他非视觉的东西。谢谢。
【解决方案2】:

试试这个代码。我认为不言自明...

procedure TForm1.ListView1ScrollViewChange(Sender: TObject);
var
  R: TRectF;
begin
  if TListView(Sender).ItemCount > 0 then // Just in case...
  begin
    // Get the last item's Rect
    R := TListView(Sender).GetItemRect(TListView(Sender).ItemCount - 1);
    // Bottom?
    if R.Bottom = TListView(Sender).Height then
      Caption := 'Reached bottom!'
    else
      Caption := 'Bottom not reached yet.';
  end;
end;

【讨论】:

  • 我喜欢这个答案,它更简单,只使用GetItemRect() 的一个电话。但是,如果侧面空间发生变化,它将失败并且不起作用,幸运的是我知道如何解决这个问题,因为我的答案涵盖了这个:)。为了克服这一点,将 if 条件从 R.Bottom = TListView(Sender).Height 更改为 R.Bottom = TListView(Sender).Height - TListView(Sender).SideSpace 并完成
  • 第一个 if 也是不必要的,因为有可能有 7 个或 15 个项目并且滚动条将不可见。只有当项目的总高度大于画布高度时,它才会可见。作为结论,没有项目和滚动条显示的情况是不可能的(至少对于这个问题)
  • 我刚刚注意到这一点。如果我简化我的第二个公式,我最终会得到你的答案(当然还有我告诉你的修改)
猜你喜欢
  • 2020-09-24
  • 1970-01-01
  • 2021-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-06
相关资源
最近更新 更多