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;
}
网友评论