View.java

/**

*<p>

*This is called to find out how big a view should be. The parent

*supplies constraint information in the width and height parameters.

*</p>

*

*<p>

*The actual mesurement work of a view is performed in

*{@link #onMeasure(int, int)},called by this method. Therefore, only

*{@link #onMeasure(int, int)}can and must be overriden by subclasses.

*</p>

*

*

*@paramwidthMeasureSpec Horizontal space requirements as imposed by the

* parent

*@paramheightMeasureSpec Vertical space requirements as imposed by the

* parent

*

*@see#onMeasure(int, int)

*/

publicfinalvoidmeasure(intwidthMeasureSpec, intheightMeasureSpec) {

if((mPrivateFlags& FORCE_LAYOUT)== FORCE_LAYOUT||

widthMeasureSpec !=mOldWidthMeasureSpec||

heightMeasureSpec !=mOldHeightMeasureSpec){


//first clears the measured dimension flag

mPrivateFlags&= ~MEASURED_DIMENSION_SET;


if(ViewDebug.TRACE_HIERARCHY){

ViewDebug.trace(this,ViewDebug.HierarchyTraceType.ON_MEASURE);

}


//measure ourselves, this should set the measured dimension flag back

onMeasure(widthMeasureSpec,heightMeasureSpec); //重点是它


//flag not set, setMeasuredDimension() was not invoked, we raise

//an exception to warn the developer

if((mPrivateFlags& MEASURED_DIMENSION_SET)!= MEASURED_DIMENSION_SET){

thrownewIllegalStateException("onMeasure()did not set the"

+ "measured dimension by calling"

+ "setMeasuredDimension()");

}


mPrivateFlags|= LAYOUT_REQUIRED;

}


mOldWidthMeasureSpec= widthMeasureSpec;

mOldHeightMeasureSpec= heightMeasureSpec;

}




/**

*<p>

*Measure the view and its content to determine the measured width andthe

*measured height. This method is invoked by {@link#measure(int, int)} and

*should be overriden by subclasses to provide accurate and efficient

*measurement of their contents.

*</p>

*

*<p>

*<strong>CONTRACT:</strong>When overriding this method, you

*<em>must</em>call {@link #setMeasuredDimension(int,int)} to store the

*measured width and height of this view. Failure to do so will triggeran

*<code>IllegalStateException</code>,thrown by

*{@link #measure(int, int)}.Calling the superclass'

*{@link #onMeasure(int, int)}is a valid use.

*</p>

*

*<p>

*The base class implementation of measure defaults to the backgroundsize,

*unless a larger size is allowed by the MeasureSpec. Subclasses should

*override {@link #onMeasure(int, int)}to provide better measurements of

*their content.

*</p>

*

*<p>

*If this method is overridden, it is the subclass's responsibility tomake

*sure the measured height and width are at least the view's minimumheight

*and width ({@link#getSuggestedMinimumHeight()} and

*{@link #getSuggestedMinimumWidth()}).

*</p>

*

*@paramwidthMeasureSpec horizontal space requirements as imposed by theparent.

* The requirements are encoded with

* {@linkandroid.view.View.MeasureSpec}.

*@paramheightMeasureSpec vertical space requirements as imposed by theparent.

* The requirements are encoded with

* {@linkandroid.view.View.MeasureSpec}.

*

*@see#getMeasuredWidth()

*@see#getMeasuredHeight()

*@see#setMeasuredDimension(int, int)

*@see#getSuggestedMinimumHeight()

*@see#getSuggestedMinimumWidth()

*@seeandroid.view.View.MeasureSpec#getMode(int)

*@seeandroid.view.View.MeasureSpec#getSize(int)

*/

protectedvoidonMeasure(intwidthMeasureSpec, intheightMeasureSpec) {

setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec),

getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec));

}




每个view中一定存在一个必调的方法,measure(int, int) ,它调用onMeasure(int,int)

onMeasure(widthMeasureSpec,heightMeasureSpec)的作用是什么?

测量view和它的content得出widthMeasureSpec heightMeasureSpec 并保存下来

measure(widthMeasureSpec,heightMeasureSpec)的作用是什么?

通过父布局提供的 widthMeasureSpecwidthMeasureSpec来确定这个View的 大小,有多高,有多宽,




