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

本文详细解析了Android中自定义布局View的onMeasure()方法,探讨了widthMeasureSpec和heightMeasureSpec参数的含义及模式类型,包括UNSPECIFIED、EXACTLY和AT_MOST。并介绍了如何通过setMeasureDimension()方法设定视图尺寸。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


<span style="font-size:18px;">    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    	super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }</span>

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 、方式一     

<span style="font-size:18px;">        @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);  
	}  </span>
       2.2、方式二     

<span style="font-size:18px;">     @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;  
    }  </span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值