您的位置:首页 > 移动开发 > Android开发

【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 - 原创文章,转载请注明出处
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