第三章 控件架构与自定义控件详解

3.1 控件架构

  • 通过ViewGroup整个控件组成一个控件树。

Activity->PhoneWindow->DecorView->Title和ContentView(contentView本质上为一个Framelayout)

  • DecorView将要显示的内容呈现在了PhoneWindow上。

所有View的监听事件都是通过WindowManagerService来进行接收。
当程序在onCreate()中调用setContentView()之后ActivityManagerService会回调onResume()方法,此时系统才会把整个DecorView添加到PhoneWindow中,并显示出来,从而最终完成界面的绘制。所以requestWindowFeature(Window.Feature_NO_TITLE)要在setContentView之前调用。

3.2 View的测量

说到测量首先得说下MeasuerSpec的作用:

1 MeasureSpec封装了父布局传递给子View的布局要求。
2 MeasureSpec可以表示宽和高
3 MeasureSpec由size和mode组成

测量模式分为三种:
  • EXACTLY : width或height为具体值时,或者为match_parent时。

  • AT_MOST:width或height为wrap_content时。

  • UNSPECIFIED:不指定,View想多大就多大,自定义View时才有机会使用。

注意:View类默认的onMeasure()方法只支持EXACTLY模式,所以在自定义控件的时候必须重写onMeasure()方法指定wrap_content时的大小,才能使View支持wrap_content属性。

  • onMeasure()最终调用setMeasuredDimension(measureWidth(widthMeasureSpec), measureWidth(heightMeasureSpec))方法。
measureWidth()方法的基本模板:
private int measureWidth(int measureSpec){
    int result =0;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    if(specMode == MeasureSpec.EXACTLY){
        result = specSize;
    }else{
        result =200;//需要具体测量,这里给定具体值
        if(specMode == MeasureSpec.AT_MOST){
        result = Math.min(result, specSize);//取最小值
       }
    }
    return result;
}

你可能感兴趣的:(第三章 控件架构与自定义控件详解)