[TOC]
文章参考:https://www.jianshu.com/p/95afeb7c8335
概述
绘制View
视图。类似measure
过程、layout
过程,draw
过程根据View的类型分为2种情况:
单一View的draw过程
下面我将一个个方法进行详细分析:draw
过程的入口 = draw()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
public void draw(Canvas canvas) {
... int saveCount;
if (!dirtyOpaque) { drawBackground(canvas); }
final int viewFlags = mViewFlags; if (!verticalEdges && !horizontalEdges) {
if (!dirtyOpaque) onDraw(canvas);
dispatchDraw(canvas);
onDrawScrollBars(canvas);
return; } ... }
private void drawBackground(Canvas canvas) { final Drawable background = mBackground; if (background == null) { return; } setBackgroundBounds();
...
final int scrollX = mScrollX; final int scrollY = mScrollY; if ((scrollX | scrollY) == 0) { background.draw(canvas); } else { canvas.translate(scrollX, scrollY);
background.draw(canvas); canvas.translate(-scrollX, -scrollY); } }
protected void onDraw(Canvas canvas) { ...
}
protected void dispatchDraw(Canvas canvas) {
...
}
public void onDrawForeground(Canvas canvas) { onDrawScrollIndicators(canvas); 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); } }
|
至此,单一View
的draw
过程已分析完毕。
ViewGroup的draw过程
- 应用场景
利用现有的组件根据特定的布局方式来组成新的组件
- 具体使用
继承自ViewGroup
或 各种Layout
;含有子 View
自上而下、一层层地传递下去,直到完成整个View
树的draw
过程
具体流程
下面我将对每个步骤和方法进行详细分析:draw
过程的入口 = draw()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
public void draw(Canvas canvas) {
... int saveCount;
if (!dirtyOpaque) { drawBackground(canvas); }
final int viewFlags = mViewFlags; if (!verticalEdges && !horizontalEdges) {
if (!dirtyOpaque) onDraw(canvas);
dispatchDraw(canvas); onDrawScrollBars(canvas);
return; } ... }
|
由于 步骤2:drawBackground()
、步骤3:onDraw()
、步骤5:onDrawForeground()
,与单一View的draw过程类似,此处不作过多描述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
protected void dispatchDraw(Canvas canvas) { ......
final int childrenCount = mChildrenCount; ......
for (int i = 0; i < childrenCount; i++) { ...... if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE || transientChild.getAnimation() != null) { more |= drawChild(canvas, transientChild, drawingTime); } .... } }
protected boolean drawChild(Canvas canvas, View child, long drawingTime) { return child.draw(canvas, this, drawingTime); }
|
至此,ViewGroup
的draw
过程已分析完毕。
View.setWillNotDraw()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
public void setWillNotDraw(boolean willNotDraw) {
setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
}
|
归纳总结
ViewGroup
的draw
过程如下: