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的理解肯定會加深不少。