preface
In the performTraversals method, after layout is executed, the next step is to draw.
Source code analysis
Analysis of the entrance
In FormTraversals there is a method that is the entry point for analyzing the rendering process:
// Perform the draw operation
performDraw();
Copy the code
private void performDraw(a) {
// Core method to draw operations
// Of course, this method is not the beginning of our analysis of the drawing
// Skip methods and procedures that are not related to this article for now --> Analysis: Start drawing
boolean canUseAsync = draw(fullRedrawNeeded);
}
Copy the code
Analysis: Start drawing
public void draw(Canvas canvas) {
final int privateFlags = mPrivateFlags;
mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
// Draw the process:
// 1. Draw the background
// 2. Draw content
// 3. Draw the child control
// 4. Draw foreground
// Draw the background
intsaveCount; drawBackground(canvas); ...boolean drawTop = false;
boolean drawBottom = false;
boolean drawLeft = false;
boolean drawRight = false;
float topFadeStrength = 0.0 f;
float bottomFadeStrength = 0.0 f;
float leftFadeStrength = 0.0 f;
float rightFadeStrength = 0.0 f;
int paddingLeft = mPaddingLeft;
final boolean offsetRequired = isPaddingOffsetRequired();
if (offsetRequired) {
paddingLeft += getLeftPaddingOffset();
}
int left = mScrollX + paddingLeft;
int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
int top = mScrollY + getFadeTop(offsetRequired);
int bottom = top + getFadeHeight(offsetRequired);
if (offsetRequired) {
right += getRightPaddingOffset();
bottom += getBottomPaddingOffset();
}
final ScrollabilityCache scrollabilityCache = mScrollCache;
final float fadeHeight = scrollabilityCache.fadingEdgeLength;
int length = (int) fadeHeight;
if (verticalEdges && (top + length > bottom - length)) {
length = (bottom - top) / 2;
}
if (horizontalEdges && (left + length > right - length)) {
length = (right - left) / 2;
}
if (verticalEdges) {
topFadeStrength = Math.max(0.0 f, Math.min(1.0 f, getTopFadingEdgeStrength()));
drawTop = topFadeStrength * fadeHeight > 1.0 f;
bottomFadeStrength = Math.max(0.0 f, Math.min(1.0 f, getBottomFadingEdgeStrength()));
drawBottom = bottomFadeStrength * fadeHeight > 1.0 f;
}
if (horizontalEdges) {
leftFadeStrength = Math.max(0.0 f, Math.min(1.0 f, getLeftFadingEdgeStrength()));
drawLeft = leftFadeStrength * fadeHeight > 1.0 f;
rightFadeStrength = Math.max(0.0 f, Math.min(1.0 f, getRightFadingEdgeStrength()));
drawRight = rightFadeStrength * fadeHeight > 1.0 f;
}
saveCount = canvas.getSaveCount();
int topSaveCount = -1;
int bottomSaveCount = -1;
int leftSaveCount = -1;
int rightSaveCount = -1;
int solidColor = getSolidColor();
if (solidColor == 0) {
if (drawTop) {
topSaveCount = canvas.saveUnclippedLayer(left, top, right, top + length);
}
if (drawBottom) {
bottomSaveCount = canvas.saveUnclippedLayer(left, bottom - length, right, bottom);
}
if (drawLeft) {
leftSaveCount = canvas.saveUnclippedLayer(left, top, left + length, bottom);
}
if(drawRight) { rightSaveCount = canvas.saveUnclippedLayer(right - length, top, right, bottom); }}else {
scrollabilityCache.setFadeColor(solidColor);
}
// Draw the content
onDraw(canvas);
// Draws a child control
dispatchDraw(canvas);
final Paint p = scrollabilityCache.paint;
final Matrix matrix = scrollabilityCache.matrix;
final Shader fade = scrollabilityCache.shader;
if (drawRight) {
matrix.setScale(1, fadeHeight * rightFadeStrength);
matrix.postRotate(90);
matrix.postTranslate(right, top);
fade.setLocalMatrix(matrix);
p.setShader(fade);
if (solidColor == 0) {
canvas.restoreUnclippedLayer(rightSaveCount, p);
} else{ canvas.drawRect(right - length, top, right, bottom, p); }}if (drawLeft) {
matrix.setScale(1, fadeHeight * leftFadeStrength);
matrix.postRotate(-90);
matrix.postTranslate(left, top);
fade.setLocalMatrix(matrix);
p.setShader(fade);
if (solidColor == 0) {
canvas.restoreUnclippedLayer(leftSaveCount, p);
} else{ canvas.drawRect(left, top, left + length, bottom, p); }}if (drawBottom) {
matrix.setScale(1, fadeHeight * bottomFadeStrength);
matrix.postRotate(180);
matrix.postTranslate(left, bottom);
fade.setLocalMatrix(matrix);
p.setShader(fade);
if (solidColor == 0) {
canvas.restoreUnclippedLayer(bottomSaveCount, p);
} else{ canvas.drawRect(left, bottom - length, right, bottom, p); }}if (drawTop) {
matrix.setScale(1, fadeHeight * topFadeStrength);
matrix.postTranslate(left, top);
fade.setLocalMatrix(matrix);
p.setShader(fade);
if (solidColor == 0) {
canvas.restoreUnclippedLayer(topSaveCount, p);
} else {
canvas.drawRect(left, top, right, top + length, p);
}
}
canvas.restoreToCount(saveCount);
drawAutofilledHighlight(canvas);
if(mOverlay ! =null && !mOverlay.isEmpty()) {
mOverlay.getOverlayView().dispatchDraw(canvas);
}
// Draw foreground
onDrawForeground(canvas);
if(debugDraw()) { debugDrawFocus(canvas); }}Copy the code
Draw content for the time being so much, in the source code there are a lot of content unrelated to draw process is not expanded to say, in general, after the draw process control will be displayed in front of us.
conclusion
View drawing process:
- drawBackground(canvas);
- onDraw(canvas);
- dispatchDraw(canvas);
- onDrawForeground(canvas);
This is simply to start from the lowest canvas: background -> control itself -> child controls (same order) -> foreground
In daily development, the onDraw method is overridden to draw custom views:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Get the View canvas
}
Copy the code
We’ll cover drawing in more detail later in the tutorial.