> 移动开发 > Android > 正文
Android4.2源码View.draw(Canvas canvas)中canvas分析
2014-01-03
来源:u012604322的专栏
我要投稿
ViewGroup.java中绘制从dispatchDraw()开始,这里的Canvas由ViewRootImpl.java中传入,此时Canvas是屏幕大小的画布。
@Override
protected void dispatchDraw(Canvas canvas) {
...
more |= drawChild(canvas, child, drawingTime);
}
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
return child.draw(canvas, this, drawingTime);
}
drawChild函数只有一句话,指向了View.java的draw(Canvas canvas, ViewGroup parent, long drawingTime)函数。(这个函数不同于draw(Canvas canvas)函数,后者是View绘制过程开始的地方)
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
...
int sx = 0;
int sy = 0;
if (!hasDisplayList) {
computeScroll();
sx = mScrollX;
sy = mScrollY;
}
final boolean hasNoCache = cache == null || hasDisplayList;
final boolean offsetForScroll = cache == null && !hasDisplayList &&
layerType != LAYER_TYPE_HARDWARE;
int restoreTo = -1;
if (!useDisplayListProperties || transformToApply != null) {
restoreTo = canvas.save();
}
if (offsetForScroll) {
canvas.translate(mLeft - sx, mTop - sy);
} else {
if (!useDisplayListProperties) {
canvas.translate(mLeft, mTop);
}
if (scalingRequired) {
if (useDisplayListProperties) {
// TODO: Might not need this if we put everything inside the DL
restoreTo = canvas.save();
}
// mAttachInfo cannot be null, otherwise scalingRequired == false
final float scale = 1.0f / mAttachInfo.mApplicationScale;
canvas.scale(scale, scale);
}
}
...
if (!layerRendered) {
if (!hasDisplayList) {
// Fast path for layouts with no backgrounds
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
if (DBG_DRAW) {
Xlog.d(VIEW_LOG_TAG, "view draw1 : calling dispatchDraw,this = " + this);
}
dispatchDraw(canvas);
} else {
if (DBG_DRAW) {
Xlog.d(VIEW_LOG_TAG, "view draw1 : calling draw,this = " + this);
}
draw(canvas);
}
} else {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
...
}
上面这段代码,有两个需要指出的地方,一个就是canvas.translate()函数,这里表明了ViewRootImpl传进来的Canvas需要根据子视图本身的布局大小进行裁减,也就是说屏幕上所有子视图的canvas都只是一块裁减后的大小的canvas,当然这也就是为什么子视图的canvas的坐标原点不是从屏幕左上角开始,而是它自身大小的左上角开始的原因。
第二个需要指出的是如果ViewGroup的子视图仍然是ViewGroup,那么它会回调dispatchDraw(canvas)进行分法,如果子视图是View,那么就调用View的draw(canvas)函数进行绘制。
点击复制链接 与好友分享!回本站首页
上一篇:android开发之蓝牙主动配对连接手机
下一篇:android返回到上一个Activity
相关文章
Android4.0 中文版界面抢先看
android4.0源码下载 编译 系统体验~
android4.0 jni Hello World 开发
Android4.0中AppWidget的一些新玩意体
Android4.0.3源码分析——开机流程之Z
如何隐藏Android4.0及以上版本的Actio
android4.0下载问题
android4.0 statusbar加载icon
android4.0 中如何在app 中屏蔽HOME键
android4.0 Power、home、menu等按键
图文推荐