简介
1、ViewGroup的职责是啥?
ViewGroup相当于一个放置View的容器,并且我们在写布局xml的时候,会告诉容器(凡是以layout为开头的属性,都是为用于告诉容器的),我们的宽度(layout_width)、高度(layout_height)、对齐方式(layout_gravity)等;当然还有margin等;于是乎,ViewGroup的职能为:给childView计算出建议的宽和高和测量模式 ;决定childView的位置;为什么只是建议的宽和高,而不是直接确定呢,别忘了childView宽和高可以设置为wrap_content,这样只有childView才能计算出自己的宽和高。
2、View的职责是啥?
View的职责,根据测量模式和ViewGroup给出的建议的宽和高,计算出自己的宽和高;同时还有个更重要的职责是:在ViewGroup为其指定的区域内绘制自己的形态。
在继承ViewGroup时有三个重要的方法,下面我们就来看看:
1、onLayout方法
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
}
在我们继承ViewGroup时会在除了构造函数之外提供这个方法,我们可以看到,在ViewGroup的源代码中方法是这样定义的,也就是父类没有提供方法的内容,需要我们自己实现。
当View要为所有子对象分配大小和位置时,调用此方法
2、addView方法
public void addView(View child) {
addView(child, -1);
}
这个方法是用来想View容器中添加组件用的。我们可以使用这个方法想这个ViewGroup中添加组件。
3、getChildAt方法
public View getChildAt(int index) {
try {
return mChildren[index];
} catch (IndexOutOfBoundsException ex) {
return null;
}
}
这个方法用来返回指定位置的View。
注意:ViewGroup中的View是从0开始计数的。
demo
布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:mystyle="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.my.administrator.zdyview.ZiDingYiGroup
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="match_parent"
mystyle:myview_background="@mipmap/meinv4"
mystyle:myview_paintwidth="30dp">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#ffccff"
android:text="开始" />
<Button
android:id="@+id/button2"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#ffccff"
android:text="开始" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="300dp"
android:background="#ffccff"
android:text="开始" />
<Button
android:id="@+id/button4"
android:layout_width="200dp"
android:layout_height="150dp"
android:background="#ffccff"
android:text="开始" />
</com.my.administrator.zdyview.ZiDingYiGroup>
接下来写一个类继承ViewGroup,在onLayout方法中对几个view的位置和大小进行设置
public class ZiDingYiGroup extends ViewGroup {
private int width;
private int height;
//记得添加这两个构造器
public ZiDingYiGroup(Context context) {
super(context);
}
public ZiDingYiGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
measureChildren(width, height);//测量
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
View child1 = getChildAt(0);
View child2 = getChildAt(1);
View child3 = getChildAt(2);
View child4 = getChildAt(3);
if(child1!=null){
child1.layout(0,0,child1.getMeasuredWidth(),child1.getMeasuredHeight());//对每个view的设置是根据左上角坐标和右下角坐标确定的
}
if(child2!=null){
child2.layout(r-child2.getMeasuredWidth(),0,r,child2.getMeasuredHeight());
}
if(child3!=null){
child3.layout(0,b-child3.getMeasuredHeight(),child3.getMeasuredWidth(),b);
}
if(child4!=null){
child4.layout(r-child4.getMeasuredWidth(),b-child4.getMeasuredHeight(),r,b);
}
}
}