`

MeasureSpec类

 
阅读更多

截取MeasureSpec类的源代码出来看看

 

 /**
     * 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. There are three possible
     * modes:
     * <dl>
     * <dt>UNSPECIFIED</dt>
     * <dd>
     * The parent has not imposed any constraint on the child. It can be whatever size
     * it wants.
     * </dd>
     *
     * <dt>EXACTLY</dt>
     * <dd>
     * The parent has determined an exact size for the child. The child is going to be
     * given those bounds regardless of how big it wants to be.
     * </dd>
     *
     * <dt>AT_MOST</dt>
     * <dd>
     * The child can be as large as it wants up to the specified size.
     * </dd>
     * </dl>
     *
     * MeasureSpecs are implemented as ints to reduce object allocation. This class
     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
     */
    public static class MeasureSpec {
        private static final int MODE_SHIFT = 30;
        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;

        /**
         * Measure specification mode: The parent has not imposed any constraint
         * on the child. It can be whatever size it wants.
         */
        public static final int UNSPECIFIED = 0 << MODE_SHIFT;

        /**
         * Measure specification mode: The parent has determined an exact size
         * for the child. The child is going to be given those bounds regardless
         * of how big it wants to be.
         */
        public static final int EXACTLY     = 1 << MODE_SHIFT;

        /**
         * Measure specification mode: The child can be as large as it wants up
         * to the specified size.
         */
        public static final int AT_MOST     = 2 << MODE_SHIFT;

        /**
         * Creates a measure specification based on the supplied size and mode.
         *
         * The mode must always be one of the following:
         * <ul>
         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
         * </ul>
         *
         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
         * implementation was such that the order of arguments did not matter
         * and overflow in either value could impact the resulting MeasureSpec.
         * {@link android.widget.RelativeLayout} was affected by this bug.
         * Apps targeting API levels greater than 17 will get the fixed, more strict
         * behavior.</p>
         *
         * @param size the size of the measure specification
         * @param mode the mode of the measure specification
         * @return the measure specification based on size and mode
         */
        public static int makeMeasureSpec(int size, int mode) {
            if (sUseBrokenMakeMeasureSpec) {
                return size + mode;
            } else {
                return (size & ~MODE_MASK) | (mode & MODE_MASK);
            }
        }

        /**
         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
         * will automatically get a size of 0. Older apps expect this.
         *
         * @hide internal use only for compatibility with system widgets and older apps
         */
        public static int makeSafeMeasureSpec(int size, int mode) {
            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
                return 0;
            }
            return makeMeasureSpec(size, mode);
        }

        /**
         * Extracts the mode from the supplied measure specification.
         *
         * @param measureSpec the measure specification to extract the mode from
         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
         *         {@link android.view.View.MeasureSpec#AT_MOST} or
         *         {@link android.view.View.MeasureSpec#EXACTLY}
         */
        public static int getMode(int measureSpec) {
            return (measureSpec & MODE_MASK);
        }

        /**
         * Extracts the size from the supplied measure specification.
         *
         * @param measureSpec the measure specification to extract the size from
         * @return the size in pixels defined in the supplied measure specification
         */
        public static int getSize(int measureSpec) {
            return (measureSpec & ~MODE_MASK);
        }

        static int adjust(int measureSpec, int delta) {
            final int mode = getMode(measureSpec);
            int size = getSize(measureSpec);
            if (mode == UNSPECIFIED) {
                // No need to adjust size for UNSPECIFIED mode.
                return makeMeasureSpec(size, UNSPECIFIED);
            }
            size += delta;
            if (size < 0) {
                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
                        ") spec: " + toString(measureSpec) + " delta: " + delta);
                size = 0;
            }
            return makeMeasureSpec(size, mode);
        }

        /**
         * Returns a String representation of the specified measure
         * specification.
         *
         * @param measureSpec the measure specification to convert to a String
         * @return a String with the following format: "MeasureSpec: MODE SIZE"
         */
        public static String toString(int measureSpec) {
            int mode = getMode(measureSpec);
            int size = getSize(measureSpec);

            StringBuilder sb = new StringBuilder("MeasureSpec: ");

            if (mode == UNSPECIFIED)
                sb.append("UNSPECIFIED ");
            else if (mode == EXACTLY)
                sb.append("EXACTLY ");
            else if (mode == AT_MOST)
                sb.append("AT_MOST ");
            else
                sb.append(mode).append(" ");

            sb.append(size);
            return sb.toString();
        }
    }

  

 

       这里我介绍一点点MeasureSpec类的知识,源码是这样注释的:

A MeasureSpec encapsulates the layout requirements passed from parent to child.

 

       意思是说,一个MeasureSpec封装了从parent view传递到 child view 的布局要求。

       在自定义view 的时候,有时候需要重写onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法。事实上参数widthMeasureSpec就是父布局传递过来的一个MeasureSpec

 

 

       比如onMeasure的参数widthMeasureSpec这个值由高2位和低30位组成,高2位保存的值叫specMode,可以通过MeasureSpec.getMode()获取;低30位为specSize,同样可以由MeasureSpec.getSize()获取。

我是如何知道高2位和低30位这些信息的呢?请看如下代码:

 

  public static int getMode(int measureSpec) {
            return (measureSpec & MODE_MASK);
        }
 

 

获取Mode的时候,直接用一个与的位运算来得到Mode,再看MODE_MASK的定义:

private static final int MODE_SHIFT = 30;
private static final int MODE_MASK  = 0x3 << MODE_SHIFT;

 

 MODE_MASK是一个16进制的3左移30位得到的结果,就是也就是11000000000.....0000000000000(30个零)

 

 

所以我们得知,高2位对应了specMode,同理,低30位对应了specSize。
MeasureSpec类还有很多值得细究的东西,待我日后解析
 
分享到:
评论

相关推荐

    Android MeasureSpec的理解和源码的解析

    MeasureSpec类提供了静态方法来创建和解析MeasureSpec。例如,可以通过`MeasureSpec.makeMeasureSpec(int size, int mode)`创建一个MeasureSpec对象,其中size参数是测量大小,mode参数是测量模式。`MeasureSpec....

    《Android 群英传》读书笔记之 View 的测量

    Android提供了MeasureSpec类来辅助测量,这个类包含了一个模式(MODE)和一个大小(SIZE)两个部分,用于描述父视图对子视图尺寸的要求。 1. **MeasureSpec模式**: - EXACTLY:表示父视图已经指定了一个确切的...

    Android高级应用源码-自定义控件入门级demo.rar

    测量规则遵循MeasureSpec类中的模式。 5. **布局更新**:通过重写onLayout()方法,可以自定义控件的布局位置,这在创建自定义 ViewGroup 类时尤为重要。 6. **触摸事件处理**:通过覆盖onTouchEvent()方法,可以...

    DIY_View-master.zip

    这个方法决定了View的宽高,通常会使用MeasureSpec类提供的计算规则。我们需要确保View的尺寸能够适应其内容并满足父容器的约束。 ```java @Override protected void onMeasure(int widthMeasureSpec, int ...

    Android自定义控件开发入门与实战.zip

    理解MeasureSpec类及其工作原理是正确布局的关键。 五、动画与触摸事件 Android提供了多种动画机制,如Property Animation和View Animation,可用于自定义控件的动态效果。同时,自定义控件需要处理触摸事件,通常...

    面试_Android_PDF知识大全.pdf

    在measure过程中,父视图会通过MeasureSpec类向子视图传递测量规格。MeasureSpec提供了三种模式:UNSPECIFIED、EXACTLY和AT_MOST。UNSPECIFIED模式意味着父视图不对子视图有任何约束,子视图可以自由发展到期望的...

    自定义View进阶一

    MeasureSpec类提供了测量模式和大小,开发者需要根据MeasureSpec提供的信息来计算并设置View的尺寸。 4. **布局(Layout)过程**:自定义View也需要处理布局过程,通常通过重写onLayout()方法来确定子视图的位置。此...

    自定义viewgroup

    通常会使用MeasureSpec类来处理测量规则。 ```java @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int ...

    Android自定义动画View

    使用MeasureSpec类提供的方法可以帮助我们处理测量模式和大小。 3. **onLayout()**:如果我们的自定义View需要管理子视图,那么我们需要在这个方法中设置子视图的位置。不过,对于不包含子视图的简单自定义View,...

    应用源码之多个按钮左右相互挤压效果demo.zip

    这可能涉及到MeasureSpec类的使用,它是Android系统用来传递测量规格给View及其子View的重要工具。 3. 布局更新:当新的按钮被添加或移除时,FlowLayout需要重新计算并布局所有的子View。这可能涉及到监听器的设置...

    自定义View

    你可以使用MeasureSpec类提供的常量来获取父视图的约束条件,并根据这些条件计算出合适的尺寸。 四、触摸事件处理 自定义View可以通过重写`onTouchEvent()`来处理触摸事件。ACTION_DOWN、ACTION_UP、ACTION_MOVE等...

    自定义控件其实很简单1/12

    理解MeasureSpec类以及如何计算合适的尺寸至关重要。 5. **触摸事件处理**:通过覆盖`onTouchEvent()`方法,可以处理用户触摸屏幕的动作。通常需要处理ACTION_DOWN、ACTION_MOVE和ACTION_UP等事件,实现交互效果。 ...

    Android应用源码之自定义控件入门级demo.zip

    Android提供MeasureSpec类帮助处理父视图传递的尺寸约束。 4. **事件处理** 自定义控件可以重写`onTouchEvent()`来处理触摸事件,`onHoverEvent()`处理悬浮事件,`onKeyDown()`和`onKeyUp()`处理键盘事件。理解...

    Android流式布局

    这里可能需要用到MeasureSpec类,它提供了处理父视图对子视图尺寸约束的机制。 3. `onLayout()`方法:在此方法中,你需要确定每个子视图的位置。当一行无法容纳更多的子视图时,需要开始新的一行。可以维护一个变量...

    当前主流技术瀑布流的实现

    这涉及到Android的MeasureSpec类,用于传递父视图对子视图的尺寸约束。 5. **数据加载与监听**:当用户滚动到底部时,需要加载更多数据。可以通过RecyclerView的addOnScrollListener()方法添加滚动监听器,然后在`...

    Android自定义View

    介绍如何自定义View,并重写onMeasure方法重新测量高度和宽度, 讲解MeasureSpec类的使用方法 详见博文 http://blog.csdn.net/a87b01c14/article/details/50359226

    Android UI绘制流程及原理详解

    MeasureSpec类是Android中用于存储测量模式和大小的类。它将测量模式和大小存储在一个int类型的变量中,前2位为模式,而后30位为大小。 在测量过程中,View需要重写onMeasure()方法,该方法会将MeasureSpec对象作为...

    Android视图控件架构分析之View、ViewGroup

    测量阶段的核心工具是MeasureSpec类。MeasureSpec包含了一个32位的整数,高2位表示测量模式,低30位表示测量大小。测量模式有三种: 1. EXACTLY:精确值模式,通常发生在layout_width或layout_height被设置为具体...

    Android View如何测量

    在Android中,这个“眼睛”就是MeasureSpec类,它提供了精确的测量指导。 MeasureSpec是一个32位的整数,包含两种信息: 1. 高2位表示测量模式(MeasureSpec Mode),有三种模式: - EXACTLY:精确模式,当View的...

Global site tag (gtag.js) - Google Analytics