//----------------------------------流程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. android中的ListView的使用方法
  2. 【android开发】之【android动态布局方法总结】
  3. android的ndk修改app_platform的方法,亲测绝对可行
  4. H5调android 的方法修改UI无效
  5. Android实现计时以及倒计时的几种方法
  6. Android程序——退出程序的时候杀死所有进程的一个方法
  7. android 串口通信,蓝牙通信等需要输出十六进制数据的方法
  8. Android 下保持屏幕常亮的实现方法

随机推荐

  1. SQL SERVER 与ACCESS、EXCEL的数据转换方
  2. SQLServer 2000 升级到 SQLServer 2008
  3. 只有mdf文件的数据库附加失败的修复方法
  4. sqlserver 锁表语句分享
  5. 某年第一周开始日期实现方法
  6. 在sql Server自定义一个用户定义星期函数
  7. sqlserver 不重复的随机数
  8. SQLServer Execpt和not in 性能区别
  9. SQL优化基础 使用索引(一个小例子)
  10. 一次性压缩Sqlserver2005中所有库日志的