特别对于一些实现ViewGroup 的控件 在某些情况下,当 android:layout_heightandroid:layout_width 不能达到目的时,可以通过重写 onMeasure(int,int) 来达到调整view高宽的目的。



/**

*<p>Thismehod must be called by {@link#onMeasure(int, int)} to store the

*measured width and measured height. Failing to do so will trigger an

*exception at measurement time.</p>

*

*@parammeasuredWidth The measured width of this view. May be a complex

*bit mask as defined by {@link#MEASURED_SIZE_MASK} and

*{@link #MEASURED_STATE_TOO_SMALL}.

*@parammeasuredHeight The measured height of this view. May be a complex

*bit mask as defined by {@link#MEASURED_SIZE_MASK} and

*{@link #MEASURED_STATE_TOO_SMALL}.

*/

protectedfinalvoidsetMeasuredDimension(intmeasuredWidth, intmeasuredHeight) {

mMeasuredWidth= measuredWidth;

mMeasuredHeight= measuredHeight;


mPrivateFlags|= MEASURED_DIMENSION_SET;

}


setMeasuredDimensiononMeasure(int,int) 中调用,用来存储跟新测量的宽和高,若不调,可能产生异常



转载:

MeasureSpec介绍及使用详解

MeasureSpecview中的内部类

一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求。一个MeasureSpec由大小和模式组成。它有三种模式:UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;AT_MOST(至多),子元素至多达到指定大小的值。

1父布局传下来的

2子元素布局文件或代码中设置的


  它常用的三个函数:

  1.staticintgetMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)

  2.staticintgetSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)

  3.staticintmakeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式)


  这个类的使用呢,通常view组件的onMeasure方法里面调用但也有少数例外,看看几个例子:

  a.首先一个我们常用到的一个有用的函数,View.resolveSize(intsize,intmeasureSpec)



publicstatic intresolveSize(intsize, int measureSpec) {

returnresolveSizeAndState(size,measureSpec, 0) & MEASURED_SIZE_MASK;

}


publicstatic intresolveSizeAndState(intsize, int measureSpec, intchildMe asuredState) {

intresult = size;

intspecMode = MeasureSpec.getMode(measureSpec);

intspecSize = MeasureSpec.getSize(measureSpec);

switch(specMode) {

caseMeasureSpec.UNSPECIFIED:

result = size;

break;

caseMeasureSpec.AT_MOST:

if(specSize < size) {

result = specSize |MEASURED_STATE_TOO_SMALL;

} else{

result = size;

}

break;

caseMeasureSpec.EXACTLY:

result = specSize;

break;

}

returnresult | (childMeasuredState&MEASURED_STATE_MASK);

}


简单说一下,这个方法的主要作用就是根据你提供的大小和MeasureSpec,返回你想要的大小值,这个里面根据传入模式的不同来做相应的处理。

  再看看MeasureSpec.makeMeasureSpec方法,实际上这个方法很简单:

publicstatic intmakeMeasureSpec(int size, intmode) {

returnsize + mode;

}

这样大家不难理解sizemeasureSpec区别了。







******************************************


布局步骤

1measure onMeasure(measureWidth, measureHight) 计算大小

2layout onLayout(chang, l, t, r, b) 给自己及 子view分配size,position

3draw ondraw(canvas) 画图




dispatchDraw 空方法体






getWidth()getMeasureWidth() 区别

getWidth()view的布局完成后,view的宽度

getMeasureWidth():这是一个过程量,得到的是在最近一次調用measure()方法測量後得到的view的寬度,它僅僅用在測量和layout的計算中

举例:有时会通过 child.getMeasureWidth()的值根据 Gravity重心得出 view4lt r b layout

Gridview 中存在一个方法:

privatevoidsetupChild(View child, intposition, inty, booleanflow, intchildrenLeft,

booleanselected, booleanrecycled, intwhere) {

booleanisSelected = selected && shouldShowSelector();

finalbooleanupdateChildSelected = isSelected != child.isSelected();

finalintmode = mTouchMode;

finalbooleanisPressed = mode > TOUCH_MODE_DOWN && mode <TOUCH_MODE_SCROLL &&

mMotionPosition ==position;

finalbooleanupdateChildPressed = isPressed != child.isPressed();

booleanneedToMeasure = !recycled || updateChildSelected ||child.isLayoutRequested();


//Respect layout params that are already in the view. Otherwise make

//some up...

AbsListView.LayoutParams p =(AbsListView.LayoutParams)child.getLayoutParams();

if(p == null){

p = newAbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,

ViewGroup.LayoutParams.WRAP_CONTENT,0);

}

