//----------------------------------流程1.2  绘制 ----------------------------------

 

 

 private void performDraw() {        ...        try {            draw(fullRedrawNeeded);        ...    }    private void draw(boolean fullRedrawNeeded) {        // ViewRootImpl 中 final 的那个 surface        Surface surface = mSurface;        ...// 在 软件上开始 draw        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) {        // Draw with software renderer.        final Canvas canvas;        try {            final int left = dirty.left;            final int top = dirty.top;            final int right = dirty.right;            final int bottom = dirty.bottom;            //1. --- lockCanvas Surface 中获取 canvas ---            canvas = mSurface.lockCanvas(dirty);            // The dirty rectangle can be modified by Surface.lockCanvas()            // noinspection ConstantConditions            if (left != dirty.left || top != dirty.top || right != dirty.right                    || bottom != dirty.bottom) {                attachInfo.mIgnoreDirtyState = true;            }            //2. --- 开始设置 canvas  ----            canvas.setDensity(mDensity);        ...        try {            if (DEBUG_ORIENTATION || DEBUG_DRAW) {                Log.v(TAG, "Surface " + surface + " drawing to bitmap w="                        + canvas.getWidth() + ", h=" + canvas.getHeight());                //canvas.drawARGB(255, 255, 0, 0);            }            // If this bitmap's format includes an alpha channel, we            // need to clear it before drawing so that the child will            // properly re-composite its drawing on a transparent            // background. This automatically respects the clip/dirty region            // or            // If we are applying an offset, we need to clear the area            // where the offset doesn't appear to avoid having garbage            // left in the blank areas.            if (!canvas.isOpaque() || yoff != 0 || xoff != 0) {                canvas.drawColor(0, PorterDuff.Mode.CLEAR);            }            dirty.setEmpty();            mIsAnimating = false;            attachInfo.mDrawingTime = SystemClock.uptimeMillis();            mView.mPrivateFlags |= View.PFLAG_DRAWN;            if (DEBUG_DRAW) {                Context cxt = mView.getContext();                Log.i(TAG, "Drawing: package:" + cxt.getPackageName() +                        ", metrics=" + cxt.getResources().getDisplayMetrics() +                        ", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo());            }            try {                canvas.translate(-xoff, -yoff);                if (mTranslator != null) {                    mTranslator.translateCanvas(canvas);                }                canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0);                attachInfo.mSetIgnoreDirtyState = false;//3. ------------- 回调mView(DecorView)的draw方法 ----------------                mView.draw(canvas);            } finally {                if (!attachInfo.mSetIgnoreDirtyState) {                    // Only clear the flag if it was not set during the mView.draw() call                    attachInfo.mIgnoreDirtyState = false;                }            }        } finally {            try {                //4. --------------绘制结束后释放canvas ---------                surface.unlockCanvasAndPost(canvas);            } catch (IllegalArgumentException e) {                Log.e(TAG, "Could not unlock surface", e);                mLayoutRequested = true;    // ask wm for a new surface next time.              ...        }        return true;    }

 DecorView.java

  

 DecorView extends FrameLayout{         @Override     public void draw(Canvas canvas) {        //------------ view ondraw -------------------------        super.draw(canvas);        if (mForeground != null) {            final Drawable foreground = mForeground;            if (mForegroundBoundsChanged) {                mForegroundBoundsChanged = false;                final Rect selfBounds = mSelfBounds;                final Rect overlayBounds = mOverlayBounds;                final int w = mRight-mLeft;                final int h = mBottom-mTop;                if (mForegroundInPadding) {                    selfBounds.set(0, 0, w, h);                } else {                    selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);                }                final int layoutDirection = getLayoutDirection();                Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds,                        layoutDirection);                foreground.setBounds(overlayBounds);            }            foreground.draw(canvas);        }      }    }        public void draw(ViewGroup root, Canvas c, View content) {        if (!hasFallback()) {            return;        }        // Draw the fallback in the padding.        ...            left = Math.min(left, child.getLeft());            top = Math.min(top, child.getTop());            right = Math.max(right, child.getRight());            bottom = Math.max(bottom, child.getBottom());        }       ....    }    public void draw(Canvas canvas) {        ...        // Step 1, draw the background, if needed        int saveCount;        if (!dirtyOpaque) {            drawBackground(canvas);        }        // 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) {            // Step 3, draw the content            if (!dirtyOpaque) onDraw(canvas); ------调用到 DecorView onDraw            // Step 4, draw the children            dispatchDraw(canvas);   ------ 调用到 ViewGroup  dispatchDraw            // Step 6, draw decorations (scrollbars)            onDrawScrollBars(canvas);            if (mOverlay != null && !mOverlay.isEmpty()) {                mOverlay.getOverlayView().dispatchDraw(canvas);            }            return;        }        ...

ViewGroup.java

 /**     * {@inheritDoc}     */    @Override    protected void dispatchDraw(Canvas canvas) {        boolean usingRenderNodeProperties = canvas.isRecordingFor(mRenderNode);        final int childrenCount = mChildrenCount;        final View[] children = mChildren;        int flags = mGroupFlags;        if ((flags & FLAG_RUN_ANIMATION) != 0 && canAnimate()) {            final boolean cache = (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE;            final boolean buildCache = !isHardwareAccelerated();            for (int i = 0; i < childrenCount; i++) {                final View child = children[i];                if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {                    final LayoutParams params = child.getLayoutParams();                    attachLayoutAnimationParameters(child, params, i, childrenCount);                    bindLayoutAnimation(child);                    if (cache) {                        child.setDrawingCacheEnabled(true);                        if (buildCache) {                            child.buildDrawingCache(true);                        }                    }                }            }            final LayoutAnimationController controller = mLayoutAnimationController;            if (controller.willOverlap()) {                mGroupFlags |= FLAG_OPTIMIZE_INVALIDATE;            }            controller.start();            mGroupFlags &= ~FLAG_RUN_ANIMATION;            mGroupFlags &= ~FLAG_ANIMATION_DONE;            if (cache) {                mGroupFlags |= FLAG_CHILDREN_DRAWN_WITH_CACHE;            }            if (mAnimationListener != null) {                mAnimationListener.onAnimationStart(controller.getAnimation());            }        }        int clipSaveCount = 0;        final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;        if (clipToPadding) {            clipSaveCount = canvas.save();            canvas.clipRect(mScrollX + mPaddingLeft, mScrollY + mPaddingTop,                    mScrollX + mRight - mLeft - mPaddingRight,                    mScrollY + mBottom - mTop - mPaddingBottom);        }        // We will draw our child's animation, let's reset the flag        mPrivateFlags &= ~PFLAG_DRAW_ANIMATION;        mGroupFlags &= ~FLAG_INVALIDATE_REQUIRED;        boolean more = false;        final long drawingTime = getDrawingTime();        if (usingRenderNodeProperties) canvas.insertReorderBarrier();        // Only use the preordered list if not HW accelerated, since the HW pipeline will do the        // draw reordering internally        final ArrayList preorderedList = usingRenderNodeProperties                ? null : buildOrderedChildList();        final boolean customOrder = preorderedList == null                && isChildrenDrawingOrderEnabled();        for (int i = 0; i < childrenCount; i++) {            int childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;            final View child = (preorderedList == null)                    ? children[childIndex] : preorderedList.get(childIndex);            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {                more |= drawChild(canvas, child, drawingTime);            }        }        if (preorderedList != null) preorderedList.clear();        // Draw any disappearing views that have animations        if (mDisappearingChildren != null) {            final ArrayList 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);            }        }        if (usingRenderNodeProperties) canvas.insertInorderBarrier();        if (debugDraw()) {            onDebugDraw(canvas);        }        if (clipToPadding) {            canvas.restoreToCount(clipSaveCount);        }        // mGroupFlags might have been updated by drawChild()        flags = mGroupFlags;        if ((flags & FLAG_INVALIDATE_REQUIRED) == FLAG_INVALIDATE_REQUIRED) {            invalidate(true);        }        if ((flags & FLAG_ANIMATION_DONE) == 0 && (flags & FLAG_NOTIFY_ANIMATION_LISTENER) == 0 &&                mLayoutAnimationController.isDone() && !more) {            // We want to erase the drawing cache and notify the listener after the            // next frame is drawn because one extra invalidate() is caused by            // drawChild() after the animation is over            mGroupFlags |= FLAG_NOTIFY_ANIMATION_LISTENER;            final Runnable end = new Runnable() {               public void run() {                   notifyAnimationListener();               }            };            post(end);        }    }    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {        return child.draw(canvas, this, drawingTime);    }

 

更多相关文章

  1. unity和Android交互(内容部分为转载)
  2. android 小钢琴
  3. Android(安卓)通过接口的方式去调用服务里面的方法
  4. Android(安卓)MedaiPlayer类的简单介绍
  5. Android(安卓)Thread/Runnable/Handler用法
  6. Android(安卓)根据包名杀死应用后台进程
  7. 新建android opengl工程
  8. android 调用camera相关操作
  9. Android(安卓)Application Fundamentals——Android应用程序基础

随机推荐

  1. android 开机动画的制作
  2. Android(安卓)Weekly Notes Issue #239
  3. android如何让service不被杀死-提高进程
  4. Android之拨打接挂电话功能实现
  5. Android自定义View
  6. ContentProvider初步
  7. 在android中解析json
  8. 深拷贝和浅拷贝
  9. android之AudioManager详解_什么是AudioM
  10. Android控制ScrollView滚动