zoukankan      html  css  js  c++  java
  • Android View measure (三) 经常用法


    ViewGroup.measureChildren()
    ViewGroup.measureChild()
    ViewGroup.measureChildWithMargins()


        /**
         * Ask one of the children of this view to measure itself, taking into
         * account both the MeasureSpec requirements for this view and its padding
         * and margins. The child must have MarginLayoutParams The heavy lifting is
         * done in getChildMeasureSpec.
         *
         * @param child The child to measure
         * @param parentWidthMeasureSpec The width requirements for this view
         * @param widthUsed Extra space that has been used up by the parent
         *        horizontally (possibly by other children of the parent)
         * @param parentHeightMeasureSpec The height requirements for this view
         * @param heightUsed Extra space that has been used up by the parent
         *        vertically (possibly by other children of the parent)
         */
        protected void measureChildWithMargins(View child,
                int parentWidthMeasureSpec, int widthUsed,
                int parentHeightMeasureSpec, int heightUsed) {
    		// 1 类型转换
            final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
    
    
    		// 2 getChildMeasureSpec方法
            final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                    mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
                            + widthUsed, lp.width);
            final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
                    mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin
                            + heightUsed, lp.height);
    
    
            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
    	




    此方法针对第一个參数传递的子视图进行Measure操作。
    1. 传递的子视图LayoutParams必须是或者继承自MarginLayoutParams,否者会抛出转换异常

        /**
         * 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.FILL_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.FILL_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.FILL_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);
        }	





        protected void measureChildWithMargins(View child,
                int parentWidthMeasureSpec, int widthUsed,
                int parentHeightMeasureSpec, int heightUsed) {
    
    
    		// 1 ....	
    			
    		// 2 getChildMeasureSpec方法
            final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                    mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
                            + widthUsed, lp.width);
    	}		





    调用此方法处。看看这三个參数的详细含义。
    1. spec : 此视图要求的规格 【parentWidthMeasureSpec】
    2. padding : 当前ViewGroup视图的padding值与传入子视图的margin值 【mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin + widthUsed】?widthUsed
    3. childDimension : 传入參数的视图,期望展示多大【lp.width】

    ** 举一个样例




    扩展:MeasureSpec方法与拼接方式



        /**
         * Utility to reconcile a desired size with constraints imposed by a MeasureSpec.
         * Will take the desired size, unless a different size is imposed by the constraints.
         *
         * @param size How big the view wants to be
         * @param measureSpec Constraints imposed by the parent
         * @return The size this view should be.
         */
        public static int resolveSize(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:
                result = Math.min(size, specSize);
                break;
            case MeasureSpec.EXACTLY:
                result = specSize;
                break;
            }
            return result;
        }



            /**
             * 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>
             *
             * @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) {
                return size + mode;
            }


        /**
         * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
         * measured width and measured height. Failing to do so will trigger an
         * exception at measurement time.</p>
         *
         * @param measuredWidth the measured width of this view
         * @param measuredHeight the measured height of this view
         */
        protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
            mMeasuredWidth = measuredWidth;
            mMeasuredHeight = measuredHeight;
    
            mPrivateFlags |= MEASURED_DIMENSION_SET;
        }
    	
    	
        /**
         * The width of this view as measured in the most recent call to measure().
         * This should be used during measurement and layout calculations only. Use
         * {@link #getWidth()} to see how wide a view is after layout.
         *
         * @return The measured width of this view.
         */
        public final int getMeasuredWidth() {
            return mMeasuredWidth;
        }
    
        /**
         * The height of this view as measured in the most recent call to measure().
         * This should be used during measurement and layout calculations only. Use
         * {@link #getHeight()} to see how tall a view is after layout.
         *
         * @return The measured height of this view.
         */
        public final int getMeasuredHeight() {
            return mMeasuredHeight;
        }





  • 相关阅读:
    redhat下设置网桥br0
    RackSpace推开源云计算平台OpenStack震动业界
    centos5.2 64位yum国内源之首选 上海交大(未验证)
    image config
    编程的四种境界
    怎样学好C语言
    利用SSL加密HTTP通道加强IIS安全性
    Sql Server 日期函数
    如何启用Oracle 11g的默认用户Scott
    ASP.NET自定义错误处理页面的添加
  • 原文地址:https://www.cnblogs.com/lytwajue/p/6918185.html
Copyright © 2011-2022 走看看