一般在自定義控件的時候getMeasuredWidth/getMeasuredHeight它的賦值在View的setMeasuredDimension中,所以有時可以在onMeasure方法中看到利用getMeasuredWidth/getMeasuredHeight初始化別的參數。而getWidth/getHeight一直在onLayout完成后才會被賦值。一般情況下,如果都完成了賦值,兩者值是相同的.(摘自鴻洋) 參考:(Android視圖繪制流程完全解析,帶你一步步深入了解View(二))
關于View的onMeasure()、onSizeChanged()、onLayout()、onDraw()調用順序 調用順序應該是   構造函數——->onMeasure——->onSizeChanged——->onLayout——->onDraw 后面有可能 onMeasure——->onLayout——->onDraw (摘自here) 并且是在onResume之后。
需要注意的是,在setMeasuredDimension()方法調用之后,我們才能使用getMeasuredWidth()和getMeasuredHeight()來獲取視圖測量出的寬高,以此之前調用這兩個方法得到的值都會是0。
視圖大小的控制是由父視圖、布局文件、以及視圖本身共同完成的,父視圖會提供給子視圖參考的大小,而開發人員可以在xml文件中指定視圖的大小,然后視圖本身會對最終的大小進行拍板。 參考:Android視圖繪制流程完全解析,帶你一步步深入了解View(二)
onLayout、layout
Android的onLayout、layout方法講解 onLayout方法是ViewGroup中子View的布局方法,用于放置子View的位置。放置子View很簡單,只需在重寫onLayout方法,然后獲取子View的實例,調用子View的layout方法實現布局。在實際開發中,一般要配合onMeasure測量方法一起使用。
@OverridePRotected abstract void onLayout(boolean changed,            int l, int t, int r, int b);該方法在ViewGroup中定義是抽象函數,繼承該類必須實現onLayout方法,而ViewGroup的onMeasure并非必須重寫的。View的放置都是根據一個矩形空間放置的,onLayout傳下來的l,t,r,b分別是放置父控件的矩形可用空間(除去margin和padding的空間)的左上角的left、top以及右下角right、bottom值。
public void layout(int l, int t, int r, int b);該方法是View的放置方法,在View類實現。調用該方法需要傳入放置View的矩形空間左上角left、top值和右下角right、bottom值。這四個值是相對于父控件而言的。例如傳入的是(10, 10, 100, 100),則該View在距離父控件的左上角位置(10, 10)處顯示,顯示的大小是寬高是90(參數r,b是相對左上角的),這有點像絕對布局。
使用方法:
public class MyViewGroup extends ViewGroup {    // 子View的水平間隔    private final static int padding = 20;    public MyViewGroup(Context context, AttributeSet attrs) {        super(context, attrs);        // TODO Auto-generated constructor stub    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        // TODO Auto-generated method stub        // 動態獲取子View實例        for (int i = 0, size = getChildCount(); i < size; i++) {            View view = getChildAt(i);            // 放置子View,寬高都是100            view.layout(l, t, l + 100, t + 100);            l += 100 + padding;        }    }}自己的測試:
public class CircleProgressView extends View {    public CircleProgressView(Context context, AttributeSet attrs,                              int defStyleAttr) {        super(context, attrs, defStyleAttr);        int measureHeight=getMeasuredHeight();        int measureWidth=getMeasuredWidth();        int height=getHeight();        int width=getWidth();        Log.e(TAG, "333onMeasure: measureHeight=="+measureHeight+"--measureWidth=="+measureWidth+"--height=="+height+"--width=="+width );    }    public CircleProgressView(Context context, AttributeSet attrs) {        super(context, attrs);        int measureHeight=getMeasuredHeight();        int measureWidth=getMeasuredWidth();        int height=getHeight();        int width=getWidth();        int left=getLeft();        int right=getRight();        Log.e(TAG, "444構造方法: measureHeight=="+measureHeight+"--measureWidth=="                +measureWidth+"--height=="+height+"--width=="+width +"--left=="+left+"--right=="+right);    }    public CircleProgressView(Context context) {        super(context);        int measureHeight=getMeasuredHeight();        int measureWidth=getMeasuredWidth();        int height=getHeight();        int width=getWidth();        Log.e(TAG, "555onMeasure: measureHeight=="+measureHeight+"--measureWidth=="+measureWidth+"--height=="+height+"--width=="+width );    }    @Override    protected void onMeasure(int widthMeasureSpec,                             int heightMeasureSpec) {        //widthMeasureSpec和heightMeasureSpec不是一般的尺寸數值,而是將模式和尺寸組合在一起的數值。        mMeasureWidth = MeasureSpec.getSize(widthMeasureSpec);//測量后的寬度        mMeasureHeigth = MeasureSpec.getSize(heightMeasureSpec);//測量后的高度        setMeasuredDimension(mMeasureWidth, mMeasureHeigth);        int measureHeight=getMeasuredHeight();        int measureWidth=getMeasuredWidth();        int height=getHeight();        int width=getWidth();        int left=getLeft();        int right=getRight();        Log.e(TAG, "1111onMeasure: measureHeight=="+measureHeight+"--measureWidth=="                +measureWidth+"--height=="+height+"--width=="+width +"--left=="+left+"--right=="+right);        initView();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        // 繪制圓        canvas.drawCircle(mCircleXY, mCircleXY, mRadius, mCirclePaint);//圓心、半徑        // 繪制弧線        canvas.drawArc(mArcRectF, 270, mSweepAngle, false, mArcPaint);//起始角度、掃過角度、不用中心        // 繪制文字        canvas.drawText(mShowText, 0, mShowText.length(),                mCircleXY, mCircleXY + (mShowTextSize / 4), mTextPaint);//文本,文本的起始與終止,文本位置(要看對齊方式)        int measureHeight=getMeasuredHeight();        int measureWidth=getMeasuredWidth();        int height=getHeight();        int width=getWidth();        int left=getLeft();        int right=getRight();        Log.e(TAG, "2222onDraw: measureHeight=="+measureHeight+"--measureWidth=="                +measureWidth+"--height=="+height+"--width=="+width +"--left=="+left+"--right=="+right);    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        int measureHeight=getMeasuredHeight();        int measureWidth=getMeasuredWidth();        int height=getHeight();        int width=getWidth();        Log.e(TAG, "666onLayout: measureHeight=="+measureHeight+"--measureWidth=="                +measureWidth+"--height=="+height+"--width=="+width +"--left=="+left+"--right=="+right);    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        int measureHeight=getMeasuredHeight();        int measureWidth=getMeasuredWidth();        int height=getHeight();        int width=getWidth();        int left=getLeft();        int right=getRight();        Log.e(TAG, "777onSizeChanged: measureHeight=="+measureHeight+"--measureWidth=="                +measureWidth+"--height=="+height+"--width=="+width +"--left=="+left+"--right=="+right);    }    private void initView() {        float length = 0;        if (mMeasureHeigth >= mMeasureWidth) {            length = mMeasureWidth;        } else {            length = mMeasureHeigth;        }        mCircleXY = length / 2;        mRadius = (float) (length * 0.5 / 2);        mCirclePaint = new Paint();        mCirclePaint.setAntiAlias(true);        mCirclePaint.setColor(getResources().getColor(                android.R.color.holo_blue_bright));        mArcRectF = new RectF(                (float) (length * 0.1),                (float) (length * 0.1),                (float) (length * 0.9),                (float) (length * 0.9));        mSweepAngle = (mSweepValue / 100f) * 360f;        mArcPaint = new Paint();        mArcPaint.setAntiAlias(true);        mArcPaint.setColor(getResources().getColor(                android.R.color.holo_blue_bright));        mArcPaint.setStrokeWidth((float) (length * 0.1));        mArcPaint.setStyle(Style.STROKE);//描邊        mShowText = setShowText();        mShowTextSize = setShowTextSize();        mTextPaint = new Paint();        mTextPaint.setTextSize(mShowTextSize);        mTextPaint.setTextAlign(Paint.Align.CENTER);    }}log結果:
02-07 10:07:34.930 13920-13920/com.imooc.systemwidget E/ContentValues: 444構造方法:measureHeight==0--measureWidth==0--height==0--width==0--left==0--right==002-07 10:07:34.955 13920-13920/com.imooc.systemwidget E/ContentValues: 1111onMeasure:measureHeight==1692--measureWidth==1080--height==0--width==0--left==0--right==002-07 10:07:35.005 13920-13920/com.imooc.systemwidget E/ContentValues: 1111onMeasure: measureHeight==1692--measureWidth==1080--height==0--width==0--left==0--right==002-07 10:07:35.006 13920-13920/com.imooc.systemwidget E/ContentValues: 777onSizeChanged: measureHeight==1692--measureWidth==1080--height==1692--width==1080--left==0--right==108002-07 10:07:35.006 13920-13920/com.imooc.systemwidget E/ContentValues: 666onLayout: measureHeight==1692--measureWidth==1080--height==1692--width==1080--left==0--right==108002-07 10:07:35.023 13920-13920/com.imooc.systemwidget E/ContentValues: 2222onDraw: measureHeight==1692--measureWidth==1080--height==1692--width==1080--left==0--right==108002-07 10:07:35.092 13920-13920/com.imooc.systemwidget E/ContentValues: 1111onMeasure: measureHeight==1692--measureWidth==1080--height==1692--width==1080--left==0--right==108002-07 10:07:35.094 13920-13920/com.imooc.systemwidget E/ContentValues: 666onLayout: measureHeight==1692--measureWidth==1080--height==1692--width==1080--left==0--right==108002-07 10:07:35.095 13920-13920/com.imooc.systemwidget E/ContentValues: 2222onDraw: measureHeight==1692--measureWidth==1080--height==1692--width==1080--left==0--right==1080結論:
  1、調用順序應該是   構造函數——->onMeasure——->onSizeChanged——->onLayout——->onDraw——-> onMeasure——->onLayout——->onDraw   2、getMeasuredWidth()在onmeasure方法中可獲取   getWidth()在onSizeChanged、onLayout、onDraw等方法中即可獲取。   3、getWidth()=getRight()-getLeft()   4、當getMeasuredWidth()和getWidth()都有值的時候,兩者相等。
參考
Android群英傳
Android藝術探索