AlexKorovyansky
AlexKorovyansky

Reputation: 4953

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.

Upvotes: 9

Views: 7735

Answers (3)

Sabya
Sabya

Reputation: 978

I had this type of problem. I want to perform click by default on the first visible position of the recylerview. I wrote the code for that on onResume but it did not work. I solved my problem by writting the code in onWindowFocusChanged method

    @Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    if(isCalledForTheFirstTime)
    {
        LinearLayoutManager manager= (LinearLayoutManager) rcViewHeader.getLayoutManager();
        int pos= manager.findFirstCompletelyVisibleItemPosition();


        View view=manager.findViewByPosition(pos);
        if(view!=null)
        {
            view.performClick();
        }

        // change the vaule so that it would not be call in case a pop up appear or disappear 
        isCalledForTheFirstTime=false;
    }

}

Upvotes: 0

jayeffkay
jayeffkay

Reputation: 1299

In my extended RecyclerView I override onChildAttachedToWindow like this

@Override
public void onChildAttachedToWindow(View child) {
    super.onChildAttachedToWindow(child);

    if (!mIsChildHeightSet) {
        // only need height of one child as they are all the same height
        child.measure(0, 0);
        // do stuff with child.getMeasuredHeight()
        mIsChildHeightSet = true;
    }
}

Upvotes: 0

Bartek Lipinski
Bartek Lipinski

Reputation: 31458

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.

Upvotes: 3

Related Questions