By rekire


2014-07-28 06:00:47 8 Comments

I need to know which elements are currently displayed in my RecyclerView. There is no equivalent to the OnScrollListener.onScroll(...) method on ListViews. I tried to work with View.getGlobalVisibleRect(...), but that hack is too ugly and does not always work too.

Someone any ideas?

7 comments

@Aleyam 2019-06-02 18:22:11

for those who have a logic to be implemented inside the RecyclerView adapter you can still use @ernesto approach combined with an on scrollListener to get what you want as the RecyclerView is consulted. Inside the adapter you will have something like this:

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

@Andreas K. aus M. 2019-05-21 18:30:34

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).

@rekire 2019-05-21 19:06:12

That is true, but this is how the collapsing toolbar works. I stopped developing Android Apps a year ago, but I can remember that fact.

@Sumit Jain 2019-02-07 09:01:13

Following Linear / Grid LayoutManager methods can be used to check which items are visible

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

and if you want to track is item visible on screen for some threshold then you can refer to the following blog.

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

@Ernesto Vega 2018-02-06 15:34:20

Finally, I found a solution to know if the current item is visible, from the onBindViewHolder event in the adapter.

The key is the method isViewPartiallyVisible from LayoutManager.

In your adapter, you can get the LayoutManager from the RecyclerView, which you get as parameter from the onAttachedToRecyclerView event.

@NocTurn 2019-01-03 23:21:39

But where would you call this method in which the layout manager is not null?

@Ernesto Vega 2019-01-04 09:07:34

You need to wait for the onAttachedToRecyclerView event of the adapter. In that event you receive the RecyclerView as parameter; and then you can get the LayoutManager from the RecyclerVie, and save it in a global var. If the LayoutManager is null, probably could be because it wasn't assigned to the RecyclerView in the Activity/Fragment/Layout; and try to build the adapter after that assignment.

@yigit 2014-07-31 07:50:48

First / last visible child depends on the LayoutManager. If you are using LinearLayoutManager or GridLayoutManager, you can use

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

For example:

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

For LinearLayoutManager, first/last depends on the adapter ordering. Don't query children from RecyclerView; LayoutManager may prefer to layout more items than visible for caching.

@rekire 2014-07-31 07:54:12

I totally missed that.

@Yorgi 2014-12-10 00:09:24

Is there any possibility to access this methods from RecyclerView.Adapter without passing reference to LayoutManager?

@yigit 2014-12-10 05:03:29

Nope, because it depends on layout manager.

@RoundSparrow hilltx 2015-04-22 15:21:41

Like @Yorgi - inside the adapter seems useful. I wonder if there is some pattern you can develop in using onBindViewHolder to track which ones are actually on-screen while a user scrolls.

@Alexandre G 2015-07-07 04:36:08

@RoundSparrowhilltx you will more likely want to do it in onView(At/De)tachedToWindow - RecyclerView not only recycles but caches items which means onBindViewHolder is not called for each view that's about to go on screen

@Juan José Melero Gómez 2015-07-15 20:47:40

Why can't I use mLinearLayoutManager directly instead of having to use method mRecyclerView.getLayoutManager?

@mbmc 2015-08-24 20:49:34

getItemCount can return 1 and findFirstVisibleItemPosition -1 on the same call.

@yigit 2015-08-25 00:36:04

@tibo, that might be ok if you call it after changing the adapter contents but before the new layout is calculated. That means there is data in the adapter but we have not laid out the views yet.

@hornet2319 2015-09-10 07:49:54

what can you suggest about StaggeredLayoutManager?

@Pratik Butani 2015-09-23 12:44:39

What about StaggeredLayoutManager?

@dVaffection 2015-11-24 05:58:09

How to get an actual view? layoutManager.getChildAt(int index) more often returns null instead of a View!

@dVaffection 2015-11-24 06:32:05

Never mind already found findViewByPosition(int position)

@Zapnologica 2016-02-17 15:55:32

quick one, How do I then Set that value? I want to recover after a screen rotation, I am saving index in bundle and want to recover in onCreateView?

@BK- 2016-03-09 00:00:09

For grid layouts (staggered and otherwise) you need to use the variant that will return multiple visible cells. The reason for this is because you have multiple columns you may have multiple visible cells per column. developer.android.com/reference/android/support/v7/widget/…

@J. K. 2016-06-07 10:05:35

These methods are so unreliable they are completly useless. Especially after notifyDataSetChanged/itemRemoved/RangeChanged

@yfsx 2016-08-25 03:07:02

findFirstCompletelyVisibleItemPosition(); works for item that completely shown on display.. how about item which longer that screen?

@Rob 2017-11-22 11:48:47

With v17 onwards (leanback) the GridLayoutManager is no longer public.

