View 与ViewGroup的测量与绘制
1.View的测量
测量的三中模式
EXACTLY
精确值模式 将layout_width layout_height 属性指定为具体数值 如android:layout_width="100dp",或者指定为match_parent属性时 使用的是EXACTLY模式
AT_MOST
最大值模式 wrap_content 控件大小随子控件或者内容的变化而变化,此时控件的尺寸只要不超过父控件允许的最大尺寸即可
UNSPECIFIED
不指定大小测量方式,View想多大就多大,通常情况下在绘制自定义View时才会使用
所以说在onMeasure方法重写中 需要利用setMeasuredDimension(int width,int height);对宽高进行设置
重新定义宽度:
private intmeasureWidth(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;
}
2.View的绘制
onDraw(Canvas canvas)方法
在Canvas(画板)上绘制
如果不是所传参数,还要用到Canvas对象就需要Canvas canvas = new Canvas(bitmap);
不传bitmap虽然不会报错,但一般不这么做。这种方式创建了Canvas对象后,后面调用的所有canvas.drawXXX方法都会发生在bitmap上
例如以下代码:
canvas.drawBitmap(bitmap1,0,0,null);
canvas.drawBitmap(bitmap2,0,0,null);
Canvas mCanvas = new Canvas(bitmap2);//将第二个位图装载到新的画布对象中
mCanvas.drawXXX的绘制效果就会作用在bitmap2上。
3.ViewGroup的测量
ViewGroup会管理子View,其中一个管理项目就是负责子View的显示大小。当ViewGroup的大小为wrap_content时,ViewGroup就会对子View进行遍历,获取所有子View的大小,来决定自己的大小(对View的测量就是在这里发生的)。在其他模式下会根据具体的指示值来设置自身的大小。
ViewGroup测量完毕,就会把View放在相应的位置上,就是View的Layout过程。ViewGroup执行Layout过程同样是使用遍历来调用子View的Layout方法,指定其具体显示位置来决定布局位置
自定义ViewGroup时,通常会重写onLayout的方法控制子View的显示逻辑。如果支持wrap_content属性就必须重写onMeasure方法,这一点与View相同
4.ViewGroup的绘制
ViewGroup通常不需要绘制,应为他本身没有需要绘制的东西。如果不是指定ViewGroup的背景颜色,ViewGroup的onDraw方法就不会被调用。但是ViewGroup会使用dispatchDraw()方法遍历绘制所有子View。