1. 程式人生 > >RecyclerView的基本用法 (五)

RecyclerView的基本用法 (五)

這一次,我用一個極簡的程式碼段來揭開layoutmanager的神祕面紗,而這段程式碼也僅僅是拿出了基本骨架,而該骨架是在自定義layoutmanager必須要有的,卻只有這些骨架還遠遠不夠,看了很多類似的專案原始碼也發現對每個子view進行相應的layout就是必不可少的需要自己定義,程式碼如下:

@Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
    int itemCount = getItemCount();
    if (itemCount == 0) {
      removeAllViews();
      return;
    }

    removeAllViews();

    mLastVisiblePosition = 0;
    //boolean isLastLayoutedView;
    int childLeft;
    int childTop;
    if (getChildCount() == 0) {
      childLeft = childTop = 0;
    }else {
      final View topChild = getChildAt(0);
      childLeft = getDecoratedLeft(topChild);
      childTop = getDecoratedTop(topChild);
    }

    do {
      View view = recycler.getViewForPosition(mLastVisiblePosition);
      addView(view);

      //isLastLayoutedView = mLayouter.isLastLaidOutView(view);
      layoutDecorated(view, childLeft, childTop, 200, childTop + 100);
      mLastVisiblePosition++;
      childTop += 100;
    } while (mLastVisiblePosition < itemCount);
  }


與viewgroup一樣,重點還是在layoutDecorated(view, childLeft, childTop, 200, childTop + 100);這個方法上。而該方法看看原始碼就知道其作用就是view.layout,唯一卻別也就是decorated這個關鍵字,這裡就不詳細解釋了,瞭解recyclerview的都知道其作用,後面會著重講decorate在recyclerview中的地位,程式碼如下:

public void layoutDecorated(View child, int left, int top, int right, int bottom) {
            final Rect insets = ((LayoutParams) child.getLayoutParams()).mDecorInsets;
            child.layout(left + insets.left, top + insets.top, right - insets.right,
                    bottom - insets.bottom);
        }


那麼在onLayoutChildren方法裡,用遍歷的方式對所有子view進行layout這種方式已經不新鮮了,因為凡是實現過自定義viewgroup的人都知道,所以也就不再贅述了。而這裡需要強調幾點:

1 與自定義view一樣,只要目標明確,實現其實並不複雜,但頭疼的最多的地方就是細節,因為需要處理的細節太多了,必須要面面俱到,而這裡也是最容易增長bug的地方。

2 何時attach何時detach,何時remove何時recycle,需要根據需求而定的,而這是layoutmanager的職責所在,所以這些需要自己定義。

3 這一點純屬個人意見,在我看來,自定義layoutmanager的使用場景其實並不多,因為多數的需求完全可以用其他的簡便方式所代替,甚至是其他方式來做會更好。而它的專屬領域在於,子view數量不定且有列表性質,如果用自定義view來做,那就需要做一套view的回收機制倒不是說不可以詳情在github上twowayview裡有,但本著不重複造輪子的原則不如自定義layoutmanager;而很多時候一些需求又完全可以通過viewtype或者放到單個子view裡去處理等等方式來實現,所以這時肯定是放到單個子view中去處理會更好。但特殊情況特殊處理。

以上就是自定義layoutmanager的所有我個人的理解,可商榷的地方肯定會不少,但最主要的還是對這幾個開源專案的深入研究,很多地方會有很多坑,比如PreLayout。就算沒有機會用到,但對recyclerview的理解肯定會加深不少。