@Stuti Kasliwal 2018-01-22 12:39:25

Really helpful!! (y)

@SudoPlz 2018-05-31 19:31:43

I came here to find which method to use reliably in order to get the position AFTER notify*Changed/Removed etc method calls. Still no answer found. :/

@Ashish Garg 2019-01-10 09:11:28

findLastVisibleItemPosition return last item of list not last item which is view. For example recyclerview has 23 entry only 5 are visible. so findLastVisibleItemPosition return it return 23 not 5

@Waseem 2019-01-23 16:46:40

I tried to get current visible top item inside onScrollChanged method with SCROLL_STATE_IDLE, but current visible item always returning 0, I have 30 items on recyclerView. Any suggestion please ?

@Waseem 2019-01-23 16:48:37

@AshishGarg I agree with your comment

@Jack 2019-05-05 08:54:56

@J. K., did you find an alternative to using those?

@VVB 2019-06-16 01:13:11

Where should I use this method? Inside Adapter or onScrolled()/onScrollStateChanged()?

@Alan 2019-07-05 08:55:59

I discovered my recycler view was inside a nested scroll view in my XML, which was causing the recycler view to actually fit the parent, and think it was displaying all of it's items. The fix is to obviously kill the nested scroll view with fire! (I inherited an android project in the new job 😅)

@Douglas Nassif Roma Junior 2016-05-17 19:57:24

For StaggeredGridLayoutManager do this:

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

And to get visible item views:

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

Remember to check if it is empty.

@tmm1 2018-01-30 23:55:50

What do you mean "check if it is empty"? How does one check?

@Douglas Nassif Roma Junior 2018-01-31 11:56:46

viewsIds is an array, and it may be empty.

@Sreejith B Naick 2014-07-28 06:47:53

You can use recyclerView.getChildAt() to get each visible child, and setting some tag convertview.setTag(index) on these view in adapter code will help you to relate it with adapter data.

@rekire 2014-07-28 06:50:24

The problem with getChildAt() is that the order of the elements can be out of 5 elements: 0, 5, 4, 3, 2, 1 (the child count is mostly >= the count of visible items). So I tried to get the order of the element via getGlobalVisibleRect.

@Sreejith B Naick 2014-07-28 06:56:45

What's your actual requirement, get visible child(child inside screen bound) in actual order ?

@rekire 2014-07-28 06:59:57

Now I want to know which element is in the center, later I'm maybe also interested in the bounds.

@Sreejith B Naick 2014-07-28 07:05:23

best way to do this,customize recycler view. On each drawChild(), check whether the drawing view is at center. If it is in center, send a listener to outside.

@Sreejith B Naick 2014-07-28 07:09:17

Logic to check whether view is in centre is upto you, 2 views can be middle,you have to decide which one to pick.

@rekire 2014-07-28 07:13:12

In my special case I have an odd count, so that's not the matter. Extending a widget which surly will change its methods soon... I don't know if I really want that.

@RoundSparrow hilltx 2015-04-22 15:20:20

You start out saying: "You can use recyclerView.getChildAt() to get each visible child," -- but isn't that a paradox? How do you know which Items are visible...

@Sreejith B Naick 2015-04-23 05:49:53

You will only get visible items from recyclerView.getChildAt(), thats how generally RecyclerView works. RecyclerView will try to hold only few child views which are currently visible (ie; within screen bounds, not Visibility as GONE,INVISIBLE) and try to recycle these views when user scrolls.

@TalkLittle 2016-01-25 23:22:02

I'd add to use recyclerView.getChildCount() in order to get the number of visible children. Then you can do a for-loop for (int i = 0; i < childCount; i++) { View visibleChild = recyclerView.getChildAt(i); }

@Kevin Lee 2016-05-04 18:05:21

View visibleChild = recyclerView.getChildAt(0); int positionOfChild = recyclerView.getChildAdapterPosition(visibleChild);

@Waseem 2019-01-23 17:59:31

@KevinLee finally your idea worked

Related Questions

Sponsored Content

16 Answered Questions

[SOLVED] View's getWidth() and getHeight() returns 0

17 Answered Questions

[SOLVED] How to create RecyclerView with multiple view type?

43 Answered Questions

[SOLVED] RecyclerView onClick

39 Answered Questions

[SOLVED] How to add dividers and spaces between items in RecyclerView?

43 Answered Questions

39 Answered Questions

[SOLVED] Get screen dimensions in pixels

15 Answered Questions

[SOLVED] Android: combining text & image on a Button or ImageButton

31 Answered Questions

[SOLVED] Why doesn't RecyclerView have onItemClickListener()?

12 Answered Questions

[SOLVED] How to update RecyclerView Adapter Data?

18 Answered Questions

[SOLVED] Fling gesture detection on grid layout

Sponsored Content