Android图形图画学习(1)

来源:互联网 发布:mac 命令行 修复系统 编辑:程序博客网 时间:2024/05/22 12:48

Android支持2D和3D绘图,其中3D绘图支持Opengl引擎,以后的学习过程中再行记录。

关于2D绘图,Android提供了一套完整的API,我们可以绘制自定义图形,也可以修改已有视图。通常在应用中,我们有两种应用形式的2D图形应用。

a.把图形或者动画图形内嵌在一个View对象中,这样,我们只需要定义内嵌的方式就行,而实际的操作处理交由系统处理View图层完成。

b.在画布上绘制图形,这等同于我们在实际生活中的画图纸上作画。这里我们需要在合适的onDraw()方法中进行操作(如果是静态单线程的我们也可以在View类的该方法中完成)。这种绘制如果不停的刷新画布,则可以进行动画绘制。


应用a,通常是绘制简单图形,并且图形不会动态的变化。例如,一个静态的图形或者是事先定义好的动画(如list-animation)。

应用b,当应用需要不停的重绘。例如视频游戏。这种重绘刷新操作有以下两种方法完成:

1.在UI主线程中,即创建自定义View组件的地方,调用invalidate()操作onDraw()回调。

2.在主线程之外的小线程中,这个小线程是管理SurfaceView的地方,这里我们不需要调用invalidate(),画布会自动进行刷新重绘。

详细介绍在后面。

Bitmap b = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);Canvas c = new Canvas(b);

绘制一个图形,需要四个基本组件:一个承载像素的Bitmap(位图),一个Canvas工具类,Canvase类中定义了所有我们需要的绘制函数,一个原始图形(例如Rect,Path,text,Bitmap)和一支画笔(Paint)定义绘制的颜色和样式。


在应用中,Canvas类见到最多的是在View控件的onDraw(Canvas canvas)函数中,onDraw()是 一个回调函数,由系统进行调用,因此我们只需要在方法中进行绘制操作即可,至于具体如何调用,我们不需要管。

如果我们需要自行创建一个Canvas对象,则我们还需要定义一个Bitmap类,事实上图形的呈现是在Bitmap上完成的,因为在计算机图形学中,图形在内存中的保存和最终在屏幕上的显示与像素密切相关。而Canvas仅仅只是一个定义了各种画图方法的工具类。


这样之后,所有在画布c上的绘制操作事实上都显示在位图b中。事实上,这种操作在应用中往往只是一个过渡,最终图形依然需要依托View.onDraw()绘制到View控件上。使用的方法是:

Canvas.drawBitmap(Bitmap,...);

这样操作的一个好处是因为位图b可以是任何图形,包括res/中的jpg图形等。View.onDraw(Canvas canvas)中使用的是空白画布,而这里的画布就可以是任何样式的了。


在View控件中绘图

如果应用不要求大量的图形操作或者帧速率(例如象棋游戏,贪吃蛇或者其他慢速动画应用,GlowPadView和MultiWaveView也是如此),那么我们可以考虑创建一个自定义View视图控件并绘图。这样做的方便之处在于Android系统框架提供了预定义的Canvas对象。

继承View类或其子类,然后在重写onDraw(Canvas c)函数绘制我们自己的图形。

Android框架会在合适的时候回调onDraw()。每次应用准备好了重绘时,我们必须让View调用invalidate()。这个函数会要求Android框架回调onDraw()方法,这样就会进行一次画图操作。

注意,我们也可以在其他小线程中要求Android框架回调onDraw()方法,使用的函数是postInvalidate()。


在SurfaceView上绘图

SurfaceView是View类的子类。它拥有一块专门的区域进行绘图操作。设计这个类的目的是在应用主线程之外进行专门的绘制操作,这样就不必等待主线程准备好的时候才进行绘图操作。

继承SurfaceView类,并且同时实现SurfaceHolder.Callback,这个接口是创建,改变和销毁绘图Surface(这是底层真正承载图形的地方)的地方。在SurfaceView类中是我们创建第二线程的地方,这里我们实现所有的绘图程序。

通过SurfaceHolder而不是直接操作Surface对象(这里应用了代理模式)。所以初始化了SurfaceView时,调用getHolder()获取SurfaceHolder。具体的关于SurfaceView的使用这里不作详述。


很明显的,SurfaceView是继承自View,但它拥有第二线程,因此这里是进行长耗时的绘图操作的地方,补充View控件的短耗时操作。



有关绘图操作,我们平时见到的除了Canvas,Bitmap等类外,还有一个类非常常见,那就是Drawable类。这个类以及它的诸多子类有什么用处呢?

先来看看Drawable类的介绍

"A Drawable is a general abstraction for 'something that can be drawn'. Most often you will deal with Drawable as the type of resource retrieved for drawing things to the screen;the Drawable class provides a generic API for dealing with an underlying visual resource that may take a variety of forms. Unlike a View, a Drawable does not have any facility to receive events or otherwise interact with the user. "——可以被绘制的通用抽象概念。通常Drawable对象作为绘制到屏幕上的资源处理;Drawable类提供了通用的API处理可见资源。不同于View类,它没有提供供用户操作的接口。

从这里可知,Drawable对象就是我们绘制到屏幕上的东西。如果我们把Canvas中的绘制看做是一笔一画的话,那么Drawable可以看做是一笔一画完成之后的一个完整图画对象,它时一笔一画的一个集成。


一个image.jpg是一个Drawable,一个短时动态的动画也可以看做一个完整的Drawable。Drawable的诸多子类预定义了许多可用的完整图画。


因此,Drawable依托View控件的onDraw(Canvas c)进行绘制也就不足为奇了:

android:src/background="@drawable/image"

或者

void onDraw(Canvas canvas){

        drawable.draw(canvas);

}


本文可以看成是所有2D图形如何绘制到屏幕上的总结,至于StateDrawable还有Matrix等等的具体应用将在后面进行介绍。