今天在自定义一个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,有这一篇就够了