Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
这些view绘制流程的细节,你真的知道吗英语_好用的画流程图的软件,希望能够帮助你!!!。
看过View绘制过程源码的小伙伴都知道,在ViewGroup中有 measureChild() 这么一个方法会对子view的尺寸进行计算。那么我们先来简单地看一看这部分的源码。
protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) { final LayoutParams lp = child.getLayoutParams(); final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft + mPaddingRight, lp.width); final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec, mPaddingTop + mPaddingBottom, lp.height); child.measure(childWidthMeasureSpec, childHeightMeasureSpec); }
主要的内容是,子View在测量前会参考父View传入的 measureSpec 并结合自身的layoutParams得到自身的measureSpec,然后调用子View measure方法。其实主要看看 getChildMeasureSpec() 方法干了些什么。
public static int getChildMeasureSpec(int spec, int padding, int childDimension) { // 第一步:获取到父View 提供的建议尺寸和测量模式 int specMode = MeasureSpec.getMode(spec); int specSize = MeasureSpec.getSize(spec); int size = Math.max(0, specSize - padding); int resultSize = 0; int resultMode = 0; // 第二步:根据 父View 的建议尺寸和测量模式,结合自身的layoutParams计算出自己的size和mode switch (specMode) { // 父view对子view实施了一个精确的尺寸 case MeasureSpec.EXACTLY: if (childDimension >= 0) { // 当子view的尺寸大于0时,表明是个明确的尺寸,赋予EXACTLY resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { // 子view 的尺寸与父view相等,也表明是个明确的尺寸,赋予EXACTLY resultSize = size; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // 子view的尺寸根据自己的子view或内容来定。但不能超过父View的尺寸 resultSize = size; resultMode = MeasureSpec.AT_MOST; } break; // 一下部分省略 }
由源码可知,里面调用了getChildMeasureSpec()方法,把父View的 MeasureSpec 以及 子View 自身的 layoutParams 属性传递进去来获取 子View 的 MeasureSpec,这也印证了“子View的MeasureSpec由父容器的 MeasureSpec 和自身的 LayoutParams 共同决定”这个结论。
那到底这些变量到底是什么?都有哪些作用呢?我们下面来看一下。
官网介绍: A MeasureSpec encapsulates the layout requirements passed from parent to child. Each MeasureSpec represents a requirement for either the width or the height. A MeasureSpec is comprised of a size and a mode.
其低30位是父控件给出的建议尺寸——size;高2位是父View自身的测量模式,给予子View进行参考。
从官方信息可以知道。MeasureSpec 中封装了父View 传递给子View 的布局要求——宽度要求和高度要求。MeasureSpec 包含了 size 和 mode这两个重要的数据,size+mode 共同影响了子view的测量结果。
上述Mode的取值有一下三种:
即精确值模式。当控件的 layout_width 或 layout_height 指定为具体数值时,例如android:layout_width="108dp",或者指定为 match_parent 时,就会使用EXACTLY模式。
即最大值模式。当控件的 layout_width 或 layout_height 设置为 warp_content 时,控件的大小一般随着控件的子控件或者自身内容的变化而变化,但是最大也不能超过父控件允许的最大尺寸。所以当A(设置为warp_content)的父控件的大小确定后,不管A的子控件比父控件大多少,A最终的大小(展示的部分)也只会等于父控件的大小。
即不指明模式。不会指明(限制、约束)控件的大小,控件本身能够多大就多大。在这种模式下,子控件就不会受到约束,完整地进行绘制。一般这种模式,用于自定义的控件中进行特殊的测量。
上面我们也说到了 子View的MeasureSpec由父容器的 MeasureSpec 和自身的 LayoutParams 共同决定。那到底这两个不同的值,会使子View的MeasureSpec有哪些结果。
父View的MeasureSpec |
子View的layoutParams |
子View的MeasureSpec |
EXACTLY + size |
数值 |
EXACTLY + 数值 |
WARP_CONTENT |
AT_MOST + size |
|
MATCH_PARENT |
EXACTLY + size |
|
AT_MOST + size |
数值 |
EXACTLY + 数值 |
WARP_CONTENT |
AT_MOST + size |
|
MATCH_PARENT |
EXACTLY + size AT_MOST + size |
|
UNSPECIFIED + size |
数值 |
EXACTLY + 数值 |
WARP_CONTENT |
UNSPECIFIED + 0 |
|
MATCH_PARENT |
UNSPECIFIED + 0 |
以上就是View绘制过程中 MeasureSpec 的一些细节。还有哪些其他细节是你觉得可以说说的呢?告诉我吧。
今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
上一篇
已是最后文章
下一篇
已是最新文章