/** * Does the hard part of measureChildren: figuring out the MeasureSpec to * pass to a particular child. This method figures out the right MeasureSpec * for one dimension (height or width) of one child view. * * The goal is to combine information from our MeasureSpec with the * LayoutParams of the child to get the best possible results. For example, * if the this view knows its size (because its MeasureSpec has a mode of * EXACTLY), and the child has indicated in its LayoutParams that it wants * to be the same size as the parent, the parent should ask the child to * layout given an exact size. * * @param spec The requirements for this view * @param padding The padding of this view for the current dimension and * margins, if applicable * @param childDimension How big the child wants to be in the current * dimension * @return a MeasureSpec integer for the child */ public static int getChildMeasureSpec(int spec, int padding, int childDimension) { int specMode = MeasureSpec.getMode(spec); int specSize = MeasureSpec.getSize(spec); int size = Math.max(0, specSize - padding); int resultSize = 0; int resultMode = 0; switch (specMode) { // Parent has imposed an exact size on us case MeasureSpec.EXACTLY: if (childDimension >= 0) { resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size. So be it. resultSize = size; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } break; // Parent has imposed a maximum size on us case MeasureSpec.AT_MOST: if (childDimension >= 0) { // Child wants a specific size... so be it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size, but our size is not fixed. // Constrain child to not be bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } break; // Parent asked to see how big we want to be case MeasureSpec.UNSPECIFIED: if (childDimension >= 0) { // Child wants a specific size... let him have it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size... find out how big it should // be resultSize = 0; resultMode = MeasureSpec.UNSPECIFIED; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size.... find out how // big it should be resultSize = 0; resultMode = MeasureSpec.UNSPECIFIED; } break; } return MeasureSpec.makeMeasureSpec(resultSize, resultMode); }
这个Measure算法主要是算child的测量方式和大小的。主要根据两种根据:
1. 自身的测量方式(MeasureSpec EXACTLY,AT_MOST,UNSPECIFIED)【这个是parent传过来的】
2. 自身的大小 【这个是parent传过来的】
3. 自己的padding【计算得到】
4. child的大小【child的LayoutParam得到】
根据以上四个推测出child的MeasureSpec 。也就是大小和测量方式。
child的请求大小来确定到底child应该有多宽以及应该怎么测量。
下面的逻辑比较多。
1.如果当前View是Exactly。那么也就是说有了固定的大小。
那么Child如果说是一个固定的LayoutParam.width 或者 height,那么返回结果resultSize 就设置为这个固定值。
如果child是wrapContent,那么resultSize 就设置为当前这个View的工作区大小。也就是去除pad和margin
的大小。同时,测量方式设置为AT_MOST
如果child是match_parent,那么由于当前View是固定大小的。那么resultSize 就设置为当前这个View的工作区大小。也就是去除pad和margin
的大小。同时,测量方式设置为EXACTLY
2.如果当前View是MeasureSpec.AT_MOST。也就是说有个最大值。也是这三种情况
a.fixed
这个时候,当前View可以无限大,并且child有个固定值。那么就设置这个值吧。 这个地方
,没有做越界判断,因此有时候会出现一个子View非常大,撑破了父View的情况。google在这里
算不算是一个bug呢?也就是当前的currrentView为wrap_content.但是parentView却有一个fixed value。 同时,childView也有一个fixed Value。这个时候,如果childView的大小超过了parentView。 则会出现childView显示不全的现象。
b.wrap_content
同理,传入AT_MOST.但是不超过当前View的大小。【这个是与当前View为EXACTLY的情况一样】
c.fill_parent
这种情况也非常奇怪。发生在
currentView是wrap_content.而childView是fill_parent的情况。这个时候就没办法搞了。
这个时候,就告诉子View你也没有固定的大小。也就是说循环依赖产生了。唯一的办法是让childView 继续wrap_content.也就是废掉这个fill_parent。从而打破了这种循环依赖。
相关推荐
这类工具背后的实现往往涉及到图像处理算法、自动化脚本(如JavaScript或Python)、以及图形用户界面设计。它们通常有跨平台的特性,可以运行在Windows、Mac OS或Linux系统上。 6. 常见的一键切图工具: - Sketch...
在Android开发中,自定义View是一项常见的需求,用于实现独特的用户界面效果,增强用户体验。"波浪滚动圆球View"就是一个这样的自定义组件,它模仿了魅族、华为等品牌设备上的滚动效果,通过波浪式的动画使得圆球在...
描述中的“user to measure object size”进一步明确了这个工具是为用户提供测量物体大小的能力。在计算机上,这可能通过交互式的图形用户界面实现,让用户能够点击或拖动来确定物体的长度、宽度或其他尺寸。 从...
总结来说,CircletextView的源码分析涵盖了Android自定义视图的基本原理,包括文字测量、视图尺寸计算、图形绘制和性能优化。通过深入理解这些概念,开发者不仅可以使用CircletextView库,还能以此为基础创建更多...
1. **自定义布局容器**:在JavaFX或Android中,需要自定义一个布局容器类,继承自`javafx.scene.layout.Region`或`android.view.ViewGroup`,然后重写相关的测量、布局和绘制方法,如`measure()`, `layout()`, 和 `...