View绘制流程

流程图如下:


看高清图请下载

对于开头的方法是调用了ViewRootImpl方法里的,之所以调这个方法也可通过高清图进行分析这里直接从performTraversals方法进行分析

    private void performTraversals() {
        // cache mView since it is used so much below...
        ......
            if (!mStopped || mReportNextDraw) {
               .....
                    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);

                   .......

                    if (measureAgain) {
                        if (DEBUG_LAYOUT) Log.v(mTag,
                                "And hey let's measure once more: width=" + width
                                + " height=" + height);
                        performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
                    }

                    layoutRequested = true;
                }
            }
            .......

        
            performLayout(lp, mWidth, mHeight);

            ......

            performDraw();
            ......
    }

    private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
        try {
            mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
    }
通过分析mView是DecorView,它实现继承了VIew类因此查找measure的方法:

	  public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
	             ......
                        onMeasure(widthMeasureSpec, heightMeasureSpec);
               ......
    }

这个onMeasure实现在

   @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        ......

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        ......

        if (measure) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
查看方法可知调用了父类的onMeasure方法,DecorView也继承FrameLayout类

 

  @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
	     ......

        count = mMatchParentChildren.size();
        if (count > 1) {
            for (int i = 0; i < count; i++) {
                final View child = mMatchParentChildren.get(i);
                ......
                child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
            }
        }
    }
通过遍历的方式将子控件的大小计算出来,如果子控件还是VIewGroup将进行递归,也就是说计算控件的大小是通过递归遍历的方式解决的

下面是Layout方法

   private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,
            int desiredWindowHeight) {
            ......
            host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());

            ......
            if (numViewsRequestingLayout > 0) {
              ......
                    host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());

			  ......

            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
        mInLayout = false;
    }
其中host就是DecorView,调用了父类View的方法
  public void layout(int l, int t, int r, int b) {
        ......

        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
            onLayout(changed, l, t, r, b);
            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;

            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnLayoutChangeListeners != null) {
                ArrayList<OnLayoutChangeListener> listenersCopy =
                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
                int numListeners = listenersCopy.size();
                for (int i = 0; i < numListeners; ++i) {
                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
                }
            }
        }
		......
    }
这样会调用Decor的onlayout方法如下:

  @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        ......
    }
调用了父类的onlayout方法:

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        layoutChildren(left, top, right, bottom, false /* no force left gravity */);
    }

 void layoutChildren(int left, int top, int right, int bottom, boolean forceLeftGravity) {


        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                ......

                child.layout(childLeft, childTop, childLeft + width, childTop + height);
            }
        }
    }
通过上面方法可知layout方法也是通过递归遍历的方式来设置view的位置的,这个和计算view的大小的逻辑是一样的

接下来是view的draw

  private void performDraw() {
        ......
        try {
            draw(fullRedrawNeeded);
        } finally {
            mIsDrawing = false;
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }

        ......
    }
  private void draw(boolean fullRedrawNeeded) {
        ......

                if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
                    return;
                }
            }
        }

        if (animating) {
            mFullRedrawNeeded = true;
            scheduleTraversals();
        }
    }
  private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
            boolean scalingRequired, Rect dirty) {

        ......
            try {
                canvas.translate(-xoff, -yoff);
                if (mTranslator != null) {
                    mTranslator.translateCanvas(canvas);
                }
                canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0);
                attachInfo.mSetIgnoreDirtyState = false;

                mView.draw(canvas);
				......
    }
其中的mView是DecorView控件,调用了View中的方法
  public void draw(Canvas canvas) {
        ......

        // Step 3, draw the content//绘制自己的内容
        if (!dirtyOpaque) onDraw(canvas);

        // Step 4, draw the children
        dispatchDraw(canvas);//绘制自己的子控件

        ......
    }
 @Override//调用的是ViewGroup中的
    protected void dispatchDraw(Canvas canvas) {
       .....
        for (int i = 0; i < childrenCount; i++) {
            while (transientIndex >= 0 && mTransientIndices.get(transientIndex) == i) {
                final View transientChild = mTransientViews.get(transientIndex);
                if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
                        transientChild.getAnimation() != null) {
                    more |= drawChild(canvas, transientChild, drawingTime);
                }
                transientIndex++;
                if (transientIndex >= transientCount) {
                    transientIndex = -1;
                }
            }

            final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);
            final View child = getAndVerifyPreorderedView(preorderedList, children, childIndex);
            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {
                more |= drawChild(canvas, child, drawingTime);
            }
        }
        while (transientIndex >= 0) {
            // there may be additional transient views after the normal views
            final View transientChild = mTransientViews.get(transientIndex);
            if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||
                    transientChild.getAnimation() != null) {
                more |= drawChild(canvas, transientChild, drawingTime);
            }
            transientIndex++;
            if (transientIndex >= transientCount) {
                break;
            }
        }
        if (preorderedList != null) preorderedList.clear();

        // Draw any disappearing views that have animations
        if (mDisappearingChildren != null) {
            final ArrayList<View> disappearingChildren = mDisappearingChildren;
            final int disappearingCount = disappearingChildren.size() - 1;
            // Go backwards -- we may delete as animations finish
            for (int i = disappearingCount; i >= 0; i--) {
                final View child = disappearingChildren.get(i);
                more |= drawChild(canvas, child, drawingTime);
            }
        }
		......
    }
通过上面最终调用drawChild方法来进行绘制子控件
  protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        return child.draw(canvas, this, drawingTime);
    }
draw这步也是通过递归遍历的方式进行操作的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值