【Android】View绘制过程分析之draw
2014-02-22 10:49
441 查看
续前文“【Android】View绘制过程分析之layout",继续分析View的绘制过程。
本文分析第3阶段,分析过程的注释标记在以下代码中。
/**
* 绘制过程
*/
public void draw(Canvas canvas) {
if (mClipBounds != null) {
canvas.clipRect(mClipBounds);
}
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;
/*
* 绘制过程依次进行下面的6步处理:
* 1. 绘制背景
* 2. If necessary, save the canvas' layers to prepare for fading
* 3. 绘制View的内容, 在onDraw(canvas)方法中完成
* 4. 绘制子View的内容
* 5. If necessary, draw the fading edges and restore layers
* 6. 绘制装饰品(如滚动条)
*/
// 第1步,绘制背景
int saveCount;
if (!dirtyOpaque) {
final Drawable background = mBackground;
if (background != null) {
final int scrollX = mScrollX;
final int scrollY = mScrollY;
if (mBackgroundSizeChanged) {
background.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
mBackgroundSizeChanged = false;
}
if ((scrollX | scrollY) == 0) {
background.draw(canvas);
} else {
canvas.translate(scrollX, scrollY);
background.draw(canvas);
canvas.translate(-scrollX, -scrollY);
}
}
}
// 一般情况下,会跳过第2步与第5步
final int viewFlags = mViewFlags;
boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
if (!verticalEdges && !horizontalEdges) {
// 第3步,绘制View的内容,自定义View时,这个方法需要我们去实现。
if (!dirtyOpaque) onDraw(canvas);
// 第4步,绘制子View的内容,参考ViewGroup中dispatchDraw(canvas)方法的实现,
//OK,你猜到了!又是一次遍历子View的过程,子View再调用draw(canvas)方法绘制自己及孙View。
//父View与子View这样的遍历过程,是Android一贯的做法。
dispatchDraw(canvas);
// 第6步,绘制装饰品(如滚动条)
onDrawScrollBars(canvas);
if (mOverlay != null && !mOverlay.isEmpty()) {
mOverlay.getOverlayView().dispatchDraw(canvas);
}
return;
}
}
/**
* 绘制View的内容,在View类此方法空实现。但在自定义View类时,要实现此方法。
* 在这个方法中,可做的事情就多了,Canvas提供了丰富的绘图方法,关键是灵活运用!
* 通常,你还可以通过调用以下方法或protected属性获取到一次绘制时需要用到的数值:
* getMeasuredWidth()与getMeasuredHeight() 获取measure()中计算到的宽度与高度
* mPaddingLeft, mPaddingTop, mPaddingRight, mPaddingBottom, mScrollX, mScrollY等等,直接使用。
*/
protected void onDraw(Canvas canvas) {
}
/**
* 下面看一下ImageView的绘制:
*/
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mDrawable == null) {
return; // couldn't resolve the URI
}
if (mDrawableWidth == 0 || mDrawableHeight == 0) {
return; // nothing to draw (empty bounds)
}
if (mDrawMatrix == null && mPaddingTop == 0 && mPaddingLeft == 0) {
mDrawable.draw(canvas);
} else {
int saveCount = canvas.getSaveCount();
canvas.save();
if (mCropToPadding) {
final int scrollX = mScrollX;
final int scrollY = mScrollY;
canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop,
scrollX + mRight - mLeft - mPaddingRight,
scrollY + mBottom - mTop - mPaddingBottom);
}
canvas.translate(mPaddingLeft, mPaddingTop);
if (mDrawMatrix != null) {
canvas.concat(mDrawMatrix);
}
mDrawable.draw(canvas);
canvas.restoreToCount(saveCount);
}
}
@容新华技术博客 - http://blog.csdn.net/rongxinhua - 原创文章,转载请注明出处
本文分析第3阶段,分析过程的注释标记在以下代码中。
/**
* 绘制过程
*/
public void draw(Canvas canvas) {
if (mClipBounds != null) {
canvas.clipRect(mClipBounds);
}
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;
/*
* 绘制过程依次进行下面的6步处理:
* 1. 绘制背景
* 2. If necessary, save the canvas' layers to prepare for fading
* 3. 绘制View的内容, 在onDraw(canvas)方法中完成
* 4. 绘制子View的内容
* 5. If necessary, draw the fading edges and restore layers
* 6. 绘制装饰品(如滚动条)
*/
// 第1步,绘制背景
int saveCount;
if (!dirtyOpaque) {
final Drawable background = mBackground;
if (background != null) {
final int scrollX = mScrollX;
final int scrollY = mScrollY;
if (mBackgroundSizeChanged) {
background.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
mBackgroundSizeChanged = false;
}
if ((scrollX | scrollY) == 0) {
background.draw(canvas);
} else {
canvas.translate(scrollX, scrollY);
background.draw(canvas);
canvas.translate(-scrollX, -scrollY);
}
}
}
// 一般情况下,会跳过第2步与第5步
final int viewFlags = mViewFlags;
boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
if (!verticalEdges && !horizontalEdges) {
// 第3步,绘制View的内容,自定义View时,这个方法需要我们去实现。
if (!dirtyOpaque) onDraw(canvas);
// 第4步,绘制子View的内容,参考ViewGroup中dispatchDraw(canvas)方法的实现,
//OK,你猜到了!又是一次遍历子View的过程,子View再调用draw(canvas)方法绘制自己及孙View。
//父View与子View这样的遍历过程,是Android一贯的做法。
dispatchDraw(canvas);
// 第6步,绘制装饰品(如滚动条)
onDrawScrollBars(canvas);
if (mOverlay != null && !mOverlay.isEmpty()) {
mOverlay.getOverlayView().dispatchDraw(canvas);
}
return;
}
}
/**
* 绘制View的内容,在View类此方法空实现。但在自定义View类时,要实现此方法。
* 在这个方法中,可做的事情就多了,Canvas提供了丰富的绘图方法,关键是灵活运用!
* 通常,你还可以通过调用以下方法或protected属性获取到一次绘制时需要用到的数值:
* getMeasuredWidth()与getMeasuredHeight() 获取measure()中计算到的宽度与高度
* mPaddingLeft, mPaddingTop, mPaddingRight, mPaddingBottom, mScrollX, mScrollY等等,直接使用。
*/
protected void onDraw(Canvas canvas) {
}
/**
* 下面看一下ImageView的绘制:
*/
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mDrawable == null) {
return; // couldn't resolve the URI
}
if (mDrawableWidth == 0 || mDrawableHeight == 0) {
return; // nothing to draw (empty bounds)
}
if (mDrawMatrix == null && mPaddingTop == 0 && mPaddingLeft == 0) {
mDrawable.draw(canvas);
} else {
int saveCount = canvas.getSaveCount();
canvas.save();
if (mCropToPadding) {
final int scrollX = mScrollX;
final int scrollY = mScrollY;
canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop,
scrollX + mRight - mLeft - mPaddingRight,
scrollY + mBottom - mTop - mPaddingBottom);
}
canvas.translate(mPaddingLeft, mPaddingTop);
if (mDrawMatrix != null) {
canvas.concat(mDrawMatrix);
}
mDrawable.draw(canvas);
canvas.restoreToCount(saveCount);
}
}
@容新华技术博客 - http://blog.csdn.net/rongxinhua - 原创文章,转载请注明出处
相关文章推荐
- Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析
- Android视图的绘制流程(下)——View的Layout与Draw过程
- android view draw源码过程分析
- 【Android系列】View的绘制之draw过程
- 【Android】View绘制过程分析之measure
- Android View深入学习(三),View的绘制(Draw)过程
- 【Android】View绘制过程分析之layout
- Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析
- android学习9#--自定义View之绘制过程分析
- Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析
- Android中将布局文件/View添加至窗口过程分析 ---- 从setContentView()谈起(写的很好,这个不是从启动app说的,说的是UI是怎么绘制的)
- Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析(下)
- Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析(上)
- Android视图的绘制流程(下)——View的Layout与Draw过程
- Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析
- Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析
- Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析
- android中View绘制过程分析
- 【Android View绘制之旅】Draw过程
- Android应用程序窗口(Activity)的测量(Measure)、布局(Layout)和绘制(Draw)过程分析