当前位置: 首页 > news >正文

漳州招商局规划建设局网站专业微信网站开发公司

漳州招商局规划建设局网站,专业微信网站开发公司,深圳找工作哪个网站好,凡科网站建设好对于一个View(ViewGroup)来说实现无非于三个流程#xff0c;onMeasure(测量)#xff0c;onLayout(定位)#xff0c;onDraw(绘制)#xff0c;接下来就对这三个部分一一分析但是首先还是对LinearLayout变量进行介绍1.LinearLayout变量其实LinearLayout变量与上篇属性篇中关联…对于一个View(ViewGroup)来说实现无非于三个流程onMeasure(测量)onLayout(定位)onDraw(绘制)接下来就对这三个部分一一分析但是首先还是对LinearLayout变量进行介绍1.LinearLayout变量其实LinearLayout变量与上篇属性篇中关联比较大,这里就直接上代码和注释了//基准线对齐变量默认为trueprivate boolean mBaselineAligned true;//基准线对齐的对象indexprivate int mBaselineAlignedChildIndex -1;//baseline额外的偏移量private int mBaselineChildTop 0;//linearlayout的排列方式private int mOrientation;//linearlayout的对齐方式private int mGravity Gravity.START | Gravity.TOP;//测量的时候通过累加得到所有子控件的高度和(Vertical)或者宽度和(Horizontal) ;private int mTotalLength;//权重总和变量private float mWeightSum;//权重最小尺寸的对象private boolean mUseLargestChild;//基准线对其相关private int[] mMaxAscent;private int[] mMaxDescent;//分隔条相关private Drawable mDivider;private int mDividerWidth;private int mDividerHeight;private int mShowDividers;private int mDividerPadding;2.measure流程Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {if (mOrientation VERTICAL) {measureVertical(widthMeasureSpec, heightMeasureSpec);} else {measureHorizontal(widthMeasureSpec, heightMeasureSpec);}}当我们设置不同的orientation就会进入不同的测量流程我们以其中的一个测量流程为例子进行说明那么另外的测量流程也就不难理解了我们以measureVertical为例来分析由于代码相对比较长所以根据不同的功能分段分析(1).变量void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {//mTotalLength为 LinearLayout的成员变量在这里指的是所有子控件的高度和mTotalLength 0;//所有子控件中宽度最大的值int maxWidth 0;//子控件的测量状态int childState 0;//子控件中layout_weight0的View最大高度int alternativeMaxWidth 0;//子控件中layout_weight0的View最大高度int weightedMaxWidth 0;//子控件是否全是match_parentboolean allFillParent true;//子控件所有layout_weight的和float totalWeight 0;//获取子控件数量final int count getVirtualChildCount();//获取测量模式final int widthMode MeasureSpec.getMode(widthMeasureSpec);final int heightMode MeasureSpec.getMode(heightMeasureSpec);//当子控件为match_parent的时候该值为tureboolean matchWidth false;boolean skippedMeasure false;//基准线对齐的对象indexfinal int baselineChildIndex mBaselineAlignedChildIndex;//权重最小尺寸的对象final boolean useLargestChild mUseLargestChild;//子View中最高高度int largestChildHeight Integer.MIN_VALUE;}(2).测量Part1其实这段代码前面自带的注释就很好说明接下来这一段代码做的事情了See how tall everyone is. Also remember max width.就不对这句话进行翻译了接下来看这一段代码做了什么事情void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {//...接上面的变量for (int i 0; i count; i) {final View child getVirtualChildAt(i);//这个不解释了measureNullChild获得的结果是0if (child null) {mTotalLength measureNullChild(i);continue;}//这个也不解释了if (child.getVisibility() View.GONE) {i getChildrenSkipCount(child, i);continue;}// 根据showDivider的值(before/middle/end)来决定遍历到当前子控件时高度是否需要加上divider的高度// 比如showDivider为before那么只会在第0个子控件测量时加上divider高度其余情况下都不加//这里测量不包括end的情况if (hasDividerBeforeChildAt(i)) {mTotalLength mDividerHeight;}LinearLayout.LayoutParams lp (LinearLayout.LayoutParams) child.getLayoutParams();//根据子控件的权重得到总权重totalWeight lp.weight;// 测量模式有三种// * UNSPECIFIED父控件对子控件无约束// * Exactly父控件对子控件强约束子控件永远在父控件边界内越界则裁剪。如果要记忆的话可以记忆为有对应的具体数值或者是Match_parent// * AT_Most子控件为wrap_content的时候测量值为AT_MOST。if (heightMode MeasureSpec.EXACTLY lp.height 0 lp.weight 0) {//父控件高度为match_parent且子控件高度为0weight0情况下// 测量到这里的时候会给个标志位稍后再处理。此时会计算总高度final int totalLength mTotalLength;mTotalLength Math.max(totalLength, totalLength lp.topMargin lp.bottomMargin);skippedMeasure true;} else {int oldHeight Integer.MIN_VALUE;if (lp.height 0 lp.weight 0) {//子控件高度为0并且weight0,并且父控件是wrap_content或者mode为UNSPECIFIED//这时候父控件的高度是wrap_content所以随着子控件的高度进行变化的//顾强制将子控件高度设置为wrap_content防止子控件高度为0oldHeight 0;lp.height LayoutParams.WRAP_CONTENT;}//方法名可知是对子控件进行测量measureChildBeforeLayout(child, i, widthMeasureSpec, 0, heightMeasureSpec,totalWeight 0 ? mTotalLength : 0);if (oldHeight ! Integer.MIN_VALUE) {lp.height oldHeight;}final int childHeight child.getMeasuredHeight();final int totalLength mTotalLength;//比较child测量前后的总高度取大值mTotalLength Math.max(totalLength, totalLength childHeight lp.topMargin lp.bottomMargin getNextLocationOffset(child));//当设置权重最小尺寸的对象为true获取子View中最高高度if (useLargestChild) {largestChildHeight Math.max(childHeight, largestChildHeight);}}//计算baseline额外的偏移量后面会用到if ((baselineChildIndex 0) (baselineChildIndex i 1)) {mBaselineChildTop mTotalLength;}//当设置的基准线对齐的对象index 大于 子对象的Index 并且 weight 0 会报异常if (i baselineChildIndex lp.weight 0) {throw new RuntimeException(A child of LinearLayout with index less than mBaselineAlignedChildIndex has weight 0, which wont work. Either remove the weight, or dont set mBaselineAlignedChildIndex.);}// 当父类(LinearLayout)不是match_parent或者精确值的时候但子控件却是一个match_parent// 那么matchWidthLocally和matchWidth置为true// 意味着这个控件将会占据父类(水平方向)的所有空间boolean matchWidthLocally false;if (widthMode ! MeasureSpec.EXACTLY lp.width LayoutParams.MATCH_PARENT) {matchWidth true;matchWidthLocally true;}final int margin lp.leftMargin lp.rightMargin;final int measuredWidth child.getMeasuredWidth() margin;//后面几个就是给变量赋值maxWidth Math.max(maxWidth, measuredWidth);childState combineMeasuredStates(childState, child.getMeasuredState());allFillParent allFillParent lp.width LayoutParams.MATCH_PARENT;if (lp.weight 0) {weightedMaxWidth Math.max(weightedMaxWidth,matchWidthLocally ? margin : measuredWidth);} else {alternativeMaxWidth Math.max(alternativeMaxWidth,matchWidthLocally ? margin : measuredWidth);}i getChildrenSkipCount(child, i);}}(3).测量Part2void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {//...接上面的方法//判断showDivider值是否为end是的情况下加上divider的高度if (mTotalLength 0 hasDividerBeforeChildAt(count)) {mTotalLength mDividerHeight;}if (useLargestChild (heightMode MeasureSpec.AT_MOST || heightMode MeasureSpec.UNSPECIFIED)) {//当设置权重最小尺寸的对象为true//并且LinearLayout是wrap_content或者mode为UNSPECIFIED//计算新的mTotalLength因为这时候所有子控件都是用最大控件的最小值mTotalLength 0;for (int i 0; i count; i) {final View child getVirtualChildAt(i);if (child null) {mTotalLength measureNullChild(i);continue;}if (child.getVisibility() GONE) {i getChildrenSkipCount(child, i);continue;}final LinearLayout.LayoutParams lp (LinearLayout.LayoutParams)child.getLayoutParams();final int totalLength mTotalLength;mTotalLength Math.max(totalLength, totalLength largestChildHeight lp.topMargin lp.bottomMargin getNextLocationOffset(child));}}//下面是计算屏幕除去所有子控件所占高度剩余的高度//为了定义权重的子控件计算高度mTotalLength mPaddingTop mPaddingBottom;int heightSize mTotalLength;heightSize Math.max(heightSize, getSuggestedMinimumHeight());int heightSizeAndState resolveSizeAndState(heightSize, heightMeasureSpec, 0);heightSize heightSizeAndState MEASURED_SIZE_MASK;int delta heightSize - mTotalLength;}(3).测量Part3void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {//...接上面的方法if (skippedMeasure || delta ! 0 totalWeight 0.0f) {//这里skippedMeasure是接的上面测量Part1当父控件为match_parent,子控件height 0 ,weight0的情况下skippedMeasure为true//这里获取总权重当我们设置了总权重则用我们设置的权重值如果没有设置则用子控件权重相加的和float weightSum mWeightSum 0.0f ? mWeightSum : totalWeight;mTotalLength 0;for (int i 0; i count; i) {//遍历子View根据权重对子View进行测量final View child getVirtualChildAt(i);if (child.getVisibility() View.GONE) {continue;}LinearLayout.LayoutParams lp (LinearLayout.LayoutParams) child.getLayoutParams();float childExtra lp.weight;if (childExtra 0) {//当子控件的weight大于0时int share (int) (childExtra * delta / weightSum);weightSum - childExtra;delta - share;final int childWidthMeasureSpec getChildMeasureSpec(widthMeasureSpec,mPaddingLeft mPaddingRight lp.leftMargin lp.rightMargin, lp.width);if ((lp.height ! 0) || (heightMode ! MeasureSpec.EXACTLY)) {int childHeight child.getMeasuredHeight() share;if (childHeight 0) {childHeight 0;}//定义权重子控件重新测量这时候childWidth是子控件本身的高度加上通过权重计算的额外高度child.measure(childWidthMeasureSpec,MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));} else {//没有定义权重子控件重新测量当额外高度大于0则以这个额外高度为子控件的高度child.measure(childWidthMeasureSpec,MeasureSpec.makeMeasureSpec(share 0 ? share : 0,MeasureSpec.EXACTLY));}childState combineMeasuredStates(childState, child.getMeasuredState() (MEASURED_STATE_MASKMEASURED_HEIGHT_STATE_SHIFT));}final int margin lp.leftMargin lp.rightMargin;final int measuredWidth child.getMeasuredWidth() margin;maxWidth Math.max(maxWidth, measuredWidth);boolean matchWidthLocally widthMode ! MeasureSpec.EXACTLY lp.width LayoutParams.MATCH_PARENT;alternativeMaxWidth Math.max(alternativeMaxWidth,matchWidthLocally ? margin : measuredWidth);allFillParent allFillParent lp.width LayoutParams.MATCH_PARENT;final int totalLength mTotalLength;mTotalLength Math.max(totalLength, totalLength child.getMeasuredHeight() lp.topMargin lp.bottomMargin getNextLocationOffset(child));}mTotalLength mPaddingTop mPaddingBottom;} else {alternativeMaxWidth Math.max(alternativeMaxWidth,weightedMaxWidth);//当设置了权重最小尺寸if (useLargestChild heightMode ! MeasureSpec.EXACTLY) {for (int i 0; i count; i) {final View child getVirtualChildAt(i);if (child null || child.getVisibility() View.GONE) {continue;}final LinearLayout.LayoutParams lp (LinearLayout.LayoutParams) child.getLayoutParams();float childExtra lp.weight;//子控件设置权重后就会以最大子元素的最小尺寸作为高度if (childExtra 0) {child.measure(MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(),MeasureSpec.EXACTLY),MeasureSpec.makeMeasureSpec(largestChildHeight,MeasureSpec.EXACTLY));}}}}if (!allFillParent widthMode ! MeasureSpec.EXACTLY) {maxWidth alternativeMaxWidth;}maxWidth mPaddingLeft mPaddingRight;maxWidth Math.max(maxWidth, getSuggestedMinimumWidth());setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),heightSizeAndState);if (matchWidth) {forceUniformWidth(count, heightMeasureSpec);}}到这里测量Vertical就结束了接下来介绍下Layout的过程2.layout流程与measure一样layout同样是分两个流程protected void onLayout(boolean changed, int l, int t, int r, int b) {if (mOrientation VERTICAL) {layoutVertical(l, t, r, b);} else {layoutHorizontal(l, t, r, b);}}同样我们取layoutVertical来进行分析layoutVertical相对代码不是很多就不拆分分析了void layoutVertical(int left, int top, int right, int bottom) {final int paddingLeft mPaddingLeft;int childTop;int childLeft;final int width right - left;int childRight width - mPaddingRight;//子控件可用的空间int childSpace width - paddingLeft - mPaddingRight;final int count getVirtualChildCount();final int majorGravity mGravity Gravity.VERTICAL_GRAVITY_MASK;final int minorGravity mGravity Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;//根据LinearLayout的对其方式设置第一个子控件的Top值switch (majorGravity) {case Gravity.BOTTOM:childTop mPaddingTop bottom - top - mTotalLength;break;case Gravity.CENTER_VERTICAL:childTop mPaddingTop (bottom - top - mTotalLength) / 2;break;case Gravity.TOP:default:childTop mPaddingTop;break;}for (int i 0; i count; i) {final View child getVirtualChildAt(i);if (child null) {childTop measureNullChild(i);} else if (child.getVisibility() ! GONE) {final int childWidth child.getMeasuredWidth();final int childHeight child.getMeasuredHeight();final LinearLayout.LayoutParams lp (LinearLayout.LayoutParams) child.getLayoutParams();int gravity lp.gravity;if (gravity 0) {gravity minorGravity;}final int layoutDirection getLayoutDirection();final int absoluteGravity Gravity.getAbsoluteGravity(gravity, layoutDirection);//根据子控件的对其方式设置left值switch (absoluteGravity Gravity.HORIZONTAL_GRAVITY_MASK) {case Gravity.CENTER_HORIZONTAL:childLeft paddingLeft ((childSpace - childWidth) / 2) lp.leftMargin - lp.rightMargin;break;case Gravity.RIGHT:childLeft childRight - childWidth - lp.rightMargin;break;case Gravity.LEFT:default:childLeft paddingLeft lp.leftMargin;break;}//当有设置分隔条需要加上分隔条的高度if (hasDividerBeforeChildAt(i)) {childTop mDividerHeight;}//子控件top递增childTop lp.topMargin;//用setChildFrame()方法设置子控件控件的在父控件上的坐标轴setChildFrame(child, childLeft, childTop getLocationOffset(child),childWidth, childHeight);childTop childHeight lp.bottomMargin getNextLocationOffset(child);i getChildrenSkipCount(child, i);}}}3.draw流程最后说下draw流程draw流程相对来说没有什么内容protected void onDraw(Canvas canvas) {if (mDivider null) {return;}if (mOrientation VERTICAL) {drawDividersVertical(canvas);} else {drawDividersHorizontal(canvas);}}measure和layout将子控件的位置和大小确定后当有设置分隔条则分为两种流程绘制分隔条void drawDividersVertical(Canvas canvas) {final int count getVirtualChildCount();//当分割线位置设置begin与middle走下面流程for (int i 0; i count; i) {final View child getVirtualChildAt(i);if (child ! null child.getVisibility() ! GONE) {if (hasDividerBeforeChildAt(i)) {final LayoutParams lp (LayoutParams) child.getLayoutParams();final int top child.getTop() - lp.topMargin - mDividerHeight;drawHorizontalDivider(canvas, top);}}}//当分割线位置设置end走下面流程if (hasDividerBeforeChildAt(count)) {final View child getLastNonGoneChild();int bottom 0;if (child null) {bottom getHeight() - getPaddingBottom() - mDividerHeight;} else {final LayoutParams lp (LayoutParams) child.getLayoutParams();bottom child.getBottom() lp.bottomMargin;}drawHorizontalDivider(canvas, bottom);}}至此LinearLayout的核心代码就分析完成了
http://www.huolong8.cn/news/118432/

