检测到视图在RecyclerView.ViewHolder中部分可见

时间:2016-08-19 14:54:22

标签: android

当ViewHolder中的一个感兴趣的视图移出窗口边界(滚动或部分滚动)时,是否有一种检测甚至更好,获得通知的好方法?

我认为一个选项是在RecyclerView上设置滚动侦听器并检查我的LayoutManager findFirstCompletelyVisibleItemPosition()等,并计算哪些视图不再可见。类似的东西:

private RecyclerView.OnScrollListener mScrollListener = new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        calculateVisibility();
    }
};

其中calculateVisibility()将在每个滚动事件上运行,但这只会让我看到我的ViewHolder位置,而不是实际的ViewHolders或这些视图持有者中的单个视图。这意味着我需要从布局管理器中查找位置的实际布局,然后测量视图支架内的各个视图。类似的东西:

private void calculateVisibility() {
    if (!isAdded() || !getUserVisibleHint() || mAdapter == null) {
        return;
    }

    if (mLayoutManager.findFirstCompletelyVisibleItemPosition() == -1
            && mLayoutManager.findLastCompletelyVisibleItemPosition() == -1
            && mLayoutManager.findFirstVisibleItemPosition() == -1
            && mLayoutManager.findLastVisibleItemPosition() == -1) {
        return;
    }
    int firstPartiallyVisiblePosition = mLayoutManager.findFirstCompletelyVisibleItemPosition();
    int lastPartiallyVisiblePosition = mLayoutManager.findFirstCompletelyVisibleItemPosition();

    View v = mLayoutManager.findViewByPosition(firstPartiallyVisiblePosition);
    for (v instanceof MySpecialView) {
        boolean visible = isViewVisible(v);
        // do stuff based on visibility
    }
}

这感觉它的效率非常低。

我可以在适配器内找到的方法似乎与回收和分离更相关,如果你只是滚动屏幕视图就不会发生这种情况。

也许有人做过类似的事情?

1 个答案:

答案 0 :(得分:2)

如果这对任何人都有用,这就是我最终做的事情:

  private void calculateVisibility() {
    if (!isAdded() || !getUserVisibleHint() || mAdapter == null
            || mAdapter.getItemCount() == 0) {
        return;
    }

    if (mLayoutManager.findFirstCompletelyVisibleItemPosition() == -1
            && mLayoutManager.findLastCompletelyVisibleItemPosition() == -1
            && mLayoutManager.findFirstVisibleItemPosition() == -1
            && mLayoutManager.findLastVisibleItemPosition() == -1) {
        return;
    }
    int findFirstVisibleItemPosition = mLayoutManager.findFirstVisibleItemPosition();
    int findLastVisibleItemPosition = mLayoutManager.findLastVisibleItemPosition();

    int [] positions = {findFirstVisibleItemPosition, findLastVisibleItemPosition};
    ViewHolder viewHolder;
    Rect scrollBounds = new Rect();
    mRecyclerView.getDrawingRect(scrollBounds);
    int location[] = new int[2];
    for (int position : positions) {
        viewHolder = mRecyclerView.getChildViewHolder(
                mLayoutManager.findViewByPosition(position));
        viewHolder.getMySpecialView().getLocationInWindow(location);

        if (location[1] < 0 || location[1] > scrollBounds.bottom) {
            // do stuff
        }
    }
}