Viewgroup绘制流程

作者: 奔跑吧李博 | 来源:发表于2019-03-23 11:00 被阅读15次
    ViewGroup的测量、设置位置大小,绘制流程图:
    ViewGroup也是继承View,实现了ViewParent和ViewManager接口
    public abstract class ViewGroup extends View implements ViewParent, ViewManager 
    
    1.onMeasure()方法流程

    Viewgroup调用measure回调onMeasure()方法,通过widthMeasureSpec和heightMeasureSpec获取测量模式和宽高尺寸,如果是测量模式是Exactly,就能直接设置自己的宽高。如果测量模式是wrapcontent,就需要遍历自己所有的子view,就需要先让子childView自己去测量它们的宽高和边距,在累加计算自己的宽高,通过setMeasureDimension()设置最终的宽高。

    计算所有ChildView的宽度和高度 然后根据ChildView的计算结果,设置自己的宽和高
        @Override  
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
            /** 
             * 获得此ViewGroup上级容器为其推荐的宽和高,以及计算模式 
             */  
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
            int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);  
            int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);  
      
      
            // 计算出所有的childView的宽和高,调用后,它所有的childView的宽和高的值就被确定,也即getMeasuredWidth()有值了。  
            measureChildren(widthMeasureSpec, heightMeasureSpec);  
            /** 
             * 记录如果是wrap_content是设置的宽和高 
             */  
            int width = 0;  
            int height = 0;  
      
            int cCount = getChildCount();  
      
            int cWidth = 0;  
            int cHeight = 0;  
            MarginLayoutParams cParams = null;  
      
            // 用于计算左边两个childView的高度  
            int lHeight = 0;  
            // 用于计算右边两个childView的高度,最终高度取二者之间大值  
            int rHeight = 0;  
      
            // 用于计算上边两个childView的宽度  
            int tWidth = 0;  
            // 用于计算下面两个childiew的宽度,最终宽度取二者之间大值  
            int bWidth = 0;  
      
            /** 
             * 根据childView计算的出的宽和高,以及设置的margin计算容器的宽和高,主要用于容器是warp_content时 
             */  
            for (int i = 0; i < cCount; i++)  
            {  
                View childView = getChildAt(i);  
                cWidth = childView.getMeasuredWidth();  
                cHeight = childView.getMeasuredHeight();  
                cParams = (MarginLayoutParams) childView.getLayoutParams();  
      
                // 上面两个childView  
                if (i == 0 || i == 1)  
                {  
                    tWidth += cWidth + cParams.leftMargin + cParams.rightMargin;  
                }  
      
                if (i == 2 || i == 3)  
                {  
                    bWidth += cWidth + cParams.leftMargin + cParams.rightMargin;  
                }  
      
                if (i == 0 || i == 2)  
                {  
                    lHeight += cHeight + cParams.topMargin + cParams.bottomMargin;  
                }  
      
                if (i == 1 || i == 3)  
                {  
                    rHeight += cHeight + cParams.topMargin + cParams.bottomMargin;  
                }  
      
            }  
              
            width = Math.max(tWidth, bWidth);  
            height = Math.max(lHeight, rHeight);  
      
            /** 
             * 如果是wrap_content设置为我们计算的值 
             * 否则:直接设置为父容器计算的值 
             */  
            setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? sizeWidth  
                    : width, (heightMode == MeasureSpec.EXACTLY) ? sizeHeight  
                    : height);  
        }  
    
    2.onLayout()方法流程

    onLayout方法是ViewGroup对其所有的子childView进行定位摆放。通过遍历子view,获取子view的宽高,再LayoutParams来获取边距,调用每个子view的layout()方法,填入与父view的上下左右边距,就设置了每个子view的位置和大小。

    3.viewgroup的绘制流程:

    1.绘制背景
    2.调用ondraw()绘制自身
    3.调用child.ondraw()绘制各个子view
    4.绘制滚动条

    那么问题又来了,怎么计算一个viewgroup的嵌套层级?

    因为viewGroup实现了ViewParent,使用递归的方式计算,只要还有父view,就继续累加记录层数。

        int count = 0;
        public void cal(ViewParent view){
            if(view.getParent() == null){
                Log.i("tag","结束");
            }
            count++;
            ViewParent parentView = view.getParent();
            Log.i("tag","当前层数" + count);
            cal(parentView);
        }
    

    相关文章

      网友评论

        本文标题:Viewgroup绘制流程

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