您的位置:首页 > 移动开发 > Android开发

Android群英传---View、ViewGroup的测量和绘制

2016-08-17 11:13 453 查看

View的测量

系统通过
onMeasure()
对View进行测量

1.系统提供
MeasureSpec
类帮助测量
View

MeasureSpec是
32bit
的int值,期中
高2bit
为测量的模式,
低30位
为测量的大小。用于提高效率

测量的模式如下:

1. ++EXACTLY++

精确值模式:

控件属性
width or height
设置为具体数值,如
100dp
,或者指定为
match_parent
属性,就是该模式。

2. ++AT_MOST++

最大值模式:

控件属性
width or height
设置为
wrap_content
。此时控件的尺寸不超过父控件允许的最大尺寸即可。

3. ++UNSPECIFIED++

不指定大小的测量模式,View想多大就多大,通常情况下载绘制自定义View时才会使用。

View类默认的
onMeasure()
方法只支持
EXACTLY
,。

自定义控件想使用
wrap_content
就必须重写
onMeasure()
来指定
wrap_content
时的大小。

*

2. View测量实例

onMeasure()如下

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}


可以发现,本质上系统最终会调用
setMeasuredDimension(int measuredWidth, int measuredHeight)
,将测量之后的宽高值设置进去。所以重写
onMeasure()
最终是将测量后的宽高值设置给该方法。

因此重写onMeasure()方法如下

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}


其中
measureWidth
or
measureHeight
用来测量高度和宽度,代码如下:

//测量宽度
private int measureWidth(int widthMeasureSpec){
//提取出模式以及尺寸
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);

int alone  = 0;

//精确值模式: 例如200dp or match_parent
if(specMode == MeasureSpec.EXACTLY){
alone = specSize;
}else{
alone = 200; //?????
//最大值模式: wrap_parent
if(specMode == MeasureSpec.AT_MOST){
alone = Math.min(alone, specSize);
}
}
return alone;
}


//测量高度
private int measureHeight(int heightMeasureSpec){
//提取出模式以及尺寸
int specMode = MeasureSpec.getMode(heightMeasureSpec);
int specSize = MeasureSpec.getSize(heightMeasureSpec);

int result  = 0;

//精确值模式: 例如200dp or match_parent
if(specMode == MeasureSpec.EXACTLY){
result = specSize;
}else{
result = 200; //?????
//最大值模式: wrap_parent
if(specMode == MeasureSpec.AT_MOST){
result = Math.min(result, specSize);
}
}
return result;
}


其中
result = 200;
表示在
wrap_content
属性的时候获得默认的
200px
作为长度

View的绘制

通常通过继承View并且重写它的
onDraw()
方法来完成绘图。

onDraw()
中有一个参数,就是
Canvas canvas
对象。使用这个
Canvas
对象就可以进行绘图了,其他对象需要用代码创建。

Canvas canvas = new Canvas(bitmap);


为什么要传入bitmap?

不传入bitmap也不会报错,但是不要这么做。
bitmap
是用来存储所有绘制在
Canvas
上的像素信息。之后所有的
Canvas.drawXXX
都在该bitmap上。

Bitmap bitmap1 = Bitmap.createBitmap(new int[]{R.color.colorAccent, R.color.colorPrimary}, 200, 100, Bitmap.Config.RGB_565);

canvas.drawBitmap(bitmap1, 0,0,null);


ViewGroup的测量

ViewGroup用于管理子View,在控制显示大小时,如果ViewGroup设置为wrap_content时,就需要遍历所有子View来确定大小

遍历子View就是调用其onMeasure方法进行测量。View摆放位置就是调用ViewGroup的layout方法,其内部遍历子View的layout方法来指定具体位置。

自定义ViewGroup

通常重写
onLayout()
控制子
View
的显示位置。

如果支持
wrap_content
,必须重写
onMeasure()


ViewGroup一般不需要绘制

设置ViewGroup背景颜色的时候,调用
onDraw()
方法

ViewGroup会调用
dispatchDraw()
方法来绘制子View,其通过遍历子View,并且调用其绘制方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android