我有一个 ListView 和一个 ArrayAdapter< CustomListViewItem> 设置为其适配器。我想跟踪每个 CustomListViewItem 项的展示次数。
每当ListView项目进入视图时,应该算作一次展示。当它离开视图然后再次进入视图时,印象计数会递增。当用户滚动时,一些项目将离开视图,一些项目将进入视图。我想跟踪那些进入视野并移出视野的物品。
我尝试了什么:
我试过的一件事就是 setOnScrollListener 列表 查看和跟踪 onScroll(AbsListView视图,int firstVisibleItem,int visibleItemCount,int totalItemCount)回调。
我可以使用 firstVisibleItem 和 visibleItemCount 来完成这项工作。 在文档中,它表示在滚动完成时调用它。但是当滚动速度很慢时,它似乎被调用很多次。可能在滚动的每个像素之后。这使得卷轴非常滞后。
还有其他办法吗?通过使用某种回调,当它退出视图或进入视图时会被调用每个项目?
我在网上搜索了很多,并没有看到任何与此类跟踪相关的帖子。
答案 0 :(得分:0)
我找不到另一种方法来做到这一点。所以,我优化了我已经在做的事情。我想我应该分享这个,因为它可以帮助别人。
我使用 onScroll()的 firstVisibleItem 和 visibleItemCount 仅回调。我使用两个变量来保存先前onScroll()回调的信息。他们是:
prevVisibleStart 和 prevVisibleEnd
让我们举一个例子来理解算法。 首先假设在第一次onScroll()
之后f irstVisibleItem = 0 和 visibleItemCount = 3 => lastVisibleItem = 2
这些用于设置我以前的可见状态。
所以, prevVisibleStart = firstVisibleItem = 3 和 prevVisibleEnd = firstVisibleItem + visibleItemCount - 1 = 2
现在,如果我向下滚动,我将永远
firstVisibleItem > = prevVisibleStart 和 lastVisibleItem > = prevVisibleEnd
所以,如果之前的范围是0到2.新的范围有点像1到3.因为,我已经考虑了0到2的印象。我只会考虑3作为新的印象。原因是视图1,2仍然在视野中,它们并没有消失。因此,不会计算新的印象。这有效地为印象提供了正确的考虑范围,同时也减少了检查的范围。
同样,这可以用于向上滚动。 假设当前可见项目为2-4。 向上滚动后,范围变为(比如)1-3。这意味着1已进入视野。因此,请为此视图留下印象。这样,onScroll()中的操作数量显着减少。
示例代码如下
范围[i-j]被认为是印象。
private static int prevVisibleStart=-1;
private static int prevVisibleEnd=-1;
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if(prevVisibleStart <= firstVisibleItem) {
// scroll down
i = Math.max(firstVisibleItem, prevVisibleEnd + 1);
j = firstVisibleItem + visibleItemCount;
} else {
// scroll up
i = firstVisibleItem;
j = Math.min(prevVisibleStart, firstVisibleItem + visibleItemCount);
}
prevVisibleStart = firstVisibleItem;
prevVisibleEnd = firstVisibleItem + visibleItemCount - 1;
// now can use [i-j) to update impressions
}