Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android4.2源碼View.draw(Canvas canvas)中canvas分析

Android4.2源碼View.draw(Canvas canvas)中canvas分析

編輯:關於Android編程

ViewGroup.java中繪制從dispatchDraw()開始,這裡的Canvas由ViewRootImpl.java中傳入,此時Canvas是屏幕大小的畫布。

@Override
    protected void dispatchDraw(Canvas canvas) {
...
                    more |= drawChild(canvas, child, drawingTime);
                }

    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
        return child.draw(canvas, this, drawingTime);
    }

drawChild函數只有一句話,指向了View.java的draw(Canvas canvas, ViewGroup parent, long drawingTime)函數。(這個函數不同於draw(Canvas canvas)函數,後者是View繪制過程開始的地方)

    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {

...

        int sx = 0;
        int sy = 0;
        if (!hasDisplayList) {
            computeScroll();
            sx = mScrollX;
            sy = mScrollY;
        }

        final boolean hasNoCache = cache == null || hasDisplayList;
        final boolean offsetForScroll = cache == null && !hasDisplayList &&
                layerType != LAYER_TYPE_HARDWARE;

        int restoreTo = -1;
        if (!useDisplayListProperties || transformToApply != null) {
            restoreTo = canvas.save();
        }
        if (offsetForScroll) {
            canvas.translate(mLeft - sx, mTop - sy);
        } else {
            if (!useDisplayListProperties) {
                canvas.translate(mLeft, mTop);
            }
            if (scalingRequired) {
                if (useDisplayListProperties) {
                    // TODO: Might not need this if we put everything inside the DL
                    restoreTo = canvas.save();
                }
                // mAttachInfo cannot be null, otherwise scalingRequired == false
                final float scale = 1.0f / mAttachInfo.mApplicationScale;
                canvas.scale(scale, scale);
            }
        }

...

        if (!layerRendered) {
                if (!hasDisplayList) {
                    // Fast path for layouts with no backgrounds
                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                        if (DBG_DRAW) {
                            Xlog.d(VIEW_LOG_TAG, "view draw1 : calling dispatchDraw,this = " + this);
                        }
                        dispatchDraw(canvas);
                    } else {
                        if (DBG_DRAW) {
                            Xlog.d(VIEW_LOG_TAG, "view draw1 : calling draw,this = " + this);
                        }
                        draw(canvas);
                    }
                } else {
                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                    ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
...
    }

上面這段代碼,有兩個需要指出的地方,一個就是canvas.translate()函數,這裡表明了ViewRootImpl傳進來的Canvas需要根據子視圖本身的布局大小進行裁減,也就是說屏幕上所有子視圖的canvas都只是一塊裁減後的大小的canvas,當然這也就是為什麼子視圖的canvas的坐標原點不是從屏幕左上角開始,而是它自身大小的左上角開始的原因。

第二個需要指出的是如果ViewGroup的子視圖仍然是ViewGroup,那麼它會回調dispatchDraw(canvas)進行分法,如果子視圖是View,那麼就調用View的draw(canvas)函數進行繪制。



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved