Why does LinearLayoutManager.childAt() returns null?

209 Views Asked by At

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

1

There are 1 best solutions below

3
On BEST ANSWER

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.