Read The Fucking Source Code

The introduction

Android custom controls involve the process of drawing and distributing views

Android Q — API 29

[Android drawing process]

1. Preview

2. draw

2.1 Differences between a View and a ViewGroup

  • View: View does not perform dispatchDraw (subview drawing).
  • ViewGroup: The ViewGroup performs dispatchDraw (recursive drawing of subviews).

2.2 Summary of Views and ViewGroups

2.2.1 View Draw process

Purple is rewritable

2.2.2 ViewGroup Draw process

Purple is rewritable

2.2.3 Meaning of each process of DRAW

2.3 DRAW distributes from the top down

2.3.1 DecorView distribution

DecorView – distributed draw

2.3.1.1 Let’s look at the performDraw() method in ViewRootImpl.

Private void performDraw() {// Boolean canUseAsync = draw(fullRedrawNeeded); if (usingAsyncReport && ! canUseAsync) { mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(null); usingAsyncReport = false; } } finally { mIsDrawing = false; Trace.traceEnd(Trace.TRACE_TAG_VIEW); } // code omitted...... }Copy the code

2.3.1.2 Let’s look at the draw() method in ViewRootImpl.

private boolean draw(boolean fullRedrawNeeded) { Surface surface = mSurface; // code omitted...... // Draw distribution if (! drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty, surfaceInsets)) { return false; }}} // code omitted...... }Copy the code

2.3.1.3 Let’s look at the drawSoftware() method in ViewRootImpl.

private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff, boolean scalingRequired, Rect dirty, Rect surfaceInsets) {// code omission...... //canvas get canvas = msurface.lockcanvas (dirty); // code omitted...... Draw (canvas); // Draw (canvas); // code omitted...... }Copy the code

2.3.2 ViewGroup distribution

2.3.2.1 Let’s look at the dispatchDraw() method in ViewGroup.

@override protected void dispatchDraw(Canvas Canvas) { for (int i = 0; i < childrenCount; i++) { while (transientIndex >= 0 && mTransientIndices.get(transientIndex) == i) { final View transientChild = mTransientViews.get(transientIndex); if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE || transientChild.getAnimation() ! = null) {/ / traverse the child View rendering more | = drawChild (canvas, transientChild drawingTime); } transientIndex++; if (transientIndex >= transientCount) { transientIndex = -1; }} // code omitted...... }Copy the code

2.3.2.2 Let’s look at the drawChild() method in ViewGroup.

DrawChild (Canvas, View child, long drawingTime) {// drawChild(Canvas, View child, long drawingTime); this, drawingTime); }Copy the code

2.3.3 the View to distribute

2.3.3.1 Let’s look at the draw() method in View.

@callsuper public void draw(Canvas Canvas) {// code omitted...... // Step 1, draw the background, if needed int saveCount; 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 onDraw(canvas); // Step 4, draw the children dispatchDraw(canvas); drawAutofilledHighlight(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); // Step 7, draw the default focus highlight drawDefaultFocusHighlight(canvas); if (debugDraw()) { debugDrawFocus(canvas); } // we're done... return; } // code omitted...... // Step 3, draw the content onDraw(canvas); // Step 4, draw the children dispatchDraw(canvas); // Step 5, draw the fade effect and restore layers final Paint p = scrollabilityCache.paint; final Matrix matrix = scrollabilityCache.matrix; final Shader fade = scrollabilityCache.shader; // code omitted...... drawAutofilledHighlight(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); if (debugDraw()) { debugDrawFocus(canvas); }}Copy the code

2.3.3.2 drawBackground() method in View: drawBackground.

2.3.3.3 Let’s look at the onDraw() method in View.

/** * / TextView * Implement this to do your drawing. * * @param canvas the canvas on which the background will be drawn */ protected void onDraw(Canvas canvas) { }Copy the code

2.3.3.4 Let’s look at the dispatchDraw() method in View.

/** * // called by draw to draw subviews. This may be overridden by derived classes, To gain control before drawing its child object (but after drawing its own view) * Called by draw to draw the child views gain control just before its children are drawn * (but after its own view has been drawn). * @param canvas the canvas on  which to draw the view */ protected void dispatchDraw(Canvas canvas) { }Copy the code

2.3.3.5 drawAutofilledHighlight() method in View: Draw the highlight of the autofill View.

2.3.3.6 ViewOverlay in View: : dispatchDraw () method: when there is coating, paint coating.

2.3.3.7 Let’s look at onDrawForeground() method in View.

Public void onDrawScrollIndicators(Canvas); public void onDrawScrollIndicators(Canvas); // Draw the onDrawScrollBars(canvas); Final Drawable foreground = mForegroundInfo! = null ? mForegroundInfo.mDrawable : null; if (foreground ! = null) { if (mForegroundInfo.mBoundsChanged) { mForegroundInfo.mBoundsChanged = false; final Rect selfBounds = mForegroundInfo.mSelfBounds; final Rect overlayBounds = mForegroundInfo.mOverlayBounds; if (mForegroundInfo.mInsidePadding) { 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); }}Copy the code

2.3.3.8 drawDefaultFocusHighlight method in the View: draw the default focus highlighting.

2.3.3.9 debugDrawFocus method in View: this is the effect of the developer option in the display layout boundary.

2.4 Problem Thinking

Why can’t ViewGroup draw custom content using the onDraw method? If I want to rewrite onDraw to do some drawing in the ViewGroup, how do I see it?

  • The ViewGroup cannot display the drawn content because the default marker bit off executes its drawBackground and onDraw methods. Viewgroups generally manage layout-related matters, and do not handle their own drawing to improve execution efficiency.
  • Call view.setwillNotDraw (false) to set the background for the ViewGroup.

Xiaobian extension links

Android View Module Family Bucket

Recommended Blogs

Custom View Draw process – the most understandable custom View principle series (4) custom View