美文网首页
MeasureSpec 理解

MeasureSpec 理解

作者: 大盗海洲 | 来源:发表于2019-06-04 14:37 被阅读0次

MeasureSpec 封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求

public class XfermodeView extends View {
  @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int wSize;

        int wMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthMeasureSize = MeasureSpec.getSize(widthMeasureSpec);

        if (wMode ==MeasureSpec.EXACTLY){
            //精确模式,用其本身大小
            wSize=widthMeasureSize;
        }else {
            WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics displayMetrics = new DisplayMetrics();
            wm.getDefaultDisplay().getMetrics(displayMetrics);
            int widthPixels = displayMetrics.widthPixels;
            //手动设置为屏幕宽度的一半
            wSize=widthPixels/2;
        }
        setMeasuredDimension(wSize,heightMeasureSpec);
    }
}

3种模式

  • UNSPECIFIED: 不对View大小做限制,ScrollView
  • EXACTLY :确切的大小,如:200dp、match_parent
  • AT_MOST : 大小不可超过父布局剩余大小,若wrap_content

子View 的 MeasureSpec是由父View的MeasureSpec 和自身的LayoutParams共同决定的

public abstract class ViewGroup extends View implements ViewParent, ViewManager {
      /**
     * Ask all of the children of this view to measure themselves, taking into
     * account both the MeasureSpec requirements for this view and its padding.
     * We skip children that are in the GONE state The heavy lifting is done in
     * getChildMeasureSpec.
     *
     * @param widthMeasureSpec The width requirements for this view
     * @param heightMeasureSpec The height requirements for this view
     */
    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) {
              //跳过View Visiable是gone
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
            }
        }
    }


  /**
     * Ask one of the children of this view to measure itself, taking into
     * account both the MeasureSpec requirements for this view and its padding.
     * The heavy lifting is done in getChildMeasureSpec.
     *
     * @param child The child to measure
     * @param parentWidthMeasureSpec The width requirements for this view
     * @param parentHeightMeasureSpec The height requirements for this view
     */
    protected void measureChild(View child, int parentWidthMeasureSpec,
            int parentHeightMeasureSpec) {
        final LayoutParams lp = child.getLayoutParams();
        //子View的MeasureSpec 是子View自身的LayoutParams 和父View的MeasureSpec 组成
        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                mPaddingLeft + mPaddingRight, lp.width);
        final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
                mPaddingTop + mPaddingBottom, lp.height);

        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }

}

//ViewGroup.java
 /**
     * 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);
        //父View布局剩余空间大小
        int size = Math.max(0, specSize - padding);

        int resultSize = 0;
        int resultMode = 0;
         // childDimension 是子view的LayoutParams具体的宽高
        switch (specMode) {
        // Parent has imposed an exact size on us
        case MeasureSpec.EXACTLY://父View有准确的dp值或者match_parent
            if (childDimension >= 0) {//子View 的childDimension大于0,则子View的大小为其本身且mode是EXACTLY
                resultSize = childDimension;
                resultMode = MeasureSpec.EXACTLY;
            } else if (childDimension == LayoutParams.MATCH_PARENT) {
                //子View的大小为父View布局剩余空间大小
                // 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.
                //子View的大小为父View布局剩余空间大小
                resultSize = size;
                resultMode = MeasureSpec.AT_MOST;
            }
            break;

        // Parent has imposed a maximum size on us
        case MeasureSpec.AT_MOST://父View是wrap_content
            if (childDimension >= 0) {
                // Child wants a specific size... so be it
                //子View的大小为其本身
                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.
               //子View的大小为父View布局剩余空间大小
                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.
                //子View的大小为父View布局剩余空间大小
                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
                //子View大小为其本身大小
                resultSize = childDimension;
                resultMode = MeasureSpec.EXACTLY;
            } else if (childDimension == LayoutParams.MATCH_PARENT) {
                // Child wants to be our size... find out how big it should
                // be
                //子View大小为0
                resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                resultMode = MeasureSpec.UNSPECIFIED;
            } else if (childDimension == LayoutParams.WRAP_CONTENT) {
                // Child wants to determine its own size.... find out how
                // big it should be
                //子View大小为0
                resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                resultMode = MeasureSpec.UNSPECIFIED;
            }
            break;
        }
        //noinspection ResourceType
        return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
    }


参考地址:
MeasureSpec详解

相关文章

  • 理解MeasureSpec

    4.2 理解MeasureSpec 为了更好地理解View的测量过程,我们还需要理解MeasureSpec。从名字...

  • 理解MeasureSpec

    MeasureSpec在很大程度上决定了一个View的尺寸规格,因为父容器影响View的MeasureSpec的创...

  • 理解MeasureSpec

    MeasureSpec是View的一个静态内部类,它通过将SpecMode和SpecSize打包成一个int值来避...

  • 理解MeasureSpec

    1.左移和右移 java中的移位运算符有三种: 左移<<左移就是将左边的操作数在内存中的二进制数据左移指定的位数,...

  • MeasureSpec 理解

    MeasureSpec 封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求 ...

  • MeasureSpec理解

    简要   今天来聊聊MeasureSpec,记得刚接触的也感觉很难理解,知其然不知其所以然。MeasureSpec...

  • Android 理解MeasureSpec

    Android View 的测量过程中使用到了MeasureSpec,正如其字面意思所表达的那个-“测量规格”。V...

  • 简单理解MeasureSpec

    MeasureSpec在很大程度上决定了一个View的尺寸规格,因为父容器影响View的MeasureSpec的创...

  • 4.2 理解MeasureSpec

    1. MeasureSpec MeasureSpec代表一个32位的int值,高2位代表SpecMode,低30位...

  • 重新理解MeasureSpec

    1 概述 网上有许多非常好的文章都在介绍MeasureSpec的测量规则,但是没有介绍MeasureSpec的作用...

网友评论

      本文标题:MeasureSpec 理解

      本文链接:https://www.haomeiwen.com/subject/bqqlxctx.html