Android--カスタムレイアウトViewのonMesasure()メソッドの詳細

4505 ワード

Viewが画面に表示されるのはmeasure(計算)とlayout(レイアウト)
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    	super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

1.onMeasure()メソッドパラメータを詳しく解く
一般的には、自分自身に基づいてサイズを定義することができます.コントロールの親要素がコントロールを配置するとき、親要素はサブコントロールに「どのくらいの場所がほしいか」と質問し、2つのパラメータ、すなわちwidthMeasureSpaceとheightMeasureSpaceを入力します.この2つのコントロールで得られるコントロールと、この空間について説明するメタデータ.
onMeasure(int widthMeasureSpec,int heightMeasureSpec)では、2つのパラメータの役割:widthMeasureSpecとheightMeasureSpecの2つのintタイプのパラメータは、名前を見ると幅と高さに関係していることがわかるはずですが、それらは実際には幅と高さではなく、幅、高さとそれぞれの方向に対応するモードで合成された値です.ここで、intタイプの32ビットのバイナリビットでは、31-30の2桁はパターンを表す、0~29の30桁は幅と高さの実値を表す.このうちモードは全部で3種類あり、AndroidのViewクラスの1つの内部クラスに定義されている: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;  
    }