AndroidのListViewはどのようにViewを保持しているのか?
Androidでカスタムビューを作った時子のViewを欲しいと思うことがあるけどどのように実装したらいいのか悩んだことがある。
AndroidでViewをリスト表示するListViewではどのようにしているのかソースコードを見ていこう。
ListViewはViewクラスを継承している。
java.lang.Object
↳ android.view.View
↳ android.view.ViewGroup
↳ android.widget.AdapterView
↳ android.widget.AbsListView
↳ android.widget.ListView
Androidでカスタムビューを作るときはViewクラスを継承して、
onDrawメソッドでCanvasに描画して実装を行う。
そのonDrawメソッドを呼び出すのがdrawメソッドだ。
Viewクラスのdrawメソッドにはこんな記述がある
View.classの13665行目付近
/* * Draw traversal performs several drawing steps which must be executed * in the appropriate order: * * 1. Draw the background * 2. If necessary, save the canvas' layers to prepare for fading * 3. Draw view's content * 4. Draw children * 5. If necessary, draw the fading edges and restore layers * 6. Draw decorations (scrollbars for instance) */
4が怪しい。
同ファイル、13710行目付近
// Step 4, draw the children dispatchDraw(canvas); // Step 6, draw decorations (scrollbars) onDrawScrollBars(canvas);
dispatchDrawメソッドでやってるっぽい
同ファイル、8606行目付近
/** * Called by draw to draw the child views. This may be overridden * by derived classes to gain control just before its children are drawn * (but after its own view has been drawn). * @param canvas the canvas on which to draw the view */ protected void dispatchDraw(Canvascanvas){ }
オーバーライドして使うものっぽいのでListViewを調べていこうと思う
ListView 3198行目付近dispachDrawメソッド内
for(int i =0; i < count; i++){ if((headerDividers || first + i >= headerCount)&& (footerDividers || first + i < footerLimit)){ View child =getChildAt(i); bottom = child.getBottom(); // Don't draw dividers next to items that are not enabled if(drawDividers && (bottom < listBottom &&!(drawOverscrollFooter && i == count -1))){ if((areAllItemsSelectable || (adapter.isEnabled(first + i)&&(i == count -1|| adapter.isEnabled(first + i +1))))){ bounds.top = bottom; bounds.bottom = bottom + dividerHeight; drawDivider(canvas, bounds, i); }elseif(fillForMissingDividers){ bounds.top = bottom; bounds.bottom = bottom + dividerHeight; canvas.drawRect(bounds, paint); } } } }
drawDividersに関しては予想だがListViewの要素一つ一つの要素に対する枠というか分けるもの何じゃないかなと思う
final boolean drawDividers = dividerHeight >0&& mDivider !=null;
宣言を見るとこんな感じで
mDividerがDrawable型だからである
Drawable mDivider;
とりあえずgetChildAtが怪しい
ViewGroup、4746付近
/** * Returns the view at the specified position in the group. * * @param index the position at which to get the view from * @return the view at the specified position or null if the position * does not exist within the group */ public View getChildAt(intindex){ if(index<index>= mChildrenCount){ return null; } return mChildren[index]; }
同ファイル386行目
// Child views of this ViewGroup private View[] mChildren; // Number of valid children in the mChildren array, the rest should be null or not // considered as children
ということでListViewはViewGroupを継承していて、ViewGroupの仕組を利用して、配列で管理してるっぽかった
当然といえば当然なのですが最初ViewGroupを継承しているのを気づいてなかった。。
mDividerはprotected属性なので継承したクラスから書き換えられるっぽいので?枠?分けている線?を工夫したい時とかにいいかもしれない?(未確認)
takam