Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView LayoutManager findViewByPosition returns null

I'm interested in what is the right and first possible moment to get size of first item of RecyclerView?

I've tried to use:

recyclerView.setLayoutManager(new GridLayoutManager(context, 2));
recyclerView.setAdapter(new MyDymmyGridRecyclerAdapter(context));
recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
     @Override
     public void onGlobalLayout() {
         recyclerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
         View firstRecyclerViewItem = recyclerView.getLayoutManager().findViewByPosition(0);
         // firstRecyclerViewItem is null here
     }
});

but it returns null at this moment.

like image 365
AlexKorovyansky Avatar asked Apr 11 '15 14:04

AlexKorovyansky


People also ask

Why is findviewbyposition not working in recyclerview?

It's because the population of the RecyclerView by the Adapter is asynchronous. You may launch an event when the adapter finish to populate the RecyclerView to be sure that findViewByPosition returns something to you.

What is a recyclerview LayoutManager?

A RecyclerView.LayoutManager implementations that lays out items in a grid. A LayoutManager is responsible for measuring and positioning item views within a RecyclerView as well as determining the policy for when to recycle item views that are no longer visible to the user.

How does recyclerview's onlayout () method work?

When measure is complete and RecyclerView's onLayout (boolean, int, int, int, int) method is called, RecyclerView checks whether it already did layout calculations during the measure pass and if so, it re-uses that information.

Why does LayoutManager return null when setadapter is called?

Might be null if setAdapter (RecyclerView.Adapter) is called with null. Called to populate focusable views within the RecyclerView. The LayoutManager implementation should return true if the default behavior of addFocusables (java.util.ArrayList, int) should be suppressed.


1 Answers

If you're using OnGlobalLayoutListener you should remember onGlobalLayout can be called multiple times. Some of those calls can happen even before Layout is ready (and by ready I mean the moment when you can get dimensions of a View by calling view.getHeight() or view.getWidth()). So the proper way of implementing your approach would be:

recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
     @Override
     public void onGlobalLayout() {
         int width = recyclerView.getWidth();
         int height = recyclerView.getHeight();
         if (width > 0 && height > 0) {
             if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
                 recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
             } else {
                 recyclerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
             }
         }

         View firstRecyclerViewItem = recyclerView.getLayoutManager().findViewByPosition(0);
     }
});

Apart from that you still need to be sure that at the time of findViewByPosition(0) call:

  1. Your RecyclerView's Adapter has at least one data element.
  2. View at position 0 is currently visible in RecyclerView

Tell me if that fixes your issue, if not there is still another way of doing what you need.

like image 169
Bartek Lipinski Avatar answered Oct 22 '22 07:10

Bartek Lipinski