自定义View---------->onMeasure()的理解

自定义View---------->onMeasure()的理解_第1张图片

解析:
在Android 中Window对象通常由PhoneWindow来实现。
PhoneWindow将一个DecorView设置为整个应用窗口的根View。DecorView作为窗口界面的顶层视图,封装了一些窗口操作的通用方法。

另外:
看图片就知道,DecorView将屏幕分成两部分,第一个是TitleView,另外一个ContentView,它是一个Id为content的FragmentLayout。也就是这样理解。DecorView是一个顶层View,一般情况下它内部会包含一个竖直方向的LinearLayout,所以就分成了TitleView跟ContentView.

那么,就知道指定布局的方法不叫做setview而是setContentView了。
然后介绍代码中,当程序中onCreate(),调用setContentView()方法后,ActivitymanagerService会回调onResume()方法,此时系统就把整个DecorView添加到PhoneWindow中,并且显示出来,最后完成界面的绘制。

问题的由来 —->如果我们要去画一个图形,就必须知道它的大小和位置。同理,告诉andriod系统应该画一个多大的View,这个过程就要在onMeasure()方法中进行。
讲起onMeasure()方法又引出了一个相关的类——>MeasureSpec
类。
MeasuseSpec :测量规格

  1. SpecMode: 测量模式
    UNSPECIFIED–父容器不对View有任何限制。(少用)
    EXACTLY—父容器检测出View所需要的精确大小,这个时候View的最终大小由SpecSize所指定的值来确定。(对应于match_parent和具体数值这两个模式)。
    AT_MOST–父容器指定了一个SpecSize的值,View得大小不能超过这个值。(对应于wrap_content)

注意:View类默认的onMeasure()方法只是支持EXACTLY模式,所以如果自定义控件时候不重写onMeause()方法的话,就只能用EXACTLY模式了。如果想让自定义View支持wrap_content属性,那么就要重写onMeasure()方法。
2. SpecSize:测量大小

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // TODO Auto-generated method stub
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

点击这个super.onMeasure();可以看出—————

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    }

可以看出系统最终调用 setMeasuredDimension()方法,所以我们重写这个onMeasure()方法时候,就要把测量出的参数设置给setMeasuredDimension();

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    setMeasuredDimension(measureWidth(widthMeasureSpec), measuredHeight(heightMeasureSpec));
    }

这个是重写后的代码,可以看出,我自定义了measureWidth(widthMeasureSpec)方法和measuredHeight(heightMeasureSpec)
接下来 :
通过判断测量模式,给出不同的测量值,当specMode为EXACTLY时候,使用指定specSize即可,当是AT_MOST模式,则需要取出我们指定的大小与specSize中最小的一个来作为最后的测量值,measureWidth()方法代码如下—>基本上模板代码。


    private int measureWidth(int widthMeasureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(widthMeasureSpec);
        int specSize = MeasureSpec.getSize(widthMeasureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        }else{
            result=200;
            if(specMode==MeasureSpec.AT_MOST){
                result=Math.min(result, specSize);
            }
        }
        return result;
    }
  @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.GRAY);
        int width = getWidth();
        int height = getHeight();
        Log.e(TAG, "width : " + width + " height : " + height);
    }

Log 输出查看
05-04 03:56:19.597: E/MainActivity(2425): width : 200 height : 200

你可能感兴趣的:(android)