p.viewType =mAdapter.getItemViewType(position);


if(recycled && !p.forceAdd) {

attachViewToParent(child,where, p);

} else{

p.forceAdd = false;

addViewInLayout(child,where, p, true);

}


if(updateChildSelected) {

child.setSelected(isSelected);

if(isSelected) {

requestFocus();

}

}


if(updateChildPressed) {

child.setPressed(isPressed);

}


if(mChoiceMode != CHOICE_MODE_NONE&& mCheckStates != null){

if(child instanceofCheckable) {

((Checkable)child).setChecked(mCheckStates.get(position));

} elseif(getContext().getApplicationInfo().targetSdkVersion

>=android.os.Build.VERSION_CODES.HONEYCOMB){

child.setActivated(mCheckStates.get(position));

}

}


if(needToMeasure) {

intchildHeightSpec = ViewGroup.getChildMeasureSpec(

MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED),0, p.height);


intchildWidthSpec = ViewGroup.getChildMeasureSpec(

MeasureSpec.makeMeasureSpec(mColumnWidth,MeasureSpec.EXACTLY),0, p.width);

child.measure(childWidthSpec,childHeightSpec);

} else{

cleanupLayoutState(child);

}


finalintw = child.getMeasuredWidth();

final int h =child.getMeasuredHeight();


intchildLeft;

finalintchildTop = flow ? y : y - h;


finalintlayoutDirection = getResolvedLayoutDirection();

finalintabsoluteGravity = Gravity.getAbsoluteGravity(mGravity,layoutDirection);

switch(absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK){

caseGravity.LEFT:

childLeft =childrenLeft;

break;

caseGravity.CENTER_HORIZONTAL:

childLeft = childrenLeft+ ((mColumnWidth - w) / 2);

break;

case Gravity.RIGHT:

childLeft = childrenLeft+ mColumnWidth - w;

break;

default:

childLeft =childrenLeft;

break;

}


if(needToMeasure) {

finalintchildRight = childLeft + w;

finalintchildBottom = childTop + h;

child.layout(childLeft,childTop, childRight, childBottom);

} else{

child.offsetLeftAndRight(childLeft- child.getLeft());

child.offsetTopAndBottom(childTop- child.getTop());

}


if(mCachingStarted) {

child.setDrawingCacheEnabled(true);

}


if(recycled &&(((AbsListView.LayoutParams)child.getLayoutParams()).scrappedFromPosition)

!= position) {

child.jumpDrawablesToCurrentState();

}

}











ViewGroup.java


1 measureChildren(measureWidth,measureHight) measureChild(child, widthMeasureSpec, heightMeasureSpec)


2继承layout(l,t, r, b) onLayout(chang,l, t, r, b)


3继承 dispatchDraw drawChild




更多相关文章

  1. Android:系统demo布局汇总
  2. ToolBar基本使用及自定义ToolBar
  3. 仿ios滚动 有弹性的ScrollView
  4. android layout动态布局
  5. android中Button显示两行字体(spannable)
  6. android练习一之保存用户名
  7. Android(安卓)MotionLayout As a Dancer
  8. Android(安卓)CV系列 > 可拖拽布局 拉长 CoordinatorLayout +Bot
  9. file system

随机推荐

  1. Android(安卓)入门第四讲04-小结-Recycle
  2. Android小项目之十二 设置中心的界面
  3. Android(安卓)Activity(活动)
  4. Google:所有含 Android Market 的 Android
  5. Android SDK 2.3与Eclipse最新版开发环境
  6. android 使用handler更新ui,使用与原理分
  7. 看网易和腾讯如何用一套 H5 通杀Android
  8. Android拦截并获取WebView内部POST请求参
  9. Android内存管理机制和内存泄漏分析及优
  10. Android(安卓)6.0 权限请求问题