RecyclerView:在创建视图后立即查找最后一个可见项目

时间:2015-07-10 05:44:21

标签: android android-layout android-adapter android-recyclerview

我遇到以下方法的问题:

int firstVisibleItemPosition = gridLayoutManager.findFirstVisibleItemPosition();
int lastVisibleItemPosition = gridLayoutManager.findLastVisibleItemPosition();

我的目标:保存有关用户查看过的内容的分析数据。

为了做到这一点,我在两种不同的场景中调用这些方法:

  • 每次滚动都转到“空闲”状态,并检查可见项目是什么。在那种情况下,我得到了预期的索引。

  • RecyclerView对用户“可见”时。 现在就是问题开始的时候。我希望当包含recylcerView的片段传递onResume()时,调用findLastVisibleItemPosition()将返回可见项。 但在这种情况下返回-1。我想这与RecyclerView +适配器内部项初始化相对于片段/活动生命周期的异步加载有关。

将此代码推迟几毫秒 - findLastVisibleItemPosition()返回正确的索引。但我不想推迟硬编码使用处理程序+延迟runnable,因为调度延迟runnable是我真正想做的解决办法:检测回收器视图何时完成膨胀并将所有视图绘制到屏幕上里面的脚.. ..

所以我的问题基本上是:

  • 如何检测RecyclerView何时完成所有初始化/测量/充气并将其绘制到屏幕上的子项? (在任何用户交互之前......)。

  • 有没有可靠的良好实践方法来确切知道回收者视图中的哪些项目真正显示在屏幕上?

3 个答案:

答案 0 :(得分:1)

配置更改怎么样?如果用户更改了屏幕方向,则可见项目也会更改。事实是,可见项目会根据RecyclerView的状态,加载的数据,滚动位置和当前屏幕配置不断变化。

你可以做的最好的事情是创建一个不断跟踪可见项超集的类,通过使它实现ItemDecoration接口,每次重新RecyclerView时调用该接口屏幕,并让此组件定期发送统计信息。您将在配置更改(保留其状态)时将其重新附加到新的RecyclerView实例。

因此,例如,该组件可以跟踪最小和最大可见位置。起初它们都是-1。然后在加载数据并在屏幕上显示第一项后,将再次调用ItemDecoration,第一个可见项位置现在为0,最后一个可见项位置现在为N.滚动后,值将为再改变一下您只需保留FirstVisibleItemPosition的最小值和LastVisibleItemPosition的最大值以获取超集。在没有更改的X秒之后,或者如果用户从活动导航回来,您将记录并发送这些数字。

答案 1 :(得分:0)

使用OnChildAttachListener检测回收商何时附加新的支架。使用延迟机制发送正确的analitycs(\不是硬编码的延迟,但像这样:

...
public void run(){
  removeCallbacks()
  postDelay(sendAnalytics(correctInformation),25);
}

25ms延迟更可靠,然后将onResume任意附加。

答案 2 :(得分:-1)

至于回答你的第一个问题。我发现这个问题的最佳解决方案是在回收站视图上设置布局更改侦听器:

recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
    @Override
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
        recyclerView.removeOnLayoutChangeListener(this); //remove layout change listener, you want need it anymore
        //do your work here
    }
});

至于第二个问题。你可以getChildCount()& getChildAt(int)获取有关当前附加子视图的信息到recyclerView,但它并不意味着它们在屏幕上可见(它们可能有点偏离屏幕)。要查看它们是否可见,请参阅Android: how to check if a View inside of ScrollView is visible?