1. onDraw
onMeasure、onLayout结束后,就到 onDraw,这里就是 真正的绘制
private void performDraw() {
draw(fullRedrawNeeded);
}
private void draw(boolean fullRedrawNeeded) {
if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)) {
return;
}
}
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;
// 创建Canvas对象
canvas = mSurface.lockCanvas(dirty);
// 然后调用 view的 draw
mView.draw(canvas);
return true;
}
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) {
// Step 3, draw the content
if (!dirtyOpaque) onDraw(canvas);
// Step 4, draw the children
dispatchDraw(canvas);
// Step 6, draw decorations (foreground, scrollbars)
onDrawForeground(canvas);
// we're done...
return;
}
// Step 2, save the canvas' layers
int paddingLeft = mPaddingLeft;
// Step 3, draw the content
if (!dirtyOpaque) 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;
// Step 6, draw decorations (foreground, scrollbars)
onDrawForeground(canvas);
}
draw绘制 用了 模板设计模式,重点是第三步
对于第一步: 绘制该view 的背景
if (!dirtyOpaque) {
// Step 1, draw the background, if needed
drawBackground(canvas);
}
private void drawBackground(Canvas canvas) {
// 首先获取 Drawable 对象 - background ,这里的 background 其实就是 在 xml文件中 通过
// android:background 设置的 背景或颜色,也可以在代码中通过
// setBackgroundColor()、setBackgroundResource() 设置背景
final Drawable background = mBackground;
// 调用 drawable 的 draw() 绘制背景
background.draw(canvas);
}
对于第三步: 绘制该view 的内容
绘制内容调用 onDraw,这个onDraw是一个空方法,是因为 每个view的 内容 肯定不同,所以 绘制内容让 子类 实现;
// Step 3, draw the content
if (!dirtyOpaque) onDraw(canvas);
protected void onDraw(Canvas canvas) {
}
对于第四步:绘制当前view的 所有的子view
// Step 4, draw the children
dispatchDraw(canvas);
protected void dispatchDraw(Canvas canvas) {
}
如果当前 view 没有 子view,就不需要绘制, View源码中的 dispatchDraw是空的,而ViewGroup中的 dispatchDraw 有具体的绘制代码;
对于第六步:绘制该view的 滚动条
// Step 6, draw decorations (foreground, scrollbars)
onDrawForeground(canvas);
2. 示例代码
下边通过一个示例代码,演示:创建画笔Paint,在 画布Canvas 绘制矩形、绘制TextView文字
效果图:
图片.png1>:自定义MyView :
/**
* ================================================
* Email: 2185134304@qq.com
* Created by Novate 2018/12/25 16:33
* Version 1.0
* Params:
* Description: 自定义MyView,继承View,
*
* 备注:用于演示:用画笔在画布上边画矩形、画文字
* ================================================
*/
public class MyView extends View {
private Paint mPaint ;
public MyView(Context context) {
this(context,null);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs , 0);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 创建画笔对象
mPaint = new Paint() ;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 设置画笔颜色为黄色
mPaint.setColor(Color.YELLOW);
// 在画布上画矩形
canvas.drawRect(0 , 0 , getWidth() , getHeight() , mPaint);
// 设置画笔颜色为蓝色
mPaint.setColor(Color.BLUE);
mPaint.setTextSize(20);
String text = "殷桃" ;
// 在画布上写文字
canvas.drawText(text , 0 , getHeight()/2 , mPaint);
}
}
2>:在 xml中使用:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<com.novate.test.view.MyView
android:layout_width="50dp"
android:layout_height="100dp"
android:background="@color/colorAccent"
/>
</LinearLayout>
因为在 MyView 代码中 没有 绘制背景,所以这里手动在xml我呢间中设置 background
网友评论