Android应用层View绘制流程之measurelayoutdraw三步曲Word文档下载推荐.docx
- 文档编号:17887804
- 上传时间:2022-12-11
- 格式:DOCX
- 页数:30
- 大小:28.69KB
Android应用层View绘制流程之measurelayoutdraw三步曲Word文档下载推荐.docx
《Android应用层View绘制流程之measurelayoutdraw三步曲Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《Android应用层View绘制流程之measurelayoutdraw三步曲Word文档下载推荐.docx(30页珍藏版)》请在冰豆网上搜索。
*Thelayoutparamsforonedimension(widthorheight)ofthe
*window.
*@returnThemeasurespectousetomeasuretherootview.
*/
privatestaticintgetRootMeasureSpec(intwindowSize,introotDimension){
intmeasureSpec;
switch(rootDimension){
caseViewGroup.LayoutParams.MATCH_PARENT:
//Windowcan'
tresize.ForcerootviewtobewindowSize.
measureSpec=MeasureSpec.makeMeasureSpec(windowSize,MeasureSpec.EXACTLY);
break;
caseViewGroup.LayoutParams.WRAP_CONTENT:
//Windowcanresize.Setmaxsizeforrootview.
measureSpec=MeasureSpec.makeMeasureSpec(windowSize,MeasureSpec.AT_MOST);
default:
//Windowwantstobeanexactsize.Forcerootviewtobethatsize.
measureSpec=MeasureSpec.makeMeasureSpec(rootDimension,MeasureSpec.EXACTLY);
returnmeasureSpec;
从上面的注释可以看出这个getRootMeasureSpec是为了根据根视图的LayoutParams计算根视图的MeasureSpec,这个根视图就是上篇博客讲的DecorView。
关于MeasureSpec
关于MeasureSpec来做一个简单的说明:
通过MeasureSpec.makeMeasureSpec来得到一个32位的整数,高两位代码测量模式mode,低30位代表测量大小size,如下所示:
publicstaticintmakeMeasureSpec(@IntRange(from=0,to=(1<
<
MeasureSpec.MODE_SHIFT)-1)intsize,
@MeasureSpecModeintmode){
if(sUseBrokenMakeMeasureSpec){
returnsize+mode;
}else{
return(size&
~MODE_MASK)|(mode&
MODE_MASK);
然后再通过getMode和getSize这两个方法来得到对应的测试模式mode和测量尺寸size,如下所示:
/**
*Extractsthemodefromthesuppliedmeasurespecification.
*@parammeasureSpecthemeasurespecificationtoextractthemodefrom
*@return{@linkandroid.view.View.MeasureSpec#UNSPECIFIED},
*{@linkandroid.view.View.MeasureSpec#AT_MOST}or
*{@linkandroid.view.View.MeasureSpec#EXACTLY}
@MeasureSpecMode
publicstaticintgetMode(intmeasureSpec){
//noinspectionResourceType
return(measureSpec&
*Extractsthesizefromthesuppliedmeasurespecification.
*@parammeasureSpecthemeasurespecificationtoextractthesizefrom
*@returnthesizeinpixelsdefinedinthesuppliedmeasurespecification
publicstaticintgetSize(intmeasureSpec){
~MODE_MASK);
View的measure和onMeasure方法
通过getRootMeasureSpec来得到DecorView的widthMeasureSpec和heightMeasureSpec之后,就需要来设置DecorView的大小了,也就是调用:
mView.measure(childWidthMeasureSpec,childHeightMeasureSpec);
发现这个measure是View的方法,如下所示:
*<
p>
*Thisiscalledtofindouthowbigaviewshouldbe.Theparent
*suppliesconstraintinformationinthewidthandheightparameters.
/p>
*Theactualmeasurementworkofaviewisperformedin
*{@link#onMeasure(int,int)},calledbythismethod.Therefore,only
*{@link#onMeasure(int,int)}canandmustbeoverriddenbysubclasses.
*@paramwidthMeasureSpecHorizontalspacerequirementsasimposedbythe
*parent
*@paramheightMeasureSpecVerticalspacerequirementsasimposedbythe
*@see#onMeasure(int,int)
publicfinalvoidmeasure(intwidthMeasureSpec,intheightMeasureSpec){
...........
onMeasure(widthMeasureSpec,heightMeasureSpec);
通过注释可以看出,这个方法是用来计算当前View应该为多大,也就是实际的宽高。
widthMeasureSpec和heightMeasureSpec是由父View传入的约束信息,代表了父View给当前View的测量规格,当前View的宽高是由父View和自身一起决定的。
measure方法是final的,不可重载,实际的测量过程是在onMeasure方法里面完成了,因此子类必须且只能重载onMeasure方法来实现自身的测量逻辑。
接下来看onMeasure方法:
*Measuretheviewanditscontenttodeterminethemeasuredwidthandthe
*measuredheight.Thismethodisinvokedby{@link#measure(int,int)}and
*shouldbeoverriddenbysubclassestoprovideaccurateandefficient
*measurementoftheircontents.
strong>
CONTRACT:
/strong>
Whenoverridingthismethod,you
em>
must<
/em>
call{@link#setMeasuredDimension(int,int)}tostorethe
*measuredwidthandheightofthisview.Failuretodosowilltriggeran
code>
IllegalStateException<
/code>
thrownby
*{@link#measure(int,int)}.Callingthesuperclass'
*{@link#onMeasure(int,int)}isavaliduse.
*Thebaseclassimplementationofmeasuredefaultstothebackgroundsize,
*unlessalargersizeisallowedbytheMeasureSpec.Subclassesshould
*override{@link#onMeasure(int,int)}toprovidebettermeasurementsof
*theircontent.
*Ifthismethodisoverridden,itisthesubclass'
sresponsibilitytomake
*surethemeasuredheightandwidthareatleasttheview'
sminimumheight
*andwidth({@link#getSuggestedMinimumHeight()}and
*{@link#getSuggestedMinimumWidth()}).
*@paramwidthMeasureSpechorizontalspacerequirementsasimposedbytheparent.
*Therequirementsareencodedwith
*{@linkandroid.view.View.MeasureSpec}.
*@paramheightMeasureSpecverticalspacerequirementsasimposedbytheparent.
*@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));
注释已经写的非常明白了,子类必须复写onMeasure方法,且最终通过调用setMeasuredDimension方法来存储当前View测量得到的宽和高。
这个宽和高是通过getDefaultSize方法得来的,如下所示:
*Utilitytoreturnadefaultsize.Usesthesuppliedsizeifthe
*MeasureSpecimposednoconstraints.Willgetlargerifallowed
*bytheMeasureSpec.
*@paramsizeDefaultsizeforthisview
*@parammeasureSpecConstraintsimposedbytheparent
*@returnThesizethisviewshouldbe.
publicstaticintgetDefaultSize(intsize,intmeasureSpec){
intresult=size;
intspecMode=MeasureSpec.getMode(measureSpec);
intspecSize=MeasureSpec.getSize(measureSpec);
switch(specMode){
caseMeasureSpec.UNSPECIFIED:
result=size;
caseMeasureSpec.AT_MOST:
caseMeasureSpec.EXACTLY:
result=specSize;
returnresult;
可以看出,如果specMode等于AT_MOST或者EXACTLY就返回specSize,也就是父类指定的specSize,否则返回通过getSuggestedMinimumWidth和getSuggestedMinimumHeight得到的size,从名字可以看出是建议的最小宽度和高度,代码如下所示:
protectedintgetSuggestedMinimumHeight(){
return(mBackground==null)?
mMinHeight:
max(mMinHeight,mBackground.getMinimumHeight());
protectedintgetSuggestedMinimumWidth(){
mMinWidth:
max(mMinWidth,mBackground.getMinimumWidth());
可以看出,建议的最小宽度和高度是由view的background以及其mMinWidth、mMinHeight共同决定的。
setMeasuredDimension方法如下所示:
protectedfinalvoidsetMeasuredDimension(intmeasuredWidth,intmeasuredHeight){
booleanoptical=isLayoutModeOptical(this);
if(optical!
=isLayoutModeOptical(mParent)){
Insetsinsets=getOpticalInsets();
intopticalWidth=insets.left+insets.right;
intopticalHeight=insets.top+insets.bottom;
measuredWidth+=optical?
opticalWidth:
-opticalWidth;
measuredHeight+=optical?
opticalHeight:
-opticalHeight;
setMeasuredDimensionRaw(measuredWidth,measuredHeight);
privatevoidsetMeasuredDimensionRaw(intmeasuredWidth,intmeasuredHeight){
mMeasuredWidth=measuredWidth;
mMeasuredHeight=measuredHeight;
mPrivateFlags|=PFLAG_MEASURED_DIMENSION_SET;
可以看出这个方法就是给mMeasuredHeight和mMeasuredWidth进行赋值。
进行了赋值之后调用View的getMeasuredWidth和getMeasuredHeight方法才能得到其正确的测量宽高!
ViewGroup的measure过程
上面提到View的measure方法传入的widthMeasureSpec和heightMeasureSpec是由父View传入的约束信息,那么这些信息是何时传入的呢?
由于View是嵌套的,因此measure过程也是递归传递的,子View的measure是由父类调用的,然后子View根据传入的父类约束来设置自身的测量规格。
继承自ViewGroup的视图均需要实现onMeasure方法,在这个方法里面对其子View进行测量,同时也对自身进行测量,比如LinearLayout的onMeasure方法如下:
@Override
if(mOrientation==VERTICAL){
measureVertical(widthMeasureSpec,heightMeasureSpec);
measureHorizontal(widthMeasureSpec,heightMeasureSpec);
根据布局的方向分别调用measureHorizontal和measureVertical方法。
在ViewGroup中定义了measureChildren,measureChild,measureChildWithMargins方法来对子视图进行测量。
measureChildren内部循环调用了measureChild。
measureChild和measureChildWithMargins的区别在于measureChildWithMargins把child的margin也考虑在内。
下面来对measureChildWithMargins方法来分析:
*Askoneofthechildrenofthisviewtomeasureitself,takinginto
*accountboththeMeasureSpecrequirementsforthisviewanditspadding
*andmargins.ThechildmusthaveMarginLayoutParamsTheheavyliftingis
*doneingetChildMeasureSpec.
*@paramchildThechildtomeasure
*@paramparentWidthMeasureSpecThewidthrequirementsforthisview
*@paramwidthUsedExtraspacethathasbeenusedupbytheparent
*horizontally(possiblybyotherchildrenoftheparent)
*@paramparentHeightMeasureSpecTheheightrequirementsforthisview
*@paramheightUsedExtraspacethathasbeenusedupbytheparent
*vertically(possiblybyotherchildrenoftheparent)
protectedvoidmeasureChildWithMargins(Viewchild,
intparentWidthMeasureSpec,intwidthUsed,
intparentHei
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 应用 View 绘制 流程 measurelayoutdraw 三步曲
链接地址:https://www.bdocx.com/doc/17887804.html