view.java

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




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.hjschoolhelper210301201_1, PID: 13135 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference at com.example.hjschoolhelper210301201_1.ClubinfoAdpter.getView(ClubinfoAdpter.java:44) at android.widget.AbsListView.obtainView(AbsListView.java:2458) at android.widget.ListView.makeAndAddView(ListView.java:2067) at android.widget.ListView.fillDown(ListView.java:793) at android.widget.ListView.fillFromTop(ListView.java:855) at android.widget.ListView.layoutChildren(ListView.java:1838) at android.widget.AbsListView.onLayout(AbsListView.java:2255) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1855) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332) at android.widget.FrameLayout.onLayout(FrameLayout.java:270) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:536) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332) at android.widget.FrameLayout.onLayout(FrameLayout.java:270) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1891) at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1729) at android.widget.LinearLayout.onLayout(LinearLayout.java:1638) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332) at android.widget.FrameLayout.onLayout(FrameLayout.java:270) at com.android.internal.policy.DecorView.onLayout(DecorView.java:799) at android.view.View.layout(View.java:23693) at android.view.ViewGroup.layout(ViewGroup.java:6413) at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3999) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3372) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2328) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9087) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1231) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239) at android.view.Choreographer.doCallbacks(Choreographer.java:899) at android.view.Choreographer.doFrame(Choreographer.java:832) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7872) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
05-17

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值