相关文章:

  • 中山有网站建设公司吗社区教育网站建设方案
  • 风景网站模板网站开发怎么使用维语
  • 怎样在网站做推广临沂营销型网站建设
  • 北京泵网站建设新闻软文自助发布平台
  • 广州商城网站建设地址西安市免费做网站
  • 网站网页宽度多少合适湖州做网站公司
  • 一家专门做衣服的网站一级域名生成二级域名
  • 新闻wordpress主题优化网站排名软件
  • 怎么做网站扩展动易论坛官方网站
  • 优秀的集团网站广州专业做网站
  • 中国建设购物网站韶关企业网站建设公司
  • l5手机网站模板wordpress禁用woff
  • 企业网站下载梅州市建设培训中心网站
  • 如何在asp网站的后台做金融看哪些网站有哪些
  • 怎样做网站背景少儿编程加盟店
  • 黄冈网站建设效果房地产网站建设平台
  • 网站模板 百科辽宁工程造价信息网官网
  • 周口市网站建设wordpress在预览图上加符号
  • 学校建设网站wordpress 内容发布
  • 长沙哪个公司做网站好住建厅电子证书的查询方式
  • 论坛网站制作做网站排版用什么软件
  • 网站建设合同书(范本)市场监督管理局投诉电话是多少
  • 品牌网站建设小7蝌蚪推广赚佣金的平台
  • 诸城做网站找个人深圳专业网站建设定制
  • 百度多久收录一次网站运营怎么自学
  • 河北省老区建设促进会网站南京市建设局网站栖霞
  • 做私人没有备案的网站学校网站
  • 网站的专业白云定制型网站建设
  • 做网站的编程语言组合昆明市建设局官方网站
  • cms建立网站微企帮做网站