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

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));
}
  • 其中measureWidthormeasureHeight用来测量高度和宽度,代码如下:
//测量宽度
    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,并且调用其绘制方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值