FrameWork之View的绘制过程(下)

      上一篇说了View测量逻辑调用,以及父视图如何影响到View的测量等概念,这一篇测量在代码中是怎么具体实现的。

      首先说ViewGroup类吧,因为该类是所有容器类的父类,所谓容器类就是布局类,比如LinearLayout、TableLayout等,用来容纳VIew控件的。

          ViewGroup提供了三个类似的方法用于对子视图进行measure()操作:

          ①measureChildren():正如其名,Children是复数啊,该方法内部使用for循环调用measureChild()方法对每一个子视图进行measure操作,源码如下:

            

<span style="font-size:18px;"> protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
        final int size = mChildrenCount;
        //所有的子视图,至于xml文件如何转换为View对象的已经介绍过了
        final View[] children = mChildren;
        //采用for循环遍历
        for (int i = 0; i < size; ++i) {
            final View child = children[i];
            if ((child.mViewFlags & VISIBILITY_MASK) != GONE) {
            	//如果可见的话才对子视图进行测量
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
            }
        }
    }</span>
              ② measureChild():为指定的子视图进行measure操作,measureChildren()方法会调用此方法,源码如下:

            

<span style="font-size:18px;">  protected void measureChild(View child, int parentWidthMeasureSpec,
            int parentHeightMeasureSpec) {
    	//首先获取其布局参数,前面的关于xml文件转换为View对象的文章中已经说过,
    	//在转换过程中已经为LayoutParams赋值了,
        final LayoutParams lp = child.getLayoutParams();

        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                mPaddingLeft + mPaddingRight, lp.width);
        final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
                mPaddingTop + mPaddingBottom, lp.height);
        //开始调用measure函数进行测量
        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }</span>
          我记得好像说过LayoutParams类是个什么情况 - -没有详细拿出来,LayoutParams类相当重要啊,每一个容器类都会有一个LayoutParams的内部类,一个视图会使用LayoutParams类来封装必要信息告诉父容器怎么去为自己布局,ViewGroup的LayoutParams以及MarginLayoutParams类如下:

        

