在android中查看onDraw(Canvas c)与draw(Canvas c)?

Posted

技术标签:

【中文标题】在android中查看onDraw(Canvas c)与draw(Canvas c)?【英文标题】:View onDraw(Canvas c) versus draw(Canvas c) in android? 【发布时间】:2012-11-30 07:07:39 【问题描述】:

我是 android 开发新手,我正在探索 View。我遇到了已知的两种方法onDraw(Canvas c)draw(Canvas c)

能否解释一下这两种方法的区别和用法?用图像更新画布时,哪种方法会提供更好的性能(FPS)?

【问题讨论】:

【参考方案1】:

它们之间是有区别的

    onDraw(Canvas c) 是一种覆盖方法,在呈现视图时会自动调用。在这里,您可以进行额外的绘图,例如画圆、线或任何您想要的。

    draw(Canvas c) 用于手动将此视图(及其所有子视图)渲染到给定的画布上。在调用此函数之前,视图必须已经完成了完整的布局。实现视图时,实现onDraw(android.graphics.Canvas) 而不是覆盖此方法。如果确实需要重写此方法,请调用超类版本。

或者简单地说draw(Canvas c)只是一个视图的函数,你可以在第一次渲染视图后调用它。此功能可用于在任何视图上进行自定义绘图。您需要提供此视图将在其上呈现的画布,并且您必须在调用此函数之前在画布上完成所有绘图。

【讨论】:

能否告诉我这两种方法之间的性能(FPS) 我不明白这是如何回答这个问题的。好像您刚刚从内联文档中粘贴了 从我的测试来看,两者都会在视图渲染时被调用。 draw(Canvas c) 将首先被调用,然后在 draw(Canvas c) 内部调用 onDraw(Canvas c)。所以我不认为这里的“不自动调用”这个词是有效的,因为在渲染视图时两者都是“自动调用”。 draw 由框架自动调用。测量是通过 onMeasure() 回调并在其中调用 setMeasuredDimensions 完成的。与 draw/onDraw 没有直接关系。 draw() 调用 onCall() 并做一些额外的事情。这个答案有点误导。 答案被接受并获得高分,但遗憾的是第二个陈述完全错误。【参考方案2】:

如果有人像我一样还在寻找答案但没有找到。

当需要重新绘制视图时,框架调用draw()方法,然后draw()方法调用onDraw()来绘制视图的内容。

void draw(Canvas canvas)

     ..... do default stuff (background, layers)
     onDraw(canvas)
     ..... do other stuff ( scroll bars, fading edges, children)


【讨论】:

请发布文档参考。很好的答案。 我实际上检查了源代码,但是你可以看到,在渲染时,ViewGroup 每个都调用它的子 'draw()' 方法,你可以在这里查看developer.android.com/guide/topics/ui/how-android-draws.html @KarimTarabisy 我们可以使用无效方法调用draw方法吗? 这就是为什么你应该重写 onDraw(),而不是 draw()【参考方案3】:

由于 API 文档笨拙,对此存在误解。 简短的回答是,draw(Canvas) 是对 View 的入站调用以执行一些重要的事情,并且在 draw(Canvas) 实现的中间某处,它还将触发 onDraw(Canvas) 回调。

在实现用于布局内部的自定义 View 时不要覆盖 draw(Canvas)。 如果您的自定义视图旨在用作全屏游戏,则覆盖 draw() 将在每个周期为您节省一些不需要的调用。

更长的答案

框架在其绘制周期中使用draw(Canvas)。这是我可以在查看代码中找到的: 第 1 步:根据需要绘制背景 第 2 步:保存画布的图层 第三步:绘制内容---onDraw()来了 第 4 步:画孩子们 第五步:绘制渐变效果并恢复图层 第 6 步:绘制滚动条

实用提示

您可以将任何视图渲染到您创建的屏幕外位图中,然后在任何地方使用此位图:

Canvas c = new Canvas();
c.setBitmap(myOffscreenBitmap);
myView.draw(c);
对于简单的情况(当它不是 ViewGroup 并且不需要滚动条时),简单的 onDraw(Canvas) 也可以解决问题。

【讨论】:

这个答案非常准确,但是有理由覆盖 draw 而不是 onDraw(c),而不是调用 super.draw(c)。性能如果您不关心框架功能并希望尽可能快地绘制,例如在视图中类似游戏的情况,您可能想跳过这些内容。 @HaMMeReD 同意,在游戏循环中跳过框架代码是有意义的。但如果在视图层次结构中实现自定义视图,则需要框架代码。 在 ViewGroup 的情况下,我发现使用 draw 而不是 onDraw。因为 onDraw 在绘制孩子之前调用,所以在 onDraw 的初始状态我对孩子视图一无所知,例如测量 @AkbolatSSS 都是在同一个方法中同步调用的,draw() 在前,然后是 onDraw()。所以在儿童测量方面没有区别。两者都发生在布局完成并且大小设置为所有内容之后。 @AmirUval 不同意,我检查了该行为,ViewGroup 对 onDraw 中的儿童尺寸一无所知,它将在 Step 4 或在 dispatchDraw(canvas) 完成后更正确地获取此信息

以上是关于在android中查看onDraw(Canvas c)与draw(Canvas c)?的主要内容,如果未能解决你的问题,请参考以下文章

Android 如何在 Canvas 的 onDraw 方法中创建 onClick 事件

Android View双缓冲机制

Android 更新视图函数ondraw() 和dispatchdraw()的区别

Android View的绘制

帆布?或 View.onDraw() 方法中的 Canvas

android:如何用canvas在自定义view里画图