View体系8:draw和onDraw

一旦ViewRootImpl成功lock到Canvas,他就可以通过ViewTree的根元素逐步把Canvas往下传输

TU 11-26
TU 11-27

1.1 View类中的UI元素

  • background:背景
  • content:内容区域,真正的画面,该区域和外边框有个距离叫padding
  • decoration:主要指scrollbar
  • fading:fading特效

1.2 draw

public void draw(Canvas canvas) {
    if (mClipBounds != null) {
        canvas.clipRect(mClipBounds);
    }
    final int privateFlags = mPrivateFlags;
    final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
            (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
    mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;

    // Step 1, 如有需要,绘制背景
    int saveCount;

    if (!dirtyOpaque) { 
    }

    // skip step 2 & 5 if possible (common case)
    final int viewFlags = mViewFlags;
    boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
    boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
    if (!verticalEdges && !horizontalEdges) {//情况1,
        // Step 3, 绘制内容
        if (!dirtyOpaque) onDraw(canvas);

        // Step 4, 绘制子对象
        dispatchDraw(canvas);

        // Step 6,绘制decoration
        onDrawScrollBars(canvas);

        if (mOverlay != null && !mOverlay.isEmpty()) {
            mOverlay.getOverlayView().dispatchDraw(canvas);
        }

        // 返回
        return;
    } 
    //情况2 ,如果程序走到这里,说明我们需要完整执行step2-step6  
    // Step 2, save the canvas' layers  
    // Step 3, draw the content
    if (!dirtyOpaque) onDraw(canvas); 
    // Step 4, draw the children
    dispatchDraw(canvas); 
    // Step 5, draw the fade effect and restore layers 
    // Step 6, draw decorations (scrollbars)
    onDrawScrollBars(canvas);

} 

1.2.1

TU 11-29
TU 11-30

  • 当一个View对象经过ViewRootImpl的统一遍历之后,它会有固定的大小和位置
  • View应该由一个初始界面
  • 什么情况下惠东
  • View经过判断发现必须更新画面后,它会首先计算出需要重绘的dirty区域,然后沿着viewTree不断向上发起界面刷新请求,最终由ViewRootImpl来主导整个过程。

1.2.2

TU11-31
TU 11-32
当draw函数由树的根节点逐步往下递归调用时,是不是所有的树叶节点都会被遍历到呢?答案是:不一定!

对于那些没有任何变化的View对象,我们没有必要浪费资源去进行重绘

1.3 onDraw (ImageView)

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (mDrawable == null) {
        return; // 如果drawable为空直接返回
    }

    if (mDrawableWidth == 0 || mDrawableHeight == 0) {
        return;     //直接返回
    }

    if (mDrawMatrix == null && mPaddingTop == 0 && mPaddingLeft == 0) {
        mDrawable.draw(canvas); //最简单的情况
    } else {
        int saveCount = canvas.getSaveCount();
        canvas.save();//保存场景,稍后还要恢复
        
        if (mCropToPadding) {
            final int scrollX = mScrollX;
            final int scrollY = mScrollY;
            canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop,
                    scrollX + mRight - mLeft - mPaddingRight,
                    scrollY + mBottom - mTop - mPaddingBottom);
        }
        //坐标变化跳过padding部分的绘制
        canvas.translate(mPaddingLeft, mPaddingTop);

        if (mDrawMatrix != null) {
            canvas.concat(mDrawMatrix);
        }
        mDrawable.draw(canvas);
        //恢复canvas
        canvas.restoreToCount(saveCount);
    }
}
 

你可能感兴趣的:(View体系8:draw和onDraw)