由大到小,外一层包着里一层
Activity >>PhoneWindow>>DecorView>>TitleView+ContentView
其中,
DecorView是整个应用窗口的根View;
ContentView是一个ID为content的FrameLayout,*.xml布局文件就是设置在里面;
TitleView里包含ActionBar
实现过程,
重写onMeasure()
@Override
protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec)
{
//super.onMeasure(widthMeasureSpec,heightMeasureSpec);
// 我们自定义了两个方法measureWidth()和measureHeight()
setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));
}
以我们自定义的方法measureWidth()为例子,measureHeight()的实现和它差不多,在这里就不写了
private int measureWidth(int measureSpec)
{
int result=0;
// 第一步:从MeasureSpec中提取出具体的测量模式和大小
int specMode=MeasureSpec.getMode(measureSpec);
int specSize=MeasureSpec.getSize(measureSpec);
// 判断模式
if(specMode==MeasureSpec.EXACTLY)
{
result=specSize;
}
else
{
result=200;// wrap_content时的默认值
if(specMode==MeasureSpec.AT_MOST)
{// 比较大小,取最小
result=Math.min(result,specSize);
}
}
return result;
}
重写onMeasure()方法的目的就是为了能够给View一个wrap_content属性下的默认大小,当指定wrap_content属性时,View就获得了一个默认值200px,而不是填充父布局了。
测量好一个View之后,可以简单的重写onDraw()方法来绘制View,这里要用到画布类Canvas。
绘制View有两种方式:
- 重写onDraw()方法,使用方法传入参数Canvas canvas对象,使用这个来绘图。
- 在其他地方,通常需要实例化创建一个Canvas对象,代码如下:
Canvas canvas=new Canvas(bitmap);// 这个步骤为装载画布,bitmap存储像素信息
ViewGroup管理其子View,其中负责子View的显示大小。
测量:ViewGroup的大小为wrap_content(即AT_MOST)时,ViewGroup对子View遍历,获取所有子View的大小(调用子View的Measure方法获取测量结果),从而决定自己的大小。其他模式下会通过具体的指定值来设置大小。
Layout过程:测量后需要将子View放到合适的位置。遍历子View的Layout方法,并制定其具体显示的位置,从而来具体决定其布局位置(可以重写onLayout()来控制子View的显示位置的逻辑,如果需要支持wrap_content属性,需重写onMeasure())。
ViewGroup通常情况是不需要绘制的。
当指定背景颜色时,onDraw方法会被调用。
ViewGroup可以通过dispatchDraw方法来(遍历调用子View的onDraw方法)绘制子View。