判断RecyclerView中的项目是否可见

8

我已经构建了一个基本界面,其中包括在RecyclerView内的CardView列表。当添加一个卡片时,我需要知道它是否在屏幕上可见。

为了实现这一点,我尝试使用布局管理器的findLastVisibleItemPosition()方法,但是它似乎返回的结果比预期少一个项目。例如,如果我有1张卡片是可见的,findLastVisibleItemPosition()返回-1(我期望可见卡片的索引为0)。

我的简化核心方法如下:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    items = new ArrayList<>();

    RecyclerView recycList = (RecyclerView) findViewById(R.id.rv);
    recycList.setHasFixedSize(true);
    llm = new LinearLayoutManager(this);
    llm.setOrientation(LinearLayoutManager.VERTICAL);
    recycList.setLayoutManager(llm);
    recycList.addOnChildAttachStateChangeListener(new ChildAttachListener(llm));
    adapter = new RecycAdapter(items);
    recycList.setAdapter(adapter);
}

private void addItem(){
    items.add(new Item());
    adapter.notifyDataSetChanged();
}

private class ChildAttachListener implements OnChildAttachStateChangeListener{
    LinearLayoutManager llm;

    public ChildAttachListener(LinearLayoutManager llm){
        super();
        this.llm = llm;
    }

    @Override
    public void onChildViewAttachedToWindow(View view) {

        System.out.println("Items size = "+items.size() + ", Last Visible Item = "+llm.findLastVisibleItemPosition());
    }

    @Override
    public void onChildViewDetachedFromWindow(View view) {

    }
}

当第一个项目添加时返回:

Items size = 1, Last Visible Item = -1

当第二个项目被添加时返回:

Items size = 2, Last Visible Item = 0
Items size = 2, Last Visible Item = 0

当第三个项目被添加时返回:

Items size = 3, Last Visible Item = 0
Items size = 3, Last Visible Item = 1
Items size = 3, Last Visible Item = 1

在所有情况下,所有项目都是可见的(屏幕上可以显示7个可见项目)。
请有人帮我理解findLastVisibleItemPosition()的返回值,并建议我如何确定添加卡片时它是否在屏幕上可见?
编辑: 我应该澄清我的真正目标是在添加项目时(使用我的addItem()方法),知道它是否可见。如果在addItem()方法内部有一种简单的方法来实现这一点,那就更好了。

你尝试过使用findLastCompletelyVisibleItemPosition()吗? - Nanoc
是的,对于上面的例子,结果完全相同(即添加3个项目,因为它们全部都是可见的)。 - Ratty
根据文档http://developer.android.com/reference/android/support/v7/widget/LinearLayoutManager.html#findLastCompletelyVisibleItemPosition%28%29,-1值与NO_POSITION常量匹配。 - Nanoc
谢谢,我理解了这一点,但我不明白的是为什么在我有一个可见项时会返回-1?例如,如果items.size() = 1并且我的OnChildAttachStateChangeListener已经触发(表明该项已附加),我可以在屏幕上看到该项,为什么findLastVisibleItemPosition()返回-1而不是0?我认为这可能与参考文档中的以下行有关:“此位置不包括在最后一次布局传递后分派的适配器更改。”,但是我不确定最后一次布局传递是何时完成的以及如何触发它? - Ratty
很遗憾,我和你一样了解的一样。 - Nanoc
@Ratty:我可能在瞎猜,但我确信recycler view返回的可见项数比实际看到的多2个;一个在第一个之前,一个在最后一个之后。这可能是因为listview在屏幕上是连续的,可能包含部分可见的列表项(我认为部分可见的区别在于我们如何看待它以及系统如何看待它)。 - Sreedevi J
1个回答

13

对于那些感兴趣的人,我通过在Handler中调用findLastVisibleItemPosition方法来解决了这个问题。

@Override
public void onChildViewAttachedToWindow(View view) {

    Handler handler = new Handler();
        handler.post(new Runnable() {
            @Override
            public void run() {

                System.out.println(llm.findLastVisibleItemPosition());
            }
        });
}

在将项目添加到适配器后,如果紧接着调用布局管理器,则其报告可能不正确。通过这种方式,它可以正常工作!谢谢! - Minas Mina

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接