我需要知道哪些元素目前显示在我的RecyclerView。ListViews上没有与OnScrollListener.onScroll(…)方法等价的方法。我试图与view . getglobalvisibl勃起(…)工作,但黑客是太丑陋,并不总是工作太。

有人有什么想法吗?


当前回答

对于那些在Kotlin中寻找答案的人:

fun getVisibleItem(recyclerView : RecyclerView) {
        recyclerView.addOnScrollListener(object: RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                 if(newState == RecyclerView.SCROLL_STATE_IDLE) {
                     val index = (recyclerView.layoutManager.findFirstVisibleItemPosition
                     //use this index for any operation you want to perform on the item visible on screen. eg. log(arrayList[index])
                 }
            }
        })
    }

您可以根据您的用例探索获取该职位的其他方法。

int findFirstCompletelyVisibleItemPosition()
int findLastVisibleItemPosition()
int findLastCompletelyVisibleItemPosition()

其他回答

第一个/最后一个可见子节点依赖于LayoutManager。 如果您正在使用LinearLayoutManager或GridLayoutManager,您可以使用

int findFirstVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();

例如:

GridLayoutManager layoutManager = ((GridLayoutManager)mRecyclerView.getLayoutManager());
int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();

对于LinearLayoutManager,第一个/最后一个取决于适配器的顺序。不要从RecyclerView中查询子元素;LayoutManager可能更倾向于布局比缓存可见的更多的项。

Addendum: The proposed functions findLast...Position() do not work correctly in a scenario with a collapsing toolbar while the toolbar is expanded. It seems that the recycler view has a fixed height, and while the toolbar is expanded, the recycler is moved down, partially out of the screen. As a consequence the results of the proposed functions are too high. Example: The last visible item is told to be #9, but in fact item #7 is the last one that is on screen. This behaviour is also the reason why my view often failed to scroll to the correct position, i.e. scrollToPosition() did not work correctly (I finally collapsed the toolbar programmatically).

对于StaggeredGridLayoutManager执行以下操作:

RecyclerView rv = findViewById(...);
StaggeredGridLayoutManager lm = new StaggeredGridLayoutManager(...);
rv.setLayoutManager(lm);

要获得可见的项目视图:

int[] viewsIds = lm.findFirstCompletelyVisibleItemPositions(null);
ViewHolder firstViewHolder = rvPlantios.findViewHolderForLayoutPosition(viewsIds[0]);
View itemView = viewHolder.itemView;

记得检查它是否为空。

以下线性/网格LayoutManager方法可用于检查哪些项是可见的。

int findFirstVisibleItemPosition();
int findLastVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();

如果你想跟踪屏幕上可见的项目,那么你可以参考下面的博客。

https://proandroiddev.com/detecting-list-items-perceived-by-user-8f164dfb1d05

对于那些需要在RecyclerView适配器中实现逻辑的人来说,您仍然可以使用@ernesto方法结合on scrollListener来在咨询RecyclerView时获得您想要的东西。 在适配器内部,你会有这样的东西:

@Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if(manager instanceof LinearLayoutManager && getItemCount() > 0) {
            LinearLayoutManager llm = (LinearLayoutManager) manager;
            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                }

                @Override
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                        int visiblePosition = llm.findFirstCompletelyVisibleItemPosition();
                        if(visiblePosition > -1) {
                            View v = llm.findViewByPosition(visiblePosition);
                            //do something
                            v.setBackgroundColor(Color.parseColor("#777777"));
                        }
                }
            });
        }
    }