Android -- 自定义布局View之 onMesasure() 方法详解

View 在屏幕上要显示出来的要经过measure(计算)和 layout(布局)


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

1、详解onMeasure()方法 参数             

               一般情况下,我们可以根据自身定义大小。在控件的父元素要放置该控件时,父元素会问子控件一个问题,“你想要多少的地方”  ,然后传入两个参数,---widthMeasureSpace  和 heightMeasureSpace.这两个控件可获得的控件以及关于这个空间描述的元数据。

              onMeasure(int widthMeasureSpec, int heightMeasureSpec)中,两个参数的作用: widthMeasureSpec和heightMeasureSpec这两个int类型的参数,看名字应该知道是跟宽和高有关系,但它们其实不是宽和高,而是由宽、高和各自方向上对应的模式来合成的一个值:其中,在int类型的32位二进制位中,31-30这两位表示模式,0~29这三十位表示宽和高的实际值.其中模式一共有三种,被定义在Android中的View类的一个内部类中:View.MeasureSpec:

            ①UNSPECIFIED:表示默认值,父控件没有给子view任何限制。------二进制表示:00
            ②EXACTLY:表示父控件给子view一个具体的值,子view要设置成这些值的大小。------二进制表示:01
            ③AT_MOST:表示父控件个子view一个最大的特定值,而子view不能超过这个值的大小。------二进制表示:10

              更好的方法是你传递view的高度和宽度到setMeasureDimension() 方法里,这样可以直接告诉父控件,需要多大的地方放置子控件。


2、代码如下:

      2.1 、方式一     

        @Override  
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
	    // 声明一个临时变量来存储计算出的测量值  
	    int resultWidth = 0;  
	  
	    // 获取宽度测量规格中的mode  
	    int modeWidth = MeasureSpec.getMode(widthMeasureSpec);  
	  
	    // 获取宽度测量规格中的size  
	    int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);  
	  
	    /* 
	     * 如果爹心里有数 
	     */  
	    if (modeWidth == MeasureSpec.EXACTLY) {  
	        // 那么儿子也不要让爹难做就取爹给的大小吧  
	        resultWidth = sizeWidth;  
	    }  
	    /* 
	     * 如果爹心里没数 
	     */  
	    else {  
	        // 那么儿子可要自己看看自己需要多大了  
	        resultWidth = mBitmap.getWidth();  
	  
	        /* 
	         * 如果爹给儿子的是一个限制值 
	         */  
	        if (modeWidth == MeasureSpec.AT_MOST) {  
	            // 那么儿子自己的需求就要跟爹的限制比比看谁小要谁  
	            resultWidth = Math.min(resultWidth, sizeWidth);  
	        }  
	    }  
	  
	    int resultHeight = 0;  
	    int modeHeight = MeasureSpec.getMode(heightMeasureSpec);  
	    int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);  
	  
	    if (modeHeight == MeasureSpec.EXACTLY) {  
	        resultHeight = sizeHeight;  
	    } else {  
	        resultHeight = mBitmap.getHeight();  
	        if (modeHeight == MeasureSpec.AT_MOST) {  
	            resultHeight = Math.min(resultHeight, sizeHeight);  
	        }  
	    }  
	  
	    // 设置测量尺寸  
	    setMeasuredDimension(resultWidth, resultHeight);  
	}  
       2.2、方式二      

     @Override  
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));  
     }  
  
    private int measureWidth(int measureSpec) {  
        int result = 0;  
        int specMode = MeasureSpec.getMode(measureSpec);  
        int specSize = MeasureSpec.getSize(measureSpec);  
  
        if (specMode == MeasureSpec.EXACTLY) {  
            // We were told how big to be  
            result = specSize;  
        } else {  
            // Measure the text  
            result = (int) mPaint.measureText(text) + getPaddingLeft() + getPaddingRight();  
            if (specMode == MeasureSpec.AT_MOST) {  
                // Respect AT_MOST value if that was what is called for by  
                // measureSpec  
                result = Math.min(result, specSize);
            }  
        }  
  
        return result;  
    }  
  
    private int measureHeight(int measureSpec) {  
        int result = 0;  
        int specMode = MeasureSpec.getMode(measureSpec);  
        int specSize = MeasureSpec.getSize(measureSpec);  
  
        mAscent = (int) mPaint.ascent();  
        if (specMode == MeasureSpec.EXACTLY) {  
            // We were told how big to be  
            result = specSize;  
        } else {  
            // Measure the text (beware: ascent is a negative number)  
            result = (int) (-mAscent + mPaint.descent()) + getPaddingTop() + getPaddingBottom();  
            if (specMode == MeasureSpec.AT_MOST) {  
                // Respect AT_MOST value if that was what is called for by  
                // measureSpec  
                result = Math.min(result, specSize);  
            }  
        }  
        return result;  
    }  


你可能感兴趣的:(Android -- 自定义布局View之 onMesasure() 方法详解)