zoukankan      html  css  js  c++  java
  • 安卓高手之路 图形系统(4 Measure的算法)

    安卓高手之路 图形系统(4 Measure的算法) - 修补C++ - ITeye技术网站

    Java代码  收藏代码
    1.           
    2.   
    3.   
    4. /** 
    5.     * Does the hard part of measureChildren: figuring out the MeasureSpec to 
    6.     * pass to a particular child. This method figures out the right MeasureSpec 
    7.     * for one dimension (height or width) of one child view. 
    8.     * 
    9.     * The goal is to combine information from our MeasureSpec with the 
    10.     * LayoutParams of the child to get the best possible results. For example, 
    11.     * if the this view knows its size (because its MeasureSpec has a mode of 
    12.     * EXACTLY), and the child has indicated in its LayoutParams that it wants 
    13.     * to be the same size as the parent, the parent should ask the child to 
    14.     * layout given an exact size. 
    15.     * 
    16.     * @param spec The requirements for this view 
    17.     * @param padding The padding of this view for the current dimension and 
    18.     *        margins, if applicable 
    19.     * @param childDimension How big the child wants to be in the current 
    20.     *        dimension 
    21.     * @return a MeasureSpec integer for the child 
    22.     */  
    23.    public static int getChildMeasureSpec(int spec, int padding, int childDimension) {  
    24.        int specMode = MeasureSpec.getMode(spec);  
    25.        int specSize = MeasureSpec.getSize(spec);  
    26.   
    27.        int size = Math.max(0, specSize - padding);  
    28.   
    29.        int resultSize = 0;  
    30.        int resultMode = 0;  
    31.   
    32.        switch (specMode) {  
    33.        // Parent has imposed an exact size on us  
    34.        case MeasureSpec.EXACTLY:  
    35.            if (childDimension >= 0) {  
    36.                resultSize = childDimension;  
    37.                resultMode = MeasureSpec.EXACTLY;  
    38.            } else if (childDimension == LayoutParams.MATCH_PARENT) {  
    39.                // Child wants to be our size. So be it.  
    40.                resultSize = size;  
    41.                resultMode = MeasureSpec.EXACTLY;  
    42.            } else if (childDimension == LayoutParams.WRAP_CONTENT) {  
    43.                // Child wants to determine its own size. It can't be  
    44.                // bigger than us.  
    45.                resultSize = size;  
    46.                resultMode = MeasureSpec.AT_MOST;  
    47.            }  
    48.            break;  
    49.   
    50.        // Parent has imposed a maximum size on us  
    51.        case MeasureSpec.AT_MOST:  
    52.            if (childDimension >= 0) {  
    53.                // Child wants a specific size... so be it  
    54.                resultSize = childDimension;  
    55.                resultMode = MeasureSpec.EXACTLY;  
    56.            } else if (childDimension == LayoutParams.MATCH_PARENT) {  
    57.                // Child wants to be our size, but our size is not fixed.  
    58.                // Constrain child to not be bigger than us.  
    59.                resultSize = size;  
    60.                resultMode = MeasureSpec.AT_MOST;  
    61.            } else if (childDimension == LayoutParams.WRAP_CONTENT) {  
    62.                // Child wants to determine its own size. It can't be  
    63.                // bigger than us.  
    64.                resultSize = size;  
    65.                resultMode = MeasureSpec.AT_MOST;  
    66.            }  
    67.            break;  
    68.   
    69.        // Parent asked to see how big we want to be  
    70.        case MeasureSpec.UNSPECIFIED:  
    71.            if (childDimension >= 0) {  
    72.                // Child wants a specific size... let him have it  
    73.                resultSize = childDimension;  
    74.                resultMode = MeasureSpec.EXACTLY;  
    75.            } else if (childDimension == LayoutParams.MATCH_PARENT) {  
    76.                // Child wants to be our size... find out how big it should  
    77.                // be  
    78.                resultSize = 0;  
    79.                resultMode = MeasureSpec.UNSPECIFIED;  
    80.            } else if (childDimension == LayoutParams.WRAP_CONTENT) {  
    81.                // Child wants to determine its own size.... find out how  
    82.                // big it should be  
    83.                resultSize = 0;  
    84.                resultMode = MeasureSpec.UNSPECIFIED;  
    85.            }  
    86.            break;  
    87.        }  
    88.        return MeasureSpec.makeMeasureSpec(resultSize, resultMode);  
    89.    }  
     /**
         * 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。从而打破了这种循环依赖。

  • 相关阅读:
    js学习笔记之(call、apply)
    windows8 应用的激活与挂起
    SharePoint2010分享
    Windows8 Metro 设计与开发vs11风格样式
    windows8 应用激活
    Windows8 Metro 设计与开发平台预览
    windows8 账户图片设置
    Windows8 Metro 设计与开发必须关注的新特性
    Windows8 Metro 设计与开发你不知道的C模型
    Windows8 Metro 设计与开发VS11的win8模拟器
  • 原文地址:https://www.cnblogs.com/seven1979/p/4369631.html
Copyright © 2011-2022 走看看