自定义viewon之Measure

                                               自定义view随笔填坑-----onMeasure


子view的大小由父view的measureSpec和子view的layoutparams共同决定。

view类的onMeasure():

protected  void  onMeasure(int  widthMeasureSpec,int  heightMeasureSpec) {

      setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));

}

widthMeasureSpec以及heightMeasureSpec的取值范围是由父view决定的

private void performTraversals() {

// cache mView since it is used so much below...

final  View host = mView;

// ...省略大量代码

WindowManager.LayoutParams lp =mWindowAttributes;intdesiredWindowWidth;

int desiredWindowHeight;

intchildWidthMeasureSpec;

intchildHeightMeasureSpec;

// ...省略大量代码

childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);

childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);

// ...省略大量代码

// 根据前面的分析可知, 这里的 host 就是 DecorView

host.measure(childWidthMeasureSpec, childHeightMeasureSpec);

// ...省略大量代码

}



private  int  getRootMeasureSpec(intwindowSize,introotDimension) {

int  measureSpec;

switch(rootDimension) {

case   ViewGroup.LayoutParams.MATCH_PARENT:

// Window can't resize. Force root view to be windowSize.

measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);

break;

case    ViewGroup.LayoutParams.WRAP_CONTENT:

// Window can resize. Set max size for root view.

measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);

break;

default:

// Window wants to be an exact size. Force root view to be that size.

measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);

break;

}

return   measureSpec;

}

一般自定view的时候,要在onMeasure对wrap_content进行处理

protected  void  onMeasure(intwidthMeasureSpec,intheightMeasureSpec) {

super.onMeasure(widthMeasureSpec , heightMeasureSpec);

int  widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);

int   widthSpceSize =MeasureSpec.getSize(widthMeasureSpec);

int   heightSpecMode=MeasureSpec.getMode(heightMeasureSpec);

int  heightSpceSize=MeasureSpec.getSize(heightMeasureSpec);if(widthSpecMode==MeasureSpec.AT_MOST&heightSpecMode==MeasureSpec.AT_MOST){

setMeasuredDimension(mWidth, mHeight);

}else  if(widthSpecMode==MeasureSpec.AT_MOST){

setMeasuredDimension(mWidth, heightSpceSize);

}else  if(heightSpecMode==MeasureSpec.AT_MOST){

setMeasuredDimension(widthSpceSize, mHeight);

}

}


在viewGroup中测量子view时会调用到measureChildWithMargins(),或者与之类似的方法

// @param child   子view

// @param parentWidthMeasureSpec  父容器(比如LinearLayout)的宽的measurerSpec

// @params withUsed 父容器在水平方向已经占用的空间大小

//@params parentHeightMeasureSpec 父容器的高的MeasureSpec

//@params heightUsed 父容器在垂直方向已经占用的空间大小

protected  void  measureChildWithMargins(View child,intparentWidthMeasureSpec,intwidthUsed,intparentHeightMeasureSpec,intheightUsed) {

final  MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) child.getLayoutParams();

finalintchildWidthMeasureSpec =

getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft + mPaddingRight +

lp.leftMargin + lp.rightMargin + widthUsed, lp.width);

final  int  childHeightMeasureSpec =

getChildMeasureSpec(parentHeightMeasureSpec, mPaddingTop + mPaddingBottom +

lp.topMargin + lp.bottomMargin + heightUsed, lp.height);

child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

}



public static int getChildMeasureSpec(intspec,intpadding,intchildDimension) { 

int  specMode = View.MeasureSpec.getMode(spec);

intspec  Size = View.MeasureSpec.getSize(spec);

int  size = Math.max(0, specSize - padding);

int  resultSize =0;

int  resultMode =0;

switch(specMode) {caseView.MeasureSpec.EXACTLY:if(childDimension >=0) {

resultSize = childDimension;

resultMode = View.MeasureSpec.EXACTLY;

}elseif(childDimension == LayoutParams.MATCH_PARENT) {


resultSize = size;

resultMode = View.MeasureSpec.EXACTLY;

}elseif(childDimension == LayoutParams.WRAP_CONTENT) {

resultSize = size;

resultMode = View.MeasureSpec.AT_MOST;

}break;caseView.MeasureSpec.AT_MOST:if(childDimension >=0) {

resultSize = childDimension;

resultMode = View.MeasureSpec.EXACTLY;

}elseif(childDimension == LayoutParams.MATCH_PARENT) {

resultSize = size;

resultMode = View.MeasureSpec.AT_MOST;

}elseif(childDimension == LayoutParams.WRAP_CONTENT) {

resultSize = size;

resultMode = View.MeasureSpec.AT_MOST;

}break;caseView.MeasureSpec.UNSPECIFIED:if(childDimension >=0) {

resultSize = childDimension;

resultMode = View.MeasureSpec.EXACTLY;

}elseif(childDimension == LayoutParams.MATCH_PARENT) {

resultSize = View.sUseZeroUnspecifiedMeasureSpec ?0: size;

resultMode = View.MeasureSpec.UNSPECIFIED;

}elseif(childDimension == LayoutParams.WRAP_CONTENT) {

resultSize = View.sUseZeroUnspecifiedMeasureSpec ?0: size;

resultMode = View.MeasureSpec.UNSPECIFIED;

}break;

}returnView.MeasureSpec.makeMeasureSpec(resultSize, resultMode);

}


自定义viewon之Measure_第1张图片

你可能感兴趣的:(自定义viewon之Measure)