我正在努力理解绘制到SurfaceView的过程,以及整个Surface/Canvas/Bitmap系统,它在Android中使用.

我已经阅读了所有的文章和API文档页面,我可以在android开发者网站上找到它们,一些android图形教程,LunarLander源代码和this question.

请告诉我,这些陈述中哪些是正确的,哪些不是,以及为什么.

  1. Canvas有它自己的Bitmap.Surface有它自己的Canvas.
  2. 所有View个窗口共享相同的Surface,因此共享相同的Canvas.
  3. SurfaceViewView的子类,与其他View的子类和View本身不同,View有自己的Surface可供借鉴.

还有一个问题:

  • 如果已经有Canvas类用于位图的高级操作,那么为什么需要Surface类呢.举一个例子,说明Canvas不适合做Surface能做的工作.

推荐答案

以下是一些定义:

  • 曲面是包含正在合成到屏幕上的像素的对象.你在屏幕上看到的每个窗口(对话框、全屏活动、状态栏)都有自己的表面,它会将其绘制到其中,surface Flinger会以正确的Z顺序将其渲染到最终显示.一个曲面通常有多个缓冲区(通常两个)来进行双缓冲渲染:当surface flinger使用最后一个缓冲区合成屏幕时,应用程序可以绘制其下一个UI状态,而无需等待应用程序完成绘制.

  • 窗口基本上就像你想象的桌面上的窗口.它有一个单独的表面,在其中渲染窗口的内容.应用程序与窗口管理器交互以创建窗口;窗口管理器 for each 窗口创建一个曲面,并将其提供给绘图应用程序.应用程序可以在表面上绘制任何它想要的东西;对于窗口管理器来说,它只是一个不透明的矩形.

  • 视图是窗口内的交互式UI元素.窗口附加了单个视图层次 struct ,该层次 struct 提供了窗口的所有行为.无论何时需要重新绘制窗口(例如,因为视图本身已无效),都会在窗口的Surface中执行此操作.曲面已锁定,这将返回可用于在其中绘制的画布.绘制遍历沿层次 struct 向下进行,向下传递每个视图的画布以绘制其UI部分.完成后,曲面将解锁并发布,以便将刚绘制的缓冲区交换到前景,然后由Surface Flinger将其合成到屏幕上.

  • SurfaceView是视图的一种特殊实现,它还创建自己的专用曲面,供应用程序直接绘制(在普通视图层次之外,否则必须共享窗口的单个曲面).其工作方式比您预期的要简单——SurfaceView所做的只是要求窗口管理器创建一个新窗口,告诉它在SurfaceView的窗口后面或前面对该窗口进行Z排序,并将其定位为与SurfaceView在包含窗口中的显示位置相匹配.如果曲面放置在主窗口后面(按Z顺序),SurfaceView也会用透明度填充其主窗口部分,以便可以看到曲面.

  • 位图只是某些像素数据的接口.当您直接创建像素时,像素可能由Bitmap本身分配,或者它可能指向它不拥有的像素,例如内部发生的将画布连接到Surface进行绘制的情况.(创建位图并将其指向曲面的当前绘图缓冲区.)

此外,请记住,正如这意味着的,SurfaceView是一个相当重的物体.如果在一个特定的用户界面中有多个SurfaceView,停下来想想是否真的需要它.如果你有两个以上,你几乎肯定有太多.

Android相关问答推荐

如何使禁用状态下的material 3按钮与启用状态下的 colored颜色 相同?

显示本地房间数据库中未保存的项目的动态列表

Android意图过滤器不限制应用程序仅处理YouTube链接

为什么当我在装有Firebase的安卓系统中登录苹果时,收到的邮箱为空?

Android布局渲染问题

Android 导航 - 定义参数

相机2问题:设置AE区域、AF区域和AWB区域.

如何避免多次调用 Jetpack Compose 的 onClick 回调

在 compose 中做可变状态堆栈

Jetpack Compose 中带有权重的行和 AnimatedVisibility 会 destruct UI

用作输入参数的 Lambda 函数导致重组

在 react native 中设置 react-native-paper 组件的样式

为什么我的应用程序使用这些信息?

compose 导航参数字符串包含花括号?

Jetpack compose 未解决的参考错误

房间创建三四表关系

如何在 Android 上移动 EditText 上的图标?

为什么官方文档用大写字母表示val变量?

Google Play 服务登录在 Unity Android 上无法正常运行

使用协程访问数据库