Understanding Canvas and Surface concepts

I'm struggling to understand the process of drawing to SurfaceView and therefore the whole Surface/Canvas/Bitmap system, which is used in Android.

I've read all articles and API documentation pages, which I was able to find on android-developers site, a few tutorials of android graphics, LunarLander source code and this question.

Please tell me, which of these statements are true, which are not, and why.

  1. Canvas has its own Bitmap attached to it. Surface has its own Canvas attached to it.
  2. All View's of window share the same Surface and thus share the same Canvas.
  3. SurfaceView is subclass of View, which, unlike other View's subclasses and View itself, has its own Surface to draw in.

There is also one additional question:

  • Why is there a need for a Surface class, if there is already a Canvas for high-level operations with bitmap. Give an example of a situation where Canvas is non-suitable for doing work which Surface can do.
42536 次浏览

A Bitmap is simply a wrapper for a collection of pixels. Think of it as an array of pixels with some other convenient functions.

Canvas 只是包含所有绘图方法的类。如果您熟悉的话,它类似于 AWT/Swing 中的 Graphics 类。所有关于如何画一个圆圈,或一个盒子等的逻辑都包含在画布中。一个画布在一个 Bitmap 或者一个打开的 GL 容器上绘制,但是将来没有理由将它扩展到其他类型的光栅上。

SurfaceView 是一个包含 Surface 的视图。表面类似于位图(它有像素存储)。我不知道它是如何实现的,但我可以想象它是某种位图包装,带有与屏幕显示直接相关的额外方法(这就是设计一个表面的原因,位图太通用了)。你可以从你的 Surface 得到一个 Canvas,它实际上是得到与底层位图相关联的 Canvas。

你的问题。

1. Canvas 有自己的位图,Surface 有自己的 Canvas。

是的,一个画布操作一个位图(或一个开放的 GL 面板)。Surface 提供了一个 Canvas,该 Canvas 在 Surface 使用的任何位图样式像素存储上进行操作。

2. 所有窗口的视图共享相同的表面,因此共享相同的画布。

不,你想看多少就看多少。

SurfaceView 是 View 的子类,与其他 View 的子类和 View 本身不同,它有自己的 Surface 可以绘制。

是的。就像 ListView 是 View 的子类一样,它有自己的 List 数据结构。View 的每个子类都执行不同的操作。

下面是一些定义:

  • Surface 是一个对象,其中包含要合成到屏幕上的像素。你在屏幕上看到的每个窗口(一个对话框,你的全屏活动,状态栏)都有它自己的表面,并且 Surface Flinger 以正确的 Z 顺序将它们呈现给最终的显示。一个表面通常有多个缓冲区(通常是两个)来进行双缓冲渲染: 应用程序可以绘制其下一个 UI 状态,而表面触发器使用最后一个缓冲区组合屏幕,而不需要等待应用程序完成绘制。

  • 一个窗口基本上就像你想象的桌面上的一个窗口。它有一个单独的 Surface,其中呈现窗口的内容。应用程序与 Window Manager 交互以创建窗口; Window Manager 为每个窗口创建一个 Surface,并将其提供给应用程序用于绘制。应用程序可以在 Surface 中绘制它想要的任何东西; 对于 Window Manager,它只是一个不透明的矩形。

  • View 是窗口内部的交互式 UI 元素。一个窗口有一个附加到它的视图层次结构,它提供了该窗口的所有行为。无论何时需要重绘窗口(例如,因为视图已经使自身失效) ,这都会在窗口的 Surface 中完成。Surface 是锁定的,它返回一个画布,可以用来绘制到它。在层次结构中进行绘制遍历,将 Canvas 传递给每个视图以绘制其 UI 部分。一旦完成,表面是解锁和张贴,以便刚刚绘制的缓冲区交换到前景,然后合成到屏幕上的表面闪烁。

  • SurfaceView 是 View 的一个特殊实现,它还为应用程序创建自己的专用 Surface,以便直接绘制(在普通视图层次结构之外,否则必须为窗口共享单个 Surface)。它的工作方式比你想象的要简单—— SurfaceView 所做的就是要求窗口管理器创建一个新窗口,告诉窗口管理器对这个窗口在 SurfaceView 窗口的后面或前面进行 Z 顺序,并将其定位到与包含窗口中出现的 SurfaceView 相匹配的位置。如果表面被放置在主窗口的后面(Z 顺序) ,那么 SurfaceView 也会以透明的方式填充它的主窗口部分,以便可以看到表面。

  • 位图只是一些像素数据的接口。当您直接创建一个像素时,像素可以由 Bitmap 本身分配,或者它可以指向它不拥有的像素,比如内部发生的将画布挂接到 Surface 进行绘图的情况。(创建一个位图并指向 Surface 的当前绘图缓冲区。)

还请记住,正如这意味着的那样,SurfaceView 是一个相当重量级的对象。如果在一个特定的 UI 中有多个 SurfaceView,停下来考虑一下是否真的需要这样做。如果你有两个以上,你几乎肯定有太多。

A conceptual overview of Window, Surface, Canvas, and Bitmap

这里是一个非常基本和简单的概念概述如何交互发生在窗口,表面,画布和位图。
有时,可视化表示对理解扭曲的概念有很大帮助。
我希望这张图能帮到别人。