android5从入门到精通绘图_第1页
android5从入门到精通绘图_第2页
android5从入门到精通绘图_第3页
android5从入门到精通绘图_第4页
android5从入门到精通绘图_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第十章绘图

10.1

2D绘图10.2

Drawable10.3

3D绘图10.4硬件加速10.5RenderScript10.6

小结10.7

思考题10.1

2D绘图AndroidAPI提供一系列进行2D绘图的方法,被放置在android.graphics.drawable包下。通常有两种2D绘图的方法:在布局文件定义的View组件中进行绘图。绘图工作由系统的绘制进程管理,开发者只需绘制图形即可。这种方式适合于绘制不需要实时更新的静态图像。在Canvas中绘图。这种方式需要由开发者自己调用onDraw()方法来对图像进行绘制。当图像需要定时更新时最好使用这种方式,适合于动画绘制和视频游戏开发。10.1.1获取Canvas对象要在Android系统下绘制图形,需要四个基本组件,分别为:Bitmap:相当于画布,用于管理像素。Canvas:相当于在在Bitmap上绘图的画家,用于管理绘制过程,提供绘图方法。Drawable绘制要素:Drawable绘制要素包括形状、路径、文本,图像等,用于将Canvas绘制的图像显示给用户。Paint:相当于绘图用到画笔,可以设置画笔的颜色、类型等。若在自定义的View组件上绘制图像,只需重写onDraw()方法即可。10.1.2使用自定义View绘图实例MyViewCanvasDemo自定义了一个名为MyView的View类,并在其onDraw()方法中绘制了简单的图像,运行效果如图10.1所示。图10.1简单View绘图10.1.3使用Bitmap绘图可以通过新建Bitmap对象,并在其上使用Canvas进行绘图的方式创建图像。实例BitmapDrawDemo演示了Canvas使用Bitmap对象绘图的过程。该实例的绘制内容与10.1.2节实例的绘制内容完全相同,只不过不是直接绘制在View上,而是绘制在一个Bitmap对象上,绘制完成后,将Bitmap图像显示到视图上,其运行效果如图10.2所示。图10.2Bitmap对象的绘图效果10.1.4使用SurfaceView绘制静态图像使用SurfaceView绘图,需要为SurfaceView对象添加SurfaceHoloder.Callback接口,并在该接口的surfaceCreated()方法中通过lockCanvas()方法获取Canvas对象,以此保证当获取Canvas时,SurfaceView对象可用。当绘图工作完成后,通过SurfaceHoloder.unlockCanvas-AndPost()方法将绘图显示出来,并释放Canvas对象。实例SurfaceViewDrawDemo演示了使用SurfaceView组件绘制静态图的过程,其绘制内容与10.1.2节绘制内容完全相同。通过该实例,读者可以清楚地认识到使用SurfaceView绘图与使用View绘图的不同之处,该实例运行效果如图10.3所示。图10.3SurfaceView绘图效果10.1.5使用SurfaceView绘制动态图像实例SurfaceViewDrawDemo绘制的是一幅静态图像,而使用SurfaceView绘图的优点在于绘制动态图像。绘制静态图像的过程应该在一个单独的线程中完成,而不应该在主线程中进行。实例SurfaceViewDynDrawDemo演示了使用SurfaceView组件绘制动态图像的过程。该实例修改自AndroidSDK提供的实例,绘制的是类似于Windows中的变幻线屏保的效果,运行效果如图10.4所示。

图10.4实例SurfaceViewDynDrawDemo运行效果10.2

Drawable

