View绘制作业流程专业资料

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

//final办法,子类不可重写publicfinalvoidmeasure(intwidthMeasureSpec,intheightMeasureSpec){......//回调onMeasure()办法onMeasure(widthMeasureSpec,heightMeasureSpec);}这个办法两个参数都是父View传递过来,代表了父view规格。她由两某些构成,高2位表达MODE,低30位表达size。//ViewonMeasure默认实现办法protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){View绘制流程第一步:递归measure源码分析setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec),getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec));}对于非ViewGroupView而言,通过调用上面默认onMeasure即可完毕View测量。setMeasuredDimension函数是一种很核心函数,它完毕了对View成员变量mMeasuredWidth和mMeasuredHeight变量赋值。publicstaticintgetDefaultSize(intsize,intmeasureSpec){intresult=size;//通过MeasureSpec解析获取mode与sizeintspecMode=MeasureSpec.getMode(measureSpec);intspecSize=MeasureSpec.getSize(measureSpec);switch(specMode){caseMeasureSpec.UNSPECIFIED:result=size;break;caseMeasureSpec.AT_MOST:caseMeasureSpec.EXACTLY:result=specSize;break;}returnresult;}protectedintgetSuggestedMinimumWidth(){return(mBackground==null)?mMinWidth:max(mMinWidth,mBackground.getMinimumWidth());}protectedintgetSuggestedMinimumHeight(){return(mBackground==null)?mMinHeight:max(mMinHeight,mBackground.getMinimumHeight());}在ViewGroup中定义了measureChildren,measureChild,measureChildWith-Margins办法来对子视图进行测量,measureChildren内部实质只是循环调用measureChild。protectedvoidmeasureChildWithMargins(Viewchild,intparentWidthMeasureSpe,cintwidthUsed,intparentHeightMeasureSpe,cintheightUsed){//获取子视图LayoutParamsfinalMarginLayoutParamslp=(MarginLayoutParams)child.getLayoutParams();//调节MeasureSpec//通过这两个参数以及子视图自身LayoutParams来共同决定子视图测量规格finalintchildWidthMeasureSpec=getChildMeasureSpec(parentWidthMeasureSpec,mPaddingLeft+mPaddingRight+lp.leftMargin+lp.rightMargin+widthUsed,lp.width);finalintchildHeightMeasureSpec=getChildMeasureSpec(parentHeightMeasureSpec,mPaddingTop+mPaddingBottom+lp.topMargin+lp.bottomMargin+heightUsed,lp.height);//调运子Viewmeasure办法,子Viewmeasure中会回调子View//onMeasure办法child.measure(childWidthMeasureSpec,childHeightMeasureSpec);}该办法就是对父视图提供measureSpec参数结合自身LayoutParams参数进行了调节,然后再来调用child.measure()办法,详细通过办法getChildMeasureSpec来进行参数调节。publicstaticintgetChildMeasureSpec(intspec,intpadding,intchildDimension){//获取当前ParentViewMode和SizeintspecMode=MeasureSpec.getMode(spec);intspecSize=MeasureSpec.getSize(spec);//获取Parentsize与padding差值(也就是Parent剩余大小),若差值不大于0直接返回0intsize=Math.max(0,specSize-padding);//定义返回值存储变量intresultSize=0;intresultMode=0;//根据当前ParentMode进行switch分支逻辑switch(specMode){//Parenthasimposedanexactsizeonus//默认RootViewMode就是EXACTLYcaseMeasureSpec.EXACTLY:if(childDimension=0){/如/果childlayout_wOrh属性在xml或者java中予以详细大//于等于0数值/设/立childsize为真实layout_wOrh属性值,mode为EXACTLYresultSize=childDimension;resultMode=MeasureSpec.EXACTLY;}elseif(childDimension==LayoutParams.MATCH_PARENT){/如/果childlayout_wOrh属性在xml或者java中予以//MATCH_PARENT//Childwantstobeoursize.Sobeit./设/立childsize为size,mode为EXACTLYresultSize=size;resultMode=MeasureSpec.EXACTLY;}elseif(childDimension==LayoutParams.WRAP_CONTENT){/如/果childlayout_wOrh属性在xml或者java中予以//WRAP_CONTENT/设/立childsize为size,mode为AT_MOST//Childwantstodetermineitsownsize.Itcan'tbe//biggerthanus.resultSize=size;resultMode=MeasureSpec.AT_MOST;}break;......View绘制流程第二步:递归layout源码分析//其她Mode分支类似}//将mode与size通过MeasureSpec办法整合为32位整数返回returnMeasureSpec.makeMeasureSpec(resultSize,resultMode);}用ViewgetMeasuredWidth()和getMeasuredHeight()办法来获取View测量宽高,必要保证这两个办法在onMeasure流程之后被调用才干返回有效值。MeasureSpec(View内部类)测量规格为int型,值由高2位规格模式specMode和低30位详细尺寸specSize构成。其中specMode只有三种值:MeasureSpec.EXACTLY//拟定模式,父View但愿子View大小是拟定,由specSize决定;MeasureSpec.AT_MOST//最多模式,父View但愿子View大小最多是specSize指定值;MeasureSpec.UNSPECIFIED//未指定模式,父View完全根据子View设计值来决定;ViewGrouplayout办法,如下:@Overridepublicfinalvoidlayout(intl,intt,intr,intb){......super.layout(l,t,r,b);.....}调运了View父类layout办法,因此咱们看下Viewlayout源码,如下:publicvoidlayout(intl,intt,intr,intb){//实质都是调用setFrame办法把参数分别赋值给mLeft、mTop、mRight和//mBottom这几种变量//判断View位置与否发生过变化,以拟定有无必要对当前View进行重新//layoutbooleanchanged=isLayoutModeOptical(mParent)?setOpticalFrame(,lt,r,b):setFrame(l,t,r,b);if(changed||(mPrivateFlags&PFLAG_LAYOUT_REQUIRED)==PFLAG_LAYOUT_REQUIRED){onLayout(changed,l,t,r,b);}}//ViewGrouponLayout办法,如下:@OverrideprotectedabstractvoidonLayout(booleanchanged,intl,intt,intr,intb);关于getWidth()、getHeight()和getMeasuredWidth()、getMeasuredHeight()这两对办法之间区别publicfinalintgetMeasuredWidth(){returnmMeasuredWidth&MEASURED_SIZE_MASK;}publicfinalintgetMeasuredHeight(){returnmMeasuredHeight&MEASURED_SIZE_MASK;}publicfinalintgetWidth(){returnmRight-mLeft;View绘制流程第三步:递归draw源码分析}publicfinalintgetHeight(){returnmBottom-mTop;}View.layout办法可被重载,ViewGroup.layout为final不可重载,ViewGroup.onLayout为abstract,子类必要重载实现自己位置逻辑。凡是layout_XXX布局属性基本都针对是包括子ViewViewGroup,当对一种没有父容器View设立有关layout_XXX属性是没有任何意义使用ViewgetWidth()和getHeight()办法来获取View测量宽高,必要保证这两个办法在onLayout流程之后被调用才干返回有效值ViewGroup没有重写Viewdraw办法,因此如下直接从Viewdraw办法开始publicvoiddraw(Canvascanvas){//Step1,drawthebackground,ifneededif(!dirtyOpaque){drawBackground(canvas);}//skipstep2&5ifpossible(commoncase)//Step2,savethecanvas'layersif(drawTop){canvas.saveLayer(l

1 / 20
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功