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

来源:互联网 发布:什么叫淘宝直通车 编辑:程序博客网 时间:2024/05/22 05:32

UI界面架构


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

其中,

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

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

  • TitleView里包含ActionBar

实现过程,

Created with Raphaël 2.1.0ActivityActivityActivityManagerServiceActivityManagerService在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()

@Overrideprotected 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。

1 0