1,概述
ViewGroup相当于一个放置VIew的容器,并且我们再写布局xml的时候,会高绿容器(凡是以layout为开头的属性,都是为用于告诉容器的)我们的宽度(layout_width)、高度(layout_height)、对齐方式(layout_gravity)等,当然还有margin
于是,ViewGroup的职能是:给chlidView计算出建议的宽和高和测量模式,决定childView的位置(为什么是建议呢,不是直接给出高和宽,因为childView宽和高可以设置为为wrap_content,这样只有childView才能计算出自己的宽度和高度),
还有个更重要的职责是:在VIewGroup为其指定的区域内绘制自己的形态
ViewGroup和LayoutParams之间的关系?
大家可以回忆一下,当在LinearLayout中写childView的时候,可以写layout_gravity,layout_weight属性;在RelativeLayout中的childView有layout_centerInParent属性,却没有layout_gravity,layout_weight,这是为什么呢?这是因为每个ViewGroup需要指定一个LayoutParams,用于确定支持childView支持哪些属性,比如LinearLayout指定LinearLayout.LayoutParams等。如果大家去看LinearLayout的源码,会发现其内部定义了LinearLayout.LayoutParams,在此类中,你可以发现weight和gravity的身影。
2,View的3种测量模式
EXACTLY:表示设置了精确的值,一般当childView设置其宽,高为精确值,match_parent时,ViewGroup会将其设置为EXACTLY
AT_MOST:表示字布局被限制在一个最大值内,一般当childView设置其宽,高为wrap_content时,
UNSPECIFIED:表示子布局想要多大就多大,一般出现在AdapterView的Item的HeightMode中,ScrollView的childView的heightMode中;此种模式比较少见。
3,从API角度进行浅析
View的根据ViewGroup传人的测量值和模式,对自己宽高进行确定(onMeasure中完成),然后在onDraw中完成对自己的绘制。
ViewGroup需要给View传入view的测量值和模式(onMeasure中完成),而且对于此ViewGroup的父布局,自己也需要在onMeasure中完成对自己宽和高的确定。此外,需要在onLayout中完成对其childView的位置的指定。
4实战
需求:我们定义一个ViewGroup,内部传入四个childView,分别依次显示在四个角角
首先,我们确定该ViewGroup的LayoutParams
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(mContext,attrs);
}
然后我们再onMeasure方法中确定ViewGroup的大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取此ViewGroup上级容器所推荐的宽度和高度,及其计算模式
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
int sizeheight = MeasureSpec.getSize(heightMeasureSpec);
//计算出所有childView的宽和高
measureChildren(widthMeasureSpec,heightMeasureSpec);
//如果是wrap_content,设置宽和高
int wdith;
int height;
mChildCount = getChildCount();
int cWidth=0;
int cHeight=0;
//两者取最大
int tWidth=0;
int bWidth=0;
//两者取最大
int lHeight=0;
int rHeight=0;
MarginLayoutParams layoutParams = null;
for(int i = 0 ;i < mChildCount;i++){
View child = getChildAt(i);
cWidth = child.getMeasuredWidth();
cHeight = child.getMeasuredHeight();
layoutParams =(MarginLayoutParams) child.getLayoutParams();
if(i == 0 || i ==1){
tWidth+=(cWidth+layoutParams.leftMargin+layoutParams.rightMargin);
}
if(i == 2 || i == 3){
bWidth +=(cWidth+layoutParams.leftMargin+layoutParams.rightMargin);
}
if(i == 0 || i == 2){
lHeight += (cHeight+layoutParams.topMargin+layoutParams.bottomMargin);
}
if(i== 1 || i == 3){
rHeight += (cHeight+layoutParams.topMargin+layoutParams.bottomMargin);
}
wdith = Math.max(tWidth,bWidth);
height = Math.max(lHeight,rHeight);
setMeasuredDimension((widthMode == MeasureSpec.EXACTLY)? sizeWidth:wdith
,(heightMode == MeasureSpec.EXACTLY)? sizeheight:height);
}
}
然后在onLayout方法中,对每一个childView确定位置
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
mChildCount = getChildCount();
int cWdith = 0;
int cHeight = 0;
MarginLayoutParams layoutParams = null;
for(int i = 0; i< mChildCount ;i++){
View childView = getChildAt(i);
cWdith = childView.getMeasuredWidth() ;
cHeight = childView.getMeasuredHeight();
layoutParams =(MarginLayoutParams) childView.getLayoutParams();
int cl = 0, ct = 0, cr = 0,cb = 0;
switch (i){
case 0:
cl=layoutParams.leftMargin;
ct=layoutParams.rightMargin;
break;
case 1 :
cl = getWidth()-cWdith-layoutParams.rightMargin;
ct = layoutParams.topMargin;
break;
case 2:
cl = layoutParams.rightMargin;
ct = getHeight()-cHeight-layoutParams.bottomMargin;
break;
case 3:
cl = getWidth()-cWdith-layoutParams.rightMargin;
ct = getHeight()-cHeight-layoutParams.bottomMargin;
break;
}
cr = cl+cWdith;
cb = ct+cHeight;
childView.layout(cl,ct,cr,cb);
}
}
布局:
<com.example.zhy_custom_viewgroup.CustomImgContainer xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#AA333333" >
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#FF4444"
android:gravity="center"
android:text="0"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#00ff00"
android:gravity="center"
android:text="1"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#ff0000"
android:gravity="center"
android:text="2"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#0000ff"
android:gravity="center"
android:text="3"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
</com.example.zhy_custom_viewgroup.CustomImgContainer>
布局2:
<com.example.zhy_custom_viewgroup.CustomImgContainer xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#AA333333" >
<TextView
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#E5ED05"
android:gravity="center"
android:text="0"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#00ff00"
android:gravity="center"
android:text="1"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#ff0000"
android:gravity="center"
android:text="2"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
<TextView
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#0000ff"
android:gravity="center"
android:text="3"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:textStyle="bold" />
</com.example.zhy_custom_viewgroup.CustomImgContainer>
本文出自:http://blog.csdn.net/lmj623565791/article/details/38339817 , 本文出自:【张鸿洋的博客】
在计算childView的时候,鸿洋大大的博客上有一个小错误,我自己改了