RecyclerView 的 LayoutManager 中的 findViewByPosition 方法返回 null。

9

我想知道在RecyclerView中获取第一个item大小的正确和最早可能的时机是什么?

我尝试使用了以下代码:

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

但是它此时返回null。
3个回答

3
如果您正在使用OnGlobalLayoutListener,请记住onGlobalLayout可能会被多次调用。其中一些调用甚至可以在Layout准备就绪之前发生(通过准备就绪,我指的是您可以通过调用view.getHeight()view.getWidth()来获取View的尺寸的时刻)。因此,正确实现您的方法的方式应该是:
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);
     }
});

除此之外,您仍需确保在调用findViewByPosition(0)时,以下几点得到满足:
  1. 您的RecyclerView的适配器至少拥有一个数据元素。
  2. 位于位置0View当前在RecyclerView中可见。
请告诉我这是否解决了您的问题。如果没有,还有其他方法可以满足您的需求。

0
在我的扩展RecyclerView中,我像这样重写了onChildAttachedToWindow方法。
@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;
    }
}

我应该在哪里写这个覆盖方法? - Rushi Ayyappa

0

我曾遇到这种问题。我想在RecyclerView的第一个可见位置上默认执行点击操作。我尝试在onResume中编写了相关代码,但并没有起作用。最终我通过将代码编写在onWindowFocusChanged方法中来解决问题。

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

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接