Drawable是“可绘制的东西”的抽象类,被定义在android.graphics.drawable包下。该类继承了很多代表不同形状的子类,例如BitmapDrawable、ShapeDrawable、PictureDrawable等等。开发者也可以定义自己的用于特定形状绘制的子类。获取Drawable对象有三种方式:使用工程资源文件中保存的图像资源。使用xml文件定义的Drawable属性。通过构造方法构建。10.2.1从资源文件中创建Drawable对象添加图像到应用程序工程中最简单的方式就是从资源文件中获取图像。资源文件中的图像资源会被放置在res/drawable/文件夹下,常见的图像资源类型有PNG、JPG和GIF,在允许的情况下,建议优先使用PNG格式的图像,其次是JPG格式的图像。系统会自动为每个drawable文件夹下的资源文件生成一个格式为R.drawable.xxx的ID号,在工程中可以通过该ID使用该资源。在之前的实例中,我们一直在使用这种方法。10.2.2从XML文件中创建Drawable对象10.2.3使用构造方法创建Drawable对象以ShapeDrawable为例,ShapeDrawable是Drawable的子类,ShapeDrawable对象适合于动态绘制二维图形。10.3

3D绘图

10.3.1OpenGLES简介OpenGL是一组跨平台的3D图像处理API,OpenGL是OpenGL的嵌入式版本,Android系统从Android1.0开始支持OpenGLES1.0和1.1,自Android2.2(APILevel8)开始,Android框架开始支持OpenGL2.0API。由于篇幅所限,在此不可能详细地介绍OpenGLES的方方面面,仅能简单介绍其使用方法。详细资料读者可以查询AndroidSDK的相关文档。10.3.2绘制3D图像实例使用OpenGLESAPI绘制3D图像,有两个基础的相关类,一个是GLSurfaceView类,一个是GLSurfaceView.Renderer接口。(1)GLSurfaceView类GLSurfaceView类是SurfaceView的子类,使用内嵌的Surface进行OpenGL绘图渲染。GLSurfaceView提供以下功能:管理Surface,Surface是一块内存,可以被加载到View视图中。管理一个EGL显示,能够使用OpenGL把内容渲染到surface上。接受用户自定义渲染器用于实际渲染。使渲染器在单独的线程总运行,和更新UI的线程相分离。支持按需渲染(on-demandrendering)和连续渲染(continuousrendering)。提供一些可选工具,如OpenGL调用的跟踪调试和错误检查等。(2)GLSurfaceView.Renderer接口GLSurfaceView.Renderer接口定义了使用OpenGL绘图时所需的方法。该接口通过GLSurfaceView.setRenderer()与GLSurfaceView关联在一起。该接口实现以下三个方法:onSurfaceCreated():当创建GLSurfaceView对象后该方法被系统调用一次。通常在该方法中设置OpenGL环境的相关参数,初始化OpenGL图形对象等。onDrawFrame():GLSurfaceView对象每一次重绘时系统都会调用该方法。该方法应该执行具体的绘图工作。onSurfaceChanged():当GLSurfaceView对象的几何外形改变时,包括GLSurfaceView的尺寸发生改变、设备屏幕的方向发生改变等情况,该方法被系统调用。实例OpenGLDemo演示了在Activity中使用GLSurfaceView和GLSurfaceView.Renderer合作绘制三维图形的过程。该实例绘制了一个不断旋转的立方体,运行效果如图10.5所示图10.5实例OpenGLDemo运行效果10.4硬件加速

