Android学习笔记(一) View、ViewGroup的测量绘制

UI界面架构

由大到小,外一层包着里一层
Activity >>PhoneWindow>>DecorView>>TitleView+ContentView

其中,

  • DecorView是整个应用窗口的根View;

  • ContentView是一个ID为content的FrameLayout,*.xml布局文件就是设置在里面;

  • TitleView里包含ActionBar

实现过程,

Created with Raphaël 2.1.0 Activity Activity ActivityManagerService ActivityManagerService 在onCreate()方法中调用setContentView()方法 把DecorView添加到PhoneWindow中, 绘制显示界面 回调onResume()方法

View的测量

  • 在onMeasure()方法中进行测量
  • Android系统给我们提供了一个32位int值(高2位是测量位,低30位是测量大小)的MeasureSpec类,利用二进制的位运算提高计算效率。

测量模式

  1. EXACTLY(精确模式):具体数值的大小或match_parent(onMeasure()方法模式使用该模式,想使用其他模式,就必须重写方法);
  2. AT_MOST(最大值模式):wrap_content;
  3. UNSPECIFIED(不指定大小的测量模式):View想多大就多大,通常在绘制自定义View的时候才会用;

写个例子

重写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的绘制

测量好一个View之后,可以简单的重写onDraw()方法来绘制View,这里要用到画布类Canvas。
绘制View有两种方式:
- 重写onDraw()方法,使用方法传入参数Canvas canvas对象,使用这个来绘图。
- 在其他地方,通常需要实例化创建一个Canvas对象,代码如下:

Canvas canvas=new Canvas(bitmap);// 这个步骤为装载画布,bitmap存储像素信息

ViewGroup的测量

ViewGroup管理其子View,其中负责子View的显示大小。
测量:ViewGroup的大小为wrap_content(即AT_MOST)时,ViewGroup对子View遍历,获取所有子View的大小(调用子View的Measure方法获取测量结果),从而决定自己的大小。其他模式下会通过具体的指定值来设置大小。
Layout过程:测量后需要将子View放到合适的位置。遍历子View的Layout方法,并制定其具体显示的位置,从而来具体决定其布局位置(可以重写onLayout()来控制子View的显示位置的逻辑,如果需要支持wrap_content属性,需重写onMeasure())。

ViewGroup的绘制

ViewGroup通常情况是不需要绘制的。
当指定背景颜色时,onDraw方法会被调用。
ViewGroup可以通过dispatchDraw方法来(遍历调用子View的onDraw方法)绘制子View。

你可能感兴趣的:(android)