Android系统调用onMeasure来定义view的大小,很长时间理解不是很透彻,今天花了些时间打日志来理解它。总结如下。

        1. widthMeasureSpec和heightMeasureSpec这两个值是android:layout_width="200dp" android:layout_height="80dp"来定义的,它由两部分构成,可通过int specModeHeight = MeasureSpec.getMode(heightMeasureSpec); int specSizeHeight = MeasureSpec.getSize(heightMeasureSpec)来得到各自的值。

如果android:layout_width="wrap_content"或android:layout_width="fill_parent",哪么得到的specMode为MeasureSpec.AT_MOST,如果为精确的值则为MeasureSpec.EXACTLY。另外,specSize要想得到合适的值需要在Androidmanifest.xml中添加

        2.系统默认的onMeasure调用方法是getDefaultSize来实现,有时候在自定义控件的时候多数采用        

       

        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        setMeasuredDimension(widthSize, heightSize);

            getDefaultSize代码如下:

           

    public static int getDefaultSize(int size, int measureSpec) {        int result = size;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize =  MeasureSpec.getSize(measureSpec);        switch (specMode) {        case MeasureSpec.UNSPECIFIED:            result = size;            break;        case MeasureSpec.AT_MOST:        case MeasureSpec.EXACTLY:            result = specSize;            break;        }        return result;    }
          3.onMeasure好像会调用两次,这点我没有到代码中具体跟踪了,如果该view的父view是RelativeLayout,则其父view的onMeasur也要测量一下。我在测试中用的xml为:

<?xml version="1.0" encoding="utf-8"?>

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stub    int specModeHeight = MeasureSpec.getMode(heightMeasureSpec);    int specSizeHeight = MeasureSpec.getSize(heightMeasureSpec);    Log.e("HJJ", "****specModeHeight:" + getModeStr(specModeHeight) + ", specSizeHeight:" + specSizeHeight );    int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);setMeasuredDimension(widthSize, heightSize);}

打印出的结果为:

01-06 12:47:53.170: ERROR/HJJ(5639): ****specModeHeight:AT_MOST, specSizeHeight:71401-06 12:47:53.170: ERROR/HJJ(5639): ****specModeHeight:EXACTLY, specSizeHeight:12001-06 12:47:53.190: ERROR/HJJ(5639): ****specModeHeight:AT_MOST, specSizeHeight:71401-06 12:47:53.190: ERROR/HJJ(5639): ****specModeHeight:EXACTLY, specSizeHeight:120

如果将RelativeLayout换成LinearLayout则为

01-06 12:51:17.980: ERROR/HJJ(5779): ****specModeHeight:EXACTLY, specSizeHeight:12001-06 12:51:18.010: ERROR/HJJ(5779): ****specModeHeight:EXACTLY, specSizeHeight:120





测试用的代码如下:

package com.goso.ui.record;import com.goso.ui.R;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.util.Log;import android.view.View;public class RecordView extends View{    static final float PIVOT_RADIUS = 3.5f;    static final float PIVOT_Y_OFFSET = 10f;    static final float SHADOW_OFFSET = 2.0f;    static final float DROPOFF_STEP = 0.18f;    static final float SURGE_STEP = 0.35f;    static final long  ANIMATION_INTERVAL = 70;        Paint mPaint, mShadow;public RecordView(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stubinit(context);}public RecordView(Context context) {super(context);// TODO Auto-generated constructor stubinit(context);}private void init(Context context){   Drawable bg = context.getResources().getDrawable(R.drawable.vumeter);   setBackgroundDrawable(bg);      mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);   mPaint.setColor(Color.WHITE);   mShadow = new Paint(Paint.ANTI_ALIAS_FLAG);   mShadow.setColor(Color.argb(60, 0, 0, 0));}    private String getModeStr(int mode){    String modeStr = null;    switch (mode) {        case MeasureSpec.UNSPECIFIED:        modeStr = "UNSPECIFIED";            break;        case MeasureSpec.AT_MOST:        modeStr = "AT_MOST";        break;        case MeasureSpec.EXACTLY:        modeStr = "EXACTLY";            break;        }    return modeStr;    }    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stub//    super.onMeasure(widthMeasureSpec, heightMeasureSpec);    int specModeWidth = MeasureSpec.getMode(widthMeasureSpec);    int specSizeWidth = MeasureSpec.getSize(widthMeasureSpec);    int specModeHeight = MeasureSpec.getMode(heightMeasureSpec);    int specSizeHeight = MeasureSpec.getSize(heightMeasureSpec);    //Log.e("HJJ", "specModeWidth:" + getModeStr(specModeWidth) + ", specSizeWidth:" + specSizeWidth );    Log.e("HJJ", "****specModeHeight:" + getModeStr(specModeHeight) + ", specSizeHeight:" + specSizeHeight );//    Log.e("HJJ", "widthMeasureSpec:" + widthMeasureSpec + ", heightMeasureSpec:" + heightMeasureSpec );//    int widthSize = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);//int heightSize = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);    int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);setMeasuredDimension(widthSize, heightSize);//Log.e("HJJ", "width:" + widthSize + ", height:" + heightSize );}@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);float w = getWidth();float h = getHeight();float pivotX = w / 2;float pivotY = h - PIVOT_RADIUS - PIVOT_Y_OFFSET;float l = h * 7 / 10;float angle = (float) Math.PI * 1/ 8;float sin = (float) Math.sin(angle);float cos = (float) Math.cos(angle);float x0 = pivotX - l * cos;float y0 = pivotY - l * sin;        canvas.drawLine(x0 + SHADOW_OFFSET, y0 + SHADOW_OFFSET, pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, mShadow);        canvas.drawCircle(pivotX + SHADOW_OFFSET, pivotY + SHADOW_OFFSET, PIVOT_RADIUS, mShadow);        canvas.drawLine(x0, y0, pivotX, pivotY, mPaint);        canvas.drawCircle(pivotX, pivotY, PIVOT_RADIUS, mPaint);}}

<?xml version="1.0" encoding="utf-8"?>

理解onMeasure_第1张图片

更多相关文章

  1. ActionBar的自定义样式
  2. Android自定义对话框(Dialog)
  3. 自定义android preference组件
  4. 《第一行代码——Android》
  5. android定义全局变量
  6. android 自定义TextView实现秒级数字时钟
  7. Android之自定义适配器
  8. Android SDK 源代码编译
  9. android布局实例代码

随机推荐

  1. WebKit – WebKit For Android
  2. Button或者ImageButton的背景设为透明或
  3. Android中Message机制的灵活应用
  4. 安装 Android(安卓)1.6 SDK
  5. Android(安卓)Jetpack Compose总结
  6. Android(安卓)解析 ByteArrayInputStream
  7. Android(安卓)SystemProperties 系统属性
  8. Android应用框架无边界
  9. Android(安卓)中会出现的问题:This Androi
  10. Android(安卓)layout xml总结