Android 在RecyclerView中获取可见项

Android 在RecyclerView中获取可见项,android,android-recyclerview,Android,Android Recyclerview,我需要知道哪些元素当前显示在我的RecyclerView中。没有与ListView上的方法等效的方法。我试着和他一起工作,但那个黑客太难看了,而且并不总是奏效 有人有什么想法吗?您可以使用recyclerView.getChildAt()来获取每个可见的子对象,并在适配器代码中的这些视图上设置一些标记convertview.setTag(index)将帮助您将其与适配器数据关联起来。您可以使用recyclerView.getChildAt()来获取每个可见的子对象,并在适配器代码中的这些视图上设

我需要知道哪些元素当前显示在我的RecyclerView中。没有与ListView上的方法等效的方法。我试着和他一起工作,但那个黑客太难看了,而且并不总是奏效


有人有什么想法吗?

您可以使用
recyclerView.getChildAt()
来获取每个可见的子对象,并在适配器代码中的这些视图上设置一些标记
convertview.setTag(index)
将帮助您将其与适配器数据关联起来。

您可以使用
recyclerView.getChildAt()
来获取每个可见的子对象,并在适配器代码中的这些视图上设置一些标记
convertview.setTag(index)
,这将帮助您将其与适配器数据关联起来。

第一个/最后一个可见子项取决于
布局管理器。
如果您使用的是
LinearLayoutManager
GridLayoutManager
,则可以使用

int findFirstVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();
例如:

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

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

第一个/最后一个可见子项取决于
LayoutManager
。 如果您使用的是
LinearLayoutManager
GridLayoutManager
,则可以使用

int findFirstVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();
例如:

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

对于
LinearLayoutManager
,第一个/最后一个取决于适配器顺序。不要从
RecyclerView
查询子项
LayoutManager
可能更喜欢为缓存布局比可见项目更多的项目。

对于
LayoutManager
执行以下操作:

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;

请记住检查它是否为空。

对于
StaggedGridLayoutManager
执行以下操作:

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;

记得检查它是否为空。

最后,我找到了一个解决方案,可以从适配器中的onBindViewHolder事件中知道当前项是否可见

关键是LayoutManager提供的方法


在适配器中,您可以从RecyclerView获取LayoutManager,该视图作为事件的参数获取。

最后,我找到了一个解决方案,可以从适配器中的onBindViewHolder事件了解当前项是否可见

关键是LayoutManager提供的方法


在适配器中,您可以从RecyclerView获取LayoutManager,该视图作为事件的参数获取。

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

int findFirstVisibleItemPosition();
int findLastVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();
如果您想跟踪
屏幕上的项目是否可见,了解一些阈值,那么您可以参考以下博客


以下
线性/网格布局管理器
方法可用于检查哪些项目是可见的

int findFirstVisibleItemPosition();
int findLastVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();
如果您想跟踪
屏幕上的项目是否可见,了解一些阈值,那么您可以参考以下博客


附录

建议的函数findLast…Position()在工具栏展开时,在工具栏折叠的情况下不能正常工作。

“回收器”视图似乎具有固定的高度,当工具栏展开时,回收器向下移动,部分移出屏幕。因此,拟议功能的结果过高。示例:最后一个可见的项目被告知是9,但实际上项目7是屏幕上的最后一个项目。


这种行为也是我的视图经常无法滚动到正确位置的原因,即scrollToPosition()无法正常工作(我最终以编程方式折叠了工具栏)。

附录

建议的函数findLast…Position()在工具栏展开时,在工具栏折叠的情况下不能正常工作。

“回收器”视图似乎具有固定的高度,当工具栏展开时,回收器向下移动,部分移出屏幕。因此,拟议功能的结果过高。示例:最后一个可见的项目被告知是9,但实际上项目7是屏幕上的最后一个项目。


这种行为也是我的视图经常无法滚动到正确位置的原因,即scrollToPosition()无法正常工作(我最终以编程方式折叠了工具栏).

对于那些需要在RecyclerView适配器内部实现逻辑的人,在查阅RecyclerView时,您仍然可以使用@ernesto方法与on-scrollListener相结合来获取所需的
。
在适配器内部,您将有如下内容:

@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"));
                        }
                }
            });
        }
    }

对于那些需要在RecyclerView适配器中实现逻辑的用户,在查阅RecyclerView时,您仍然可以使用@ernesto方法结合on-scrollListener来获得所需的
。 在适配器内部,您将有如下内容:

@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"));
                        }
                }
            });
        }
    }

您可以找到回收视图的第一个和最后一个可见子视图,并检查您要查找的视图是否在以下范围内:

var visibleChild: View = rv.getChildAt(0)
val firstChild: Int = rv.getChildAdapterPosition(visibleChild)
visibleChild = rv.getChildAt(rv.childCount - 1)
val lastChild: Int = rv.getChildAdapterPosition(visibleChild)
println("first visible child is: $firstChild")
println("last visible child is: $lastChild")

您可以找到回收视图的第一个和最后一个可见子视图,并检查您要查找的视图是否在以下范围内:

var visibleChild: View = rv.getChildAt(0)
val firstChild: Int = rv.getChildAdapterPosition(visibleChild)
visibleChild = rv.getChildAt(rv.childCount - 1)
val lastChild: Int = rv.getChildAdapterPosition(visibleChild)
println("first visible child is: $firstChild")
println("last visible child is: $lastChild")

上面的每个答案都是正确的,我还想从我的工作代码中添加一个快照

recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
           //some code when initially scrollState changes
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            //Some code while the list is scrolling
            LinearLayoutManager lManager = (LinearLayoutManager) recycler.getLayoutManager();
            int firstElementPosition = lManager.findFirstVisibleItemPosition();
            
        }
    });

上面的每个答案都是正确的,我还想从我的工作代码中添加一个快照

recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
           //some code when initially scrollState changes
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            //Some code while the list is scrolling
            LinearLayoutManager lManager = (LinearLayoutManager) recycler.getLayoutManager();
            int firstElementPosition = lManager.findFirstVisibleItemPosition();
            
        }
    });

我希望下面的代码能帮助人们定义上述方法。如果可视项目位置与项目位置之前不同,屏幕上将显示toast消息

myRecyclerview.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);

            LinearLayoutManager manager= (LinearLayoutManager) myRecyclerview.getLayoutManager();
            assert manager != null;
            int visiblePosition = manager.findLastCompletelyVisibleItemPosition();


            if(visiblePosition > -1&&a!=visiblePosition) {
                Toast.makeText(context,String.valueOf(visiblePosition),Toast.LENGTH_SHORT).show();
                //do something
                a=visiblePosition;

            }
        }

        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            //Some code while the list is scrolling


        }
    });

我希望下面的代码能帮助人们定义上述方法。如果可视项目位置与项目位置之前不同,屏幕上将显示toast消息

myRecyclerview.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);

            LinearLayoutManager manager= (LinearLayoutManager) myRecyclerview.getLayoutManager();
            assert manager != null;
            int visiblePosition = manager.findLastCompletelyVisibleItemPosition();


            if(visiblePosition > -1&&a!=visiblePosition) {
                Toast.makeText(context,String.valueOf(visiblePosition),Toast.LENGTH_SHORT).show();
                //do something
                a=visiblePosition;

            }
        }

        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            //Some code while the list is scrolling


        }
    });
getChildAt()的问题在于元素的顺序可以是5个元素中的任意一个:0、5、4、3、2、1(子元素的数量通常大于等于可见项的数量)。所以我试图通过ge获得元素的顺序