欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Android中常见的图形绘制方式总结

程序员文章站 2022-03-05 20:36:25
目录view + canvassurfaceview + canvastextureview + canvassurfaceview + opengl esglsurfaceview + opengl...

图形绘制概述

android平台提供丰富的官方控件给开发者实现界面ui开发,但在实际业务中经常会遇到各种各样的定制化需求,这必须由开发者通过自绘控件的方式来实现。通常android提供了canvas和opengl es两种方式来实现,其中canvas借助于android底层的skia 2d向量图形处理函数库来实现的。具体如何通过canvas和opengl来绘制图形呢?这必须依赖于android提供的view类来具体实现,下面组合几种常见的应用方式,如下所示:

canvas

  • view + canvas
  • surfaceview + canvas
  • textureview + canvas

opengl es

  • surfaceview + opengl es
  • glsurfaceview + opengl es
  • textureview + opengl es

view + canvas

这是一种通常使用的自绘控件方式,通过重写view类的ondraw(canvas canvas)方法实现。当需要刷新绘制图形时,调用invalidate()方法让view对象自身进行刷新。该方案比较简单,涉及自定义逻辑较少,缺点是绘制逻辑在ui线程中进行,刷新效率不高,且不支持3d渲染。

surfaceview + canvas

这种方式相对于view + canvas方式在于使用surfaceview,因此会在android的wms系统上创建一块自己的surface进行渲染绘制,其绘制逻辑可以在独立的线程中进行,因此性能相对于view + canvas方式更高效。但通常情况下需要创建一个绘制线程,以及实现surfaceholder.callback接口来管理surfaceview的生命周期,其实现逻辑相比view + canvas略复杂。另外它依然不支持3d渲染,且surface因不在view hierachy中,它的显示也不受view的属性控制,所以不能进行平移,缩放等变换,也不能放在其它viewgroup中,surfaceview 不能嵌套使用。

textureview + canvas

该方式同surfaceview + canvas方式有些类似,但由于它是通过textureview来实现的,所以可以摒弃surface不在view hierachy中缺陷,textureview不会在wms中单独创建窗口,而是作为view hierachy中的一个普通view,因此可以和其它普通view一样进行移动,旋转,缩放,动画等变化。这种方式也有自身缺点,它必须在硬件加速的窗口中才能使用,占用内存比surfaceview要高,在5.0以前在主ui线程渲染,5.0以后有单独的渲染线程。

以上都是2d图形渲染常见的方式,如果想要进行3d图形渲染或者是高级图像处理(比如滤镜、ar等效果),就必须得引入opengl es来实现了。opengl es (opengl for embedded systems) 是 opengl 三维图形 api 的子集,针对手机、pda和游戏主机等嵌入式设备而设计,是一种图形渲染api的设计标准,不同的软硬件开发商在opengl api内部可能会有不同的实现方式。

下面介绍一下在android平台上,如何进行opengl es渲染绘制,通常有以下三种方式:

surfaceview + opengl es

egl是opengl api和原生窗口系统之间的接口,opengl es 的平台无关性正是借助 egl 实现的,egl 屏蔽了不同平台的差异。如果使用opengl api来绘制图形就必须先构建egl环境。

通常使用 egl 渲染的一般步骤:

- 获取 egldisplay对象,建立与本地窗口系统的连接调用eglgetdisplay方法得到egldisplay。

- 初始化egl方法,打开连接之后,调用eglinitialize方法初始化。

- 获取eglconfig对象,确定渲染表面的配置信息调用eglchooseconfig方法得到 eglconfig。

- 创建渲染表面eglsurface通过egldisplay和eglconfig,调用eglcreatewindowsurface或eglcreatepbuffersurface方法创建渲染表面得到eglsurface。

- 创建渲染上下文eglcontext通过egldisplay和eglconfig,调用eglcreatecontext方法创建渲染上下文,得到eglcontext。

- 绑定上下文通过eglmakecurrent 方法将 eglsurface、eglcontext、egldisplay 三者绑定,绑定成功之后opengles环境就创建好了,接下来便可以进行渲染。

- 交换缓冲opengles 绘制结束后,使用eglswapbuffers方法交换前后缓冲,将绘制内容显示到屏幕上,而屏幕外的渲染不需要调用此方法。

- 释放egl环境绘制结束后,不再需要使用egl时,需要取消eglmakecurrent的绑定,销毁 egldisplay、eglsurface、eglcontext三个对象。

以上egl环境构建比较复杂,这里先不做过多解释,下面可以通过代码参考其具体实现:

从上面的代码可以看到,相对于surfaceview + canvas的绘制方式,主要有以下两点变化:

  • 在while(true)循环前后增加了egl环境构造的代码
  • onrender()方法内参数用的是gl10而不是canvas

glsurfaceview + opengl es

由于构建egl环境比较繁琐,以及还需要健壮地维护一个线程,直接使用surfaceview进行opengl绘制并不方便。幸好android平台提供glsurfaceview类,很好地封装了这些逻辑,使开发者能够快速地进行opengl的渲染开发。要使用glsurfaceview类进行图形渲染,需要实现glsurfaceview.renderer接口,该接口提供一个ondrawframe(gl10 gl)方法,在该方法内实现具体的渲染逻辑。

textureview + opengl es

该方式跟surfaceview + opengl es使用方法比较类似,使用该方法有个好处是它是通过textureview来实现的,所以可以摒弃surface不在view hierachy中缺陷,textureview不会在wms中单独创建窗口,而是作为view hierachy中的一个普通view,因此可以和其它普通view一样进行移动,旋转,缩放,动画等变化。这里使用textureview类在构建egl环境时需要注意,传入eglcreatewindowsurface()的参数是surfacetexture实例。

代码示例参考

总结

到此这篇关于android中常见图形绘制方式的文章就介绍到这了,更多相关android图形绘制方式内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!