`
luochuang
  • 浏览: 24050 次
  • 性别: Icon_minigender_1
  • 来自: 成都
最近访客 更多访客>>
社区版块
存档分类
最新评论

MeasureSpec

 
阅读更多

MeasureSpec和LayoutParams的对应关系

 

当View采用固定宽/高的时候,不管父容器的MeasureSpec是什么,View的MeasureSpec都是精确模式并且其大小遵循Layoutparams中的大小。

 

当View的宽/高是match_parent时,如果父容器的模式是精准模式,那么View也是精准模式并且其大小是父容器的剩余空间;如果父容器是最大模式,那么View也是最大模式并且其大小不会超过父容器的剩余空间。

 

当View的宽/高是wrap_content时,不管父容器的模式是精准还是最大化,View的模式总是最大化并且大小不能超过父容器的剩余空间。

 

 

 

具体流程

 

1. View的measure过程 

 

View的measure过程由其measure方法来完成,measure方法是一个final类型的方法,这意味着子类不能重写此方法,在View的measure方法中会去调用View的onMeasure方法,因此只需要看onMeasure的实现即可。

 

 

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    }

    public static int getDefaultSize(int size, int measureSpec) {
        int result = size;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        switch (specMode) {
        case MeasureSpec.UNSPECIFIED:
            result = size;
            break;
        case MeasureSpec.AT_MOST:
        case MeasureSpec.EXACTLY:
            result = specSize;
            break;
        }
        return result;
    }

 

 

这里很显然根据不同的 SpecMode 值来返回不同的 result 值,也就是 SpecSize。 在 AT_MOST 和 EXACTLY 模式下,都返回 SpecSize 这个值,即 View 在这两种模式下的测量 宽和高直接取决于 SpecSize。

 

对于一个直接继承自 View 的自定义 View 来说,它的 wrap_content 和 match_parent 属性的效果是一样的。因此如果要实现自定义 View 的 wrap_content,则要重写 onMeasure 方法,并对自定义 View 的 wrap_content 属性进行处理

 

 

2、ViewGroup的measure过程

 

对于ViewGroup来说,除了完成自己的measure过程以外,还会遍历去调用所有子元素的measure方法,各个子元素再递归去执行这个过程。和View不同的是,ViewGroup是一个抽象类,因此它没有重写View的onMeasure方法,但是它提供了一个叫measureChildren的方法。

 

 

    protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
        final int size = mChildrenCount;
        final View[] children = mChildren;
        for (int i = 0; i < size; ++i) {
            final View child = children[i];
            if ((child.mViewFlags & VISIBILITY_MASK) != GONE) {
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
            }
        }
    }

    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);
    }

 

 

measureChild的思想就是取出子元素的LayoutParams,然后再通过getChildMeasureSpec来创建子元素的MeasureSpec,接着将MeasureSpec直接传递给View的measure方法来进行测量。

 

ViewGroup并没有定义其测量的具体过程,这是因为ViewGroup是一个抽象类,其测量过程的onMeasure方法需要各个子类去具体实现,比如LinearLayout、RelativeLayout等。

 

为什么ViewGroup不像View一样对其onMeasure方法做统一的实现呢?那是因为不同的ViewGroup子类有不同的布局特性,这导致它们的测量细节各不相同,比如LinearLayout和RelativeLayout这两者的布局特性显然不同,因此ViewGroup无法做统一实现。

 

分享到:
评论

相关推荐

    MeasureSpec三种测量模式详解例子

    MeasureSpec是Android系统中用于布局管理的一个重要概念,它在处理View的尺寸计算时起到关键作用。MeasureSpec是由两个部分组成的:mode(模式)和size(大小)。在这个详解例子中,我们将深入探讨MeasureSpec的三种...

    Android MeasureSpec的理解和源码的解析

    1. 当子View的LayoutParams的宽(高)采用具体的值(如100px)时且父容器的MeasureSpec为MeasureSpec.EXACTLY或者MeasureSpec.AT_MOST或者MeasureSpec.UNSPECIFIED时:系统返回给该子View的specMode就为MeasureSpec....

    类似时光网IOS城市列表(ListView)效果.zip

    int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE &gt;&gt; 2,MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, expandSpec); } 搜索功能其实没写进demo里面,从项目里整理出来太麻烦了。...

    android自定义组件(七) onMeasure测量尺寸

    1. **设置MeasureSpec**:MeasureSpec是一个组合了模式(MeasureSpec MODE)和大小(MeasureSpec SIZE)的32位整数。它包含了父视图对当前视图的尺寸限制。MeasureSpec有三种模式: - `MeasureSpec.EXACTLY`:父...

    android自定义控件-侧滑菜单

    mode共有三种情况,取值分别为MeasureSpec.UNSPECIFIED, MeasureSpec.EXACTLY, MeasureSpec.AT_MOST。 MeasureSpec.EXACTLY是精确尺寸, 当我们将控件的layout_width或layout_height指定为具体数值时如andorid ...

    自定义控件属性

    `onMeasure`方法用于计算控件的大小,它有三种测量模式:MeasureSpec.EXACTLY、MeasureSpec.AT_MOST和MeasureSpec.UNSPECIFIED。 1. **MeasureSpec.EXACTLY**:这是最常见的模式,表示父视图已经指定了确切的大小。...

    Android视图的绘制流程(上) View的测量

    通过`MeasureSpec`的`makeMeasureSpec`方法可以创建一个MeasureSpec,同时可以用`getMode`和`getSize`获取其specMode和specSize。 在View的`onMeasure`方法中,通常会调用`setMeasuredDimension`来设置View的测量...

    自定义view

    int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { // 设置默认宽度 result = ...

    android 动态添加布局

    MeasureSpec包含模式(MeasureSpec MODE)和大小(Size)两部分,模式分为EXACTLY(固定大小)、AT_MOST(最大不超过)和UNSPECIFIED(无限制)。我们需要根据MeasureSpec来计算视图的实际大小。 例如,如果要动态...

    测量view的宽高 以及 动态设置View的位置

    `onMeasure()`方法有两个参数:`MeasureSpec`,它们分别代表父容器对View宽度和高度的要求。MeasureSpec包含两个部分:模式(Mode)和大小(Size)。模式可以是EXACTLY(表示必须精确到给定大小)、AT_MOST(表示不...

    自定义控件量测主过程

    此方法接收两个参数,`MeasureSpec`对象,分别代表父视图对当前视图宽度和高度的要求。MeasureSpec包含一个模式(MODE)和一个大小(SIZE)。模式有三种:EXACTLY(精确)、AT_MOST(最大不超过)和UNSPECIFIED(未...

    自定义ViewGroup

    int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(parentHeight, MeasureSpec.AT_MOST); for (int i = 0; i (); i++) { getChildAt(i).measure(childWidthMeasureSpec, childHeightMeasureSpec); } ...

    自定义View和viewGroup

    在自定义View或ViewGroup时,需要根据父容器的MeasureSpec和自己的LayoutParams来计算自己的MeasureSpec。 结论 ---- 自定义View和ViewGroup是Android应用程序中非常重要的组件,它们都是Android UI组件树的基础。...

    ScrollView_android_

    heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize + statusBarHeight, MeasureSpec.EXACTLY); } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (heightMode != MeasureSpec....

    动态设置textview的高.

    int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.EXACTLY: // 父视图指定了确切的大小,使用这个大小 result = ...

    自定义视图实现水波从中心扩散效果_android源码.zip

    setMeasuredDimension(measureSpec(widthMeasureSpec), measureSpec(heightMeasureSpec)); } private int measureSpec(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); ...

    Android获取webView快照与屏幕截屏的方法

    webView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); webView.layout(0, 0, webView.getMeasuredWidth(), webView....

    Android评论图片可移动顺序选择器(推荐)

    `MeasureSpec.getSize()`获取父视图指定的大小,而`MeasureSpec.makeMeasureSpec()`则用于创建一个MeasureSpec对象,用于子视图的测量。 7. **测量过程**: `width`和`height`被设置为相等且基于屏幕宽度进行计算,...

    Android中onMesure研究(1)项目源码

    `onMeasure()`方法接收两个参数:`MeasureSpec`对象,分别代表父视图对当前视图宽度和高度的要求。 MeasureSpec包含两个部分:模式(Mode)和大小(Size)。模式分为三种: 1. `EXACTLY`:父视图已经确定了具体的...

Global site tag (gtag.js) - Google Analytics