从Android3.0(APILevel11)开始,Android2D渲染管线被设计为能更好地支持硬件加速功能。硬件加速功能将所有在View组件的Canvas上执行的绘制操作都交由GPU来完成。由于硬件加速功能需要更多的资源,因此启用硬件加速功能的应用程序会耗费更多的内存资源。10.4.1启用硬件加速启用硬件加速最简单的方法是在总体上位整个应用程序打开硬件加速功能。如果应用程序中仅仅使用了标准的View和Drawable对象进行图像绘制,那么在总体上打开硬件加速功能不会出现任何的不良影响。但是,由于硬件加速功能并不是被所有的2D绘制操作所支持,因此对于一些自定义的View组件和Drawable对象的绘制,可能会出现无法显示、异常或者错误渲染的点等问题。为了避免这类问题的发生,Android平台提供了以下四个应用层次的硬件加速开关设置:Application,应用程序级。Activity,视图级。Window,窗口级。View,组件级。10.4.2Android绘图模型1.基于软件的绘图模型当应用程序需要更新UI的某一个部分时,会通过更改了内容的View组件调用invalidate()方法将当前组件无效化。该方法触发一个重绘消息,该消息会沿着视图的层次一直向上传递,以计算需要重绘的区域。然后Android系统会重绘在视图层次中与要重绘区域有交叉的所有组件。基于软件的绘图模式主要完成如下两个工作:无效化绘图层次重绘绘图层次这种绘图模型有两个缺点:首先,这个模型会导致在消息传递过程中多执行大量无效的绘图代码。例如,一个按钮位于一个View上,当该按钮被单击时,虽然该View没有发生任何的改变,但是在这种绘图模型下,该View也会被重绘。第二个缺点是这种绘图模型可能隐藏应用程序中的bug。由于Android系统会重绘所有与需重绘区域有交叉的View组件,一个被用户改变了内容的View组件可能会被重绘,即使该组件没有调用invalidate()方法。当这种情况发生的时候,用户只能依靠另外一个组件的重绘操作来获取自己想要的效果,而这种效果可能会不断改变。因此,开发者应该在自定义的组件上不断的调用invalidate()方法以保证内容显示正确,无论该组件的内容是否被改变。当Android组件的内容发生改变,如背景色改变或者文本改变时,该组件会自动调用invalidate()方法。2.硬件加速绘制模型在硬件加速绘制模型下,Android系统依然使用invalidate()方法和draw()方法来对屏幕进行更新并绘制图形,但是具体处理的方法有所不同。这种模式下Android系统并没有马上执行绘图命令,而是记录了当前视图的显示列表。显示列表中包含了视图层次中所有绘图代码的输出。Android系统只需要录制并且更新需要重绘组件的显示列表即可。那些没有被无效化的组件可以简单通过重新使用之前记录的显示列表的方式来重绘图形。硬件加速绘图模型主要完成如下三个工作:无效化视图的绘图层次记录并更新显示列表绘制显示列表在这种模式下,与不能依靠与需要更新区域有交叉的组件的draw()方法来更新图像,而是应该调用invalidate()方法来使Android系统记录组件的显示列表。如果没有这样做,该组件的更新将不会显示出来。使用显示列表方式绘制图像对动画绘制也有很大好处。因为设置特定属性,例如透明度、旋转灯,不需要重新绘制整个视图,而只需对特定属性进行更改即可。例如,假如有一个LinearLayout,该LinearLayout中包含一个ListView组件和一个Button组件,ListView组件被放置在Button组件的上面。该LinearLayout组件的显示列表如下所示:DrawDisplayList(ListeView)DrawDisplayList(Button)如果开发者需要更改ListView的透明度,那么通过ListView对象调用了setAlpha(0.5f)方法后,LinearLayout的显示列表如下:SaveLayerAlpha(0.5)DrawDisplayList(ListeView)RestoreDrawDisplayList(Button)由此可见,绘图ListView的复杂代码并没有被执行,系统只是简单更新了LinearLayout的显示列表。对于一个没有被硬件加速的应用程序,该过程中的每一行代码都会被重新执行一次。10.5RenderScript

