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

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

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

【问题讨论】:

    标签: android view android-canvas


    【解决方案1】:

    它们之间是有区别的

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

    2. 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) 完成后更正确地获取此信息
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多