View的绘制流程分析之四 -- draw
来源:互联网 发布:中国的穆斯林问题 知乎 编辑:程序博客网 时间:2024/06/13 20:08
转载请注明出处:http://blog.csdn.net/crazy1235/article/details/72633392
draw - 绘制
将View绘制在屏幕上!
在ViewRootImpl.java的函数performTravesals() 方法体最后,就开始了绘制流程!
if (!cancelDraw && !newSurface) { if (mPendingTransitions != null && mPendingTransitions.size() > 0) { for (int i = 0; i < mPendingTransitions.size(); ++i) { mPendingTransitions.get(i).startChangingAnimations(); } mPendingTransitions.clear(); } performDraw();
performDraw()
private void performDraw() { // ... // 第一次绘制mFullRedrawNeeded = true, 表示全部绘制 final boolean fullRedrawNeeded = mFullRedrawNeeded; mFullRedrawNeeded = false; try { draw(fullRedrawNeeded); // draw(true) } finally { mIsDrawing = false; Trace.traceEnd(Trace.TRACE_TAG_VIEW); } // ... }
方法内部调用 draw()
private void draw(boolean fullRedrawNeeded) { // ... if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) { // ... } else { // ... if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) { return; } } } // ... }
drawSoftware()
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff, boolean scalingRequired, Rect dirty) { // ... // 这里创建了canvas对象! canvas = mSurface.lockCanvas(dirty); try { // ... try { canvas.translate(-xoff, -yoff); if (mTranslator != null) { mTranslator.translateCanvas(canvas); } canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0); attachInfo.mSetIgnoreDirtyState = false; // 开始绘制 mView.draw(canvas); drawAccessibilityFocusedDrawableIfNeeded(canvas); } finally { // ... } } finally { // ... } return true; }
这里才针对DecorView开始真正的绘制流程!
不管是ViewGroup还是View都是调用 View.draw(canvas)
View.java中draw(Canvas canvas)有这样一段注释:
/* * Draw traversal performs several drawing steps which must be executed * in the appropriate order: * * 1. Draw the background * 2. If necessary, save the canvas' layers to prepare for fading * 3. Draw view's content * 4. Draw children * 5. If necessary, draw the fading edges and restore layers * 6. Draw decorations (scrollbars for instance) */
这段注释说明了draw() 绘制的流程步骤!
绘制背景
绘制自己的内容
绘制子view
绘制装饰
public void draw(Canvas canvas) { 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; /* * Draw traversal performs several drawing steps which must be executed * in the appropriate order: * * 1. Draw the background * 2. If necessary, save the canvas' layers to prepare for fading * 3. Draw view's content * 4. Draw children * 5. If necessary, draw the fading edges and restore layers * 6. Draw decorations (scrollbars for instance) */ // 第一步 // 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) { // 第三步,绘制自己的内容 if (!dirtyOpaque) onDraw(canvas); // 第四步,绘制子view dispatchDraw(canvas); // Overlay is part of the content and draws beneath Foreground if (mOverlay != null && !mOverlay.isEmpty()) { mOverlay.getOverlayView().dispatchDraw(canvas); } // 第六步,绘制装饰 // Step 6, draw decorations (foreground, scrollbars) onDrawForeground(canvas); // we're done... return; } // ... }
drawBackground(Canvas canvas)
/** * Draws the background onto the specified canvas. * * @param canvas Canvas on which to draw the background */ private void drawBackground(Canvas canvas) { final Drawable background = mBackground; if (background == null) { // 无背景直接return return; } setBackgroundBounds(); // Attempt to use a display list if requested. if (canvas.isHardwareAccelerated() && mAttachInfo != null && mAttachInfo.mHardwareRenderer != null) { mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode); final RenderNode renderNode = mBackgroundRenderNode; if (renderNode != null && renderNode.isValid()) { setBackgroundRenderNodeProperties(renderNode); ((DisplayListCanvas) canvas).drawRenderNode(renderNode); return; } } final int scrollX = mScrollX; final int scrollY = mScrollY; if ((scrollX | scrollY) == 0) { background.draw(canvas); // 绘制背景 } else { // 如果有scrollX,scrollY值,则需要先移动画布,在进行绘制,最后画布反向移动还原 canvas.translate(scrollX, scrollY); background.draw(canvas); // 绘制背景 canvas.translate(-scrollX, -scrollY); } }
onDraw(Canvas canvas)
protected void onDraw(Canvas canvas) { }
onDraw()函数在View中是一个空实现!不同的View实现类有不同的实现!
dispatchDraw(Canvas canvas)
ViewGroup.dispatchDraw()
@Override protected void dispatchDraw(Canvas canvas) { boolean usingRenderNodeProperties = canvas.isRecordingFor(mRenderNode); final int childrenCount = mChildrenCount; final View[] children = mChildren; int flags = mGroupFlags; // ... // Only use the preordered list if not HW accelerated, since the HW pipeline will do the // draw reordering internally final ArrayList<View> preorderedList = usingRenderNodeProperties ? null : buildOrderedChildList(); final boolean customOrder = preorderedList == null && isChildrenDrawingOrderEnabled(); for (int i = 0; i < childrenCount; i++) { // 遍历子View 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); // 调用drawChild() } transientIndex++; if (transientIndex >= transientCount) { transientIndex = -1; } } // ... } 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; } } // ... }
方法内部遍历子view,调用drawChild()来绘制子view
protected boolean drawChild(Canvas canvas, View child, long drawingTime) { return child.draw(canvas, this, drawingTime); }
这里又调用View的draw()方法。上面已经分析过!
onDrawForeground(Canvas canvas)
public void onDrawForeground(Canvas canvas) { onDrawScrollIndicators(canvas); onDrawScrollBars(canvas); final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null; if (foreground != null) { // forground不为空才绘制 if (mForegroundInfo.mBoundsChanged) { mForegroundInfo.mBoundsChanged = false; final Rect selfBounds = mForegroundInfo.mSelfBounds; final Rect overlayBounds = mForegroundInfo.mOverlayBounds; if (mForegroundInfo.mInsidePadding) { // 设置bound selfBounds.set(0, 0, getWidth(), getHeight()); } else { selfBounds.set(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()); } final int ld = getLayoutDirection(); Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(), foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld); foreground.setBounds(overlayBounds); } foreground.draw(canvas); // 开始绘制 } }
OVER!
阅读全文
0 0
- View的绘制流程分析之四 -- draw
- view绘制流程之layout和draw
- 【Android】View绘制过程分析之draw
- Android界面生成流程:View的绘制(Draw)
- View绘制之draw过程
- 深入理解 Android 之 View 的绘制流程(四)_Draw
- Android View 绘制流程(Draw) 完全解析
- Android View 绘制流程(Draw) 完全解析
- View框架之draw()流程
- View的绘制流程分析之二 -- measure
- View的绘制流程分析之三 -- layout
- 【Android系列】View的绘制之draw过程
- View的Draw方法流程
- View的绘制流程(三)--------view的layout和draw过程
- 深入了解View(三)—— draw绘制流程分析
- 【Android View绘制之旅】Draw过程
- ViewRootImpl类分析View绘制的流程
- View的绘制流程分析之一
- AOJ.872 背菜谱
- Cable master POJ
- View的绘制流程分析之三 -- layout
- 计算机网络漫谈之UDP和TCP
- Spanning trees in a secure lock pattern UVALive
- View的绘制流程分析之四 -- draw
- 模板类与类模板、函数模板与模板函数等的区别 (四)
- Android程序编译时报错:duplicate entry: android/support/v4/content/res/TypedArrayUtils.class
- ubuntu下从源码编译比特币(Bitcoin)客户端
- IO流
- python远程调用rpc模块xmlrpclib
- 使用Docker搭建hadoop集群
- Android Studio自用配置
- spring和mybatis的整合简介