<span style="font-size:18px;">public static class LayoutParams {
        /**
         * Special value for the height or width requested by a View.
         * FILL_PARENT means that the view wants to be as big as its parent,
         * minus the parent's padding, if any. This value is deprecated
         * starting in API Level 8 and replaced by {@link #MATCH_PARENT}.
         */
     
        //这个值熟悉吗,这是4.1.2版本了,此属性已经不被推荐使用
        public static final int FILL_PARENT = -1;

        //熟悉吗
        public static final int MATCH_PARENT = -1;

   
        public static final int WRAP_CONTENT = -2;

        
        public int width;
     
        public int height;

      
        public LayoutAnimationController.AnimationParameters layoutAnimationParameters;

        public LayoutParams(Context c, AttributeSet attrs) {
            TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_Layout);
            setBaseAttributes(a,
                    R.styleable.ViewGroup_Layout_layout_width,
                    R.styleable.ViewGroup_Layout_layout_height);
            a.recycle();
        }

   
        public LayoutParams(int width, int height) {
            this.width = width;
            this.height = height;
        }

        /**
         * @param source The layout params to copy from.
         */
        public LayoutParams(LayoutParams source) {
            this.width = source.width;
            this.height = source.height;
        }

        /**
         * Used internally by MarginLayoutParams.
         * @hide
         */
        LayoutParams() {
        }
        protected void setBaseAttributes(TypedArray a, int widthAttr, int heightAttr) {
            width = a.getLayoutDimension(widthAttr, "layout_width");
            height = a.getLayoutDimension(heightAttr, "layout_height");
        }

        /**
         * @hide
         */
        public void onResolveLayoutDirection(int layoutDirection) {
        }

        /**
         * @hide
         */
        public String debug(String output) {
            return output + "ViewGroup.LayoutParams={ width="
                    + sizeToString(width) + ", height=" + sizeToString(height) + " }";
        }

        public void onDebugDraw(View view, Canvas canvas) {
        }
        protected static String sizeToString(int size) {
            if (size == WRAP_CONTENT) {
                return "wrap-content";
            }
            if (size == MATCH_PARENT) {
                return "match-parent";
            }
            return String.valueOf(size);
        }
    }

    /**
     * Per-child layout information for layouts that support margins.
     * See
     *继承了本类的LayoutParams
     */
    public static class MarginLayoutParams extends ViewGroup.LayoutParams {
       
        public int leftMargin;

        public int topMargin;

        public int rightMargin;

        public int bottomMargin;

        /**
         * @hide
         */
        @ViewDebug.ExportedProperty(category = "layout")
        public int startMargin = DEFAULT_RELATIVE;

        /**
         * @hide
         */
        @ViewDebug.ExportedProperty(category = "layout")
        public int endMargin = DEFAULT_RELATIVE;

        static private final int DEFAULT_RELATIVE = Integer.MIN_VALUE;

 public MarginLayoutParams(Context c, AttributeSet attrs) {
            super();

            TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_MarginLayout);
            setBaseAttributes(a,
                    R.styleable.ViewGroup_MarginLayout_layout_width,
                    R.styleable.ViewGroup_MarginLayout_layout_height);

            int margin = a.getDimensionPixelSize(
                    com.android.internal.R.styleable.ViewGroup_MarginLayout_layout_margin, -1);
            if (margin >= 0) {
                leftMargin = margin;
                topMargin = margin;
                rightMargin= margin;
                bottomMargin = margin;
            } else {
                leftMargin = a.getDimensionPixelSize(
                        R.styleable.ViewGroup_MarginLayout_layout_marginLeft, 0);
                topMargin = a.getDimensionPixelSize(
                        R.styleable.ViewGroup_MarginLayout_layout_marginTop, 0);
                rightMargin = a.getDimensionPixelSize(
                        R.styleable.ViewGroup_MarginLayout_layout_marginRight, 0);
                bottomMargin = a.getDimensionPixelSize(
                        R.styleable.ViewGroup_MarginLayout_layout_marginBottom, 0);
                startMargin = a.getDimensionPixelSize(
                        R.styleable.ViewGroup_MarginLayout_layout_marginStart, DEFAULT_RELATIVE);
                endMargin = a.getDimensionPixelSize(
                        R.styleable.ViewGroup_MarginLayout_layout_marginEnd, DEFAULT_RELATIVE);
            }

            a.recycle();
        }

        public MarginLayoutParams(int width, int height) {
            super(width, height);
        }

        /**
         * Copy constructor. Clones the width, height and margin values of the source.
         * @param source The layout params to copy from.
         */
        public MarginLayoutParams(MarginLayoutParams source) {
            this.width = source.width;
            this.height = source.height;

            this.leftMargin = source.leftMargin;
            this.topMargin = source.topMargin;
            this.rightMargin = source.rightMargin;
            this.bottomMargin = source.bottomMargin;
            this.startMargin = source.startMargin;
            this.endMargin = source.endMargin;
        }

        /**
         * {@inheritDoc}
         */
        public MarginLayoutParams(LayoutParams source) {
            super(source);
        }

        public void setMargins(int left, int top, int right, int bottom) {
            leftMargin = left;
            topMargin = top;
            rightMargin = right;
            bottomMargin = bottom;
        }

        /**
         * Sets the relative margins, in pixels. A call to {@link android.view.View#requestLayout()}
         * @hide
         */
        public void setMarginsRelative(int start, int top, int end, int bottom) {
            startMargin = start;
            topMargin = top;
            endMargin = end;
            bottomMargin = bottom;
        }

        /**
         * Returns the start margin in pixels
         * @hide
         */
        public int getMarginStart() {
            return startMargin;
        }

        /**
         * @hide
         */
        public int getMarginEnd() {
            return endMargin;
        }

        /**
         * @hide
         */
        public boolean isMarginRelative() {
            return (startMargin != DEFAULT_RELATIVE) || (endMargin != DEFAULT_RELATIVE);
        }

        /**
  
         * @hide
         */
        @Override
        public void onResolveLayoutDirection(int layoutDirection) {
            switch(layoutDirection) {
                case View.LAYOUT_DIRECTION_RTL:
                    leftMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : leftMargin;
                    rightMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : rightMargin;
                    break;
                case View.LAYOUT_DIRECTION_LTR:
                default:
                    leftMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : leftMargin;
                    rightMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : rightMargin;
                    break;
            }
        }

        /**
         * @hide
         */
        @Override
        public void onDebugDraw(View view, Canvas canvas) {
            drawRect(canvas,
                    view.getLeft() - leftMargin,
                    view.getTop() - topMargin,
                    view.getRight() + rightMargin,
                    view.getBottom() + bottomMargin, Color.MAGENTA);
        }
    }</span>

     ③measureChildWithMargins():该函数与measureChild的唯一区别就是measure的时候会考虑把margin 以及padding作为子视图的一部分。源码如下!:

<span style="font-size:14px;">    protected void measureChildWithMargins(View child,
            int parentWidthMeasureSpec, int widthUsed,
            int parentHeightMeasureSpec, int heightUsed) {
        final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();

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

         

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值