Renderscript基于C99标准,提供了一个平台独立的运行在底层的计算引擎,用于加速需要大量计算的应用程序,常用于3D图像渲染。RenderScript主要优点如下:可移植性:RenderScript被设计为在各种具有不同CPU和CPU架构的设备上运行。由于其代码是在运行设备上进行编译和缓存的,因此RenderScript可以支持所有架构而不需要针对某种架构具体编程。性能:RenderScript能够提供与OpenGL相似的性能,同时提供与Android框架提供的OpenGLAPI(android.opengl)相同的移植性。另外,RenderScript提供OpenGL所没有的高性能计算API。可用性:RenderScript尽可能简化了开发过程。当然,RenderScript也有缺点,主要表现在:开发复杂:RenderScript提供资金的API集合,开发者需要重新学习。RenderScript处理内存的方式与OpenGL不同。调试可见:RenderScript可以在其他处理器上被执行,而不是主CPU上。在这种情况下,调试变得很困难。特性较少:RenderScript不像OpenGL那样提供很多特性,例如压缩纹理格式或者GL扩展。10.5.1RenderScript综述RenderScript采用的是主从结构。底层的本地化代码被高层的运行的虚拟机中的Android系统控制。Android虚拟机保有内存和声明周期的控制权,在需要的时候调用本地的RenderScript代码。本地化代码被编译为中间的字节码,并且被打包到应用程序的.apk文件中。当应用程序在设备上运行的时候,字节码被编译为针对当前机器优化的机器码。编译的字节码被缓存起来,因此之后需要使用RenderScript代码时不需要重新编译。RenderScript有三个层次的代码,允许本地化代码和Android框架之间进行通信。本地RenderScript层:该层负责密集运算或者图像渲染,相关代码被保存在.rs或者.rsh文件中。反射层:该层由一系列类组成,这些类由本地代码反射而来。基本上是对本地代码的包装,以允许Android框架与本地RenderScript代码进行交互。AndroidBuild工具自动生成该层的相关类。Android框架层:该层由Android框架API组成,包括android.renderscript包。该层用于给反射层发出高级命令,如“旋转视图”或者“过滤位图”,然后反射层将命令传送给本地层执行。(1)本地RenderScript库的关键特性包括:大量针对标量和向量计算的数学函数,包含加、乘、加乘、点乘等。原始数据与向量的转换例程,矩阵例程、日期和时间例程、图像例程等。日志函数。图形渲染函数。内存分配请求特性。支持RenderScript系统的数据类型和结构,例如二维向量、三维向量、思维向量等。RenderScript库相关头文件被放置在<Androidsdk_root>/platform-tools/renderscript/include目录下。该目录下的头文件会被自动保存进.rs文件中,除了RenderScript的图像处理头文件。因此需要使用下面的代码手工导入:#include"rs_graphics.rsh"(2)反射层是一组由AndroidBuild工具生成的类,可以从Android虚拟机访问本地的RenderScript代码。反射层定义了RenderScript函数和变量的访问点,以便Android框架能够访问透明。该层也提供了构造方法,用于为定义在RenderScript代码中的指针分配内存。下面简单介绍被反射的主要组件:每个.rs文件都生成一个类,被存放在名为ScriptC_renderscript_filename的ScriptC类型的文件中,它相当于.rs文件的.java版本,可以被Android框架调用。该类包含了下列反射:.rs文件中的非静态方法。非静态的全局的RenderScript变量。全局指针。(3)Android框架层由通常的Android框架API组成,包含android.renderscript包。该层管理Activity的声明周期以及应用程序的内存分配。它通过反射层发送命令给本地RenderScript代码,并接收用户事件按需传递给RenderScript代码。10.5.2使用动态分配的内存涉及RenderScript内存分配API的类有三个:Element:内存分配的基本单位,可以是基本的数据类型或者是复合类型。Type:表示要分配的元素个数。Allocation:用于执行分配内存操作。RenderScript支持指针,但是必须在Android框架代码中为它分配内存。当开发者在.rs文件中声明一个全局的指针时,需要通过合适的反射层类来分配内存,并将其绑定到本地的RenderScript层。开发者可以通过Android框架层和RenderScript层读写该内存。1.定义指针2.反射指针3.分配并绑定内存到RenderScript4.读写内存10.5.3使用静态分配的内存在RenderScript中声明的非静态的全局原始数据类型和结构体很容易使用,因为这些内存是静态分配的。AndroidBuild工具在生成反射层类时会自动为这些变量生成存取方法,开发者可以通过这些方法来使用静态分配的内存。10.6

小结

本章简单介绍了Android系统下绘图的相关方法。Android系统提供了一系列方法可供开发者绘制自己所需要的2D或者3D

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论