1

I have a recylcerview where the method shown below gets called on each selection of an item. The method only runs sucessfully when I do not scroll the recyclerview, so the firstvisible is 0. The moment I scroll down a bit and select something the first and last visible are set correctly in the method, but as can be seen in the screenshot, for reasons I do not understand the childAt returns null instead of the view I can see on my app screen. In the screenshot for position 7, the first 4-6 returned a child.

Can someone explain to me how this can happen? From my pov, getChildAt() should always return a view in this scenario.

enter image description here

Tupsi
  • 33
  • 6

1 Answers1

1

first and last are going to be the adapter positions of the data and not the position as laid out in the layout manager. See LinearLayoutManager#findFirstVisibleItemPosition. The children will always start with zero and increase from there.

That is why it works before your scroll since the child at the zeroth index in the layout manager is also the zeroth item in the adapter.

Here is a discussion about the various positions in RecyclerView.

It looks like you want to make changes to all visible items. Your first and last variables will have the correct start/end adapter positions that correspond to what is visible on the screen. You need the adapter positions to call the various "notify" methods.

So, given the adapter positions, we need a map to the views that are represented on the screen. As an example, the following code loops through every visible view and changes the background color of each view.

LinearLayoutManager lm = (LinearLayoutManager) Recycler.getLayoutManager();
// Get adapter positions for first and last visible items on screen.
int firstVisible = lm.findFirstVisibleItemPosition();
int lastVisible = lm.findLastVisibleItemPosition();
for (int i = firstVisible; i <= lastVisible; i++) {
    // Find the view that corresponds to this position in the adapter.
    View visibleView = lm.findViewByPosition(i);
    visibleView.setBackgroundColor(getResources().getColor(android.R.color.holo_red_light));
}

If you use the child methods of the layout manager, you will need to loop from zero to LayoutManager.getChildCount() - 1 to make the changes. You will see each attached view which, I believe, can exceed the number of visible views.

Cheticamp
  • 61,413
  • 10
  • 78
  • 131
  • Does this mean I can not be sure that all numbers in between first and last are also present on the screen? (Sounds like it). So how would I achieve looping through all visible items on the screen, so I can update them with notifyItemChanged()? – Tupsi Jun 07 '22 at 06:22
  • All views between first and last inclusive will be present on the screen. You are confusing the various positions available with _RecyclerView_. See the updated answer. – Cheticamp Jun 07 '22 at 12:30
  • Thank you very much for the lengthy explanation and the code snippet. This brings me to closer to what I want to achieve! – Tupsi Jun 07 '22 at 14:56