ViewGroup中的onLayout方法的理解
阿新 • • 發佈:2018-11-30
今天在自定義一個ViewGroup的時候出現了一個這樣問題,事後分析是因為自己對ViewGroup中的onLayout方法和其中子View的layout方法的理解不足導致的。
我要實現的效果是做一個類似LinearLayout垂直排列子View的ViewGroup,在ViewGroup中onMeasure方法中測量完ViewGroup的大小以後進開始擺放子View了,onLayout的開始的程式碼如下:
@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { int count = getChildCount(); int curHeight = top; for (int i = 0 ; i < count ; i++){ View childView = getChildAt(i); int height = childView.getMeasuredHeight(); int width = childView.getMeasuredWidth(); childView.layout(left,curHeight,right + width,bottom + height); curHeight += height; } }
程式碼如下,測試了一下發現當自定義的ViewGroup和其他的View並列的時候就會出現問題,如果子佈局中只有自定義的ViewGroup自己,頁面顯示是沒有問題的。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:background="#e41212" android:layout_width="match_parent" android:layout_height="50dp" android:text="按鈕" /> <!--自定義ViewGroup--> <com.emm.datastructure.custom_view.ZHViewGroup android:background="#b42666" android:layout_width="wrap_content" android:layout_height="wrap_content"> <Button android:layout_width="wrap_content" android:layout_height="100dp" android:text="btn" /> </com.emm.datastructure.custom_view.ZHViewGroup> </LinearLayout>
經過分析發現是ViewGroup中的onLayout程式碼寫錯了,正確的onLayout方法如下:
/** *引數左上右下,是指以螢幕的左上角為座標原點的座標 */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { int count = getChildCount(); //記錄當前高度位置。 //因為在擺放子View的時候,子View的layout方法是以ViewGroup的左上角為座標原點來測量的,所以第一個子View的高度應該為0。 int curHeight = 0; //注意此處和上面錯誤的不一樣 for (int i = 0 ; i < count ; i++){ View childView = getChildAt(i); int height = childView.getMeasuredHeight(); int width = childView.getMeasuredWidth(); childView.layout(left,curHeight,right + width,bottom + height); curHeight += height; } }
上面的註釋寫的很清楚,是因為對ViewGroup中onLayout方法中的引數理解錯誤導致的,如果此處curHeight
欄位填寫top
引數,那麼ViewGroup中的第一個子View肯定會向下移動上面並列的View的高度。
參考文章:自定義View,有這一篇就夠了