首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > 移动开发 >

Canvas and Drawables(1)翻译

2013-04-02 
Canvas and Drawables(一)翻译Canvas and DrawablesAndroid Framework层的API为用户提供了2D绘画的API,使

Canvas and Drawables(一)翻译

Canvas and Drawables

Android Framework层的API为用户提供了2D绘画的API,使得用户可以在画布上绘制自定义的图形,或者根据用户自己的审美和感觉进行修改现有的View对象。当想要绘制2D图形的时候,您可能使用以下一两种方式:

A.  在Layout中的View对象时行绘制图形或者动画。使用这种方式绘制,您绘制的图形是由系统绘制view图层来进行绘制的—您只需要简单的在view中绘制图形即可。

B.  直接在画布上绘制图形。使用这种方式,您需要手动的调用响应类的onDraw()方法(将图像传递给Canvas),或者调用Canvas的draw…()方法(比如 drawPicture())。使用这种方法,你还可以控制任何动画。

方法A,在View对象上绘制,如果您想要绘制简单的图形或者不需要定期变化且不属于密集型游戏,方法A将是最好的选择。比如,假如你想要绘制一个静态的图形或者动画,您应该在View上绘制图形。阅读Drawables部分内容获取更多信息。

方法B,在画布上绘制,当您需要定期重绘的话,这会是更好的选择。比如视频游戏应该在Canvas上绘制。然而,有更多的方法可以完成绘制:

               在于UI Activity相同的线程中,当在Layout中创建自定义View的时候,要调用invalidate()方法,并且处理onDraw()方法的回调。

               如果是一个单独的线程,管理着SurfaceView对象,并且使用线程来执行把图形绘制到Canvas对象上的任务(不需要请求invalidate()方法)。

Draw with a Canvas

当您正在进行专业的绘图或者想要控制图形的动画的时候,您应该在画布上绘制来完成。Canvas作为一个虚拟的绘图接口存在,实际的图像是绘制在Canvas上的,Canvas持有所有的”draw”的方法。通过Canvas,您绘制的图形将会在基本的位图之上展现在窗口上。

在onDraw()回调方法的绘制事件中,会提供一个Canvas对象,并且只需要把要绘制的内容交给Canvas对象就可以了。在处理SurfaceView对象时,还可以从SurfaceHolder.lockCanvas()方法来获取一个Canvas对象。但是,如果需要创建一个新的Canvas对象,那么就必须在实际执行绘制处理的Canvas对象上定义Bitmap对象。对于Canvas对象来说,这个Bitmap对象是始终必须的,应该像以下示例这样建立一个新的Canvas对象:

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


 

现在您的Canvas对象将会被绘制在已经定义好的Bitmap对象上了。当在Canvas上绘制完毕之后,您可以通过调用Canvas.drawBitmap(Bitmap,…)方法来将这个Bitmap绘制在其他的Canvas对象上。使用通过View.onDraw()方法或者SurfaceHolder.lockCanvas()方法得到的Canvas对象来绘制最终的图形是被推荐的。(也就是用这两个方法参数中传入的Canvas进行绘制)

Canvas类有可以使用的自己的一组绘图方法,如drawBitmap(…)、drawRect(…)、drawText(…)等。还可以使用其他的有draw()方法类。例如,可能想要把某些Drawable对象放到Canvas对象上。Drawable类就有带有Canvas对象作为参数的draw()方法。

On a View

假如您的应用程序中不需要大量的图形处理和很高的帧频率(比如国际象棋,贪吃蛇游戏,或者其他慢动画程序),那么您应该考虑创建自定义View组件,并且通过View.onDraw()方法进行绘制。这种方式最方便的一点在于,android framework层将为您提供预定义的Canvas来让您直接在上边进行绘制。

首先,要继承View类或者View的子类,然后定义onDraw()这个回调方法。这个方法将会被android framework调用来绘制这个View对象本身。这也是通过Canvas对象来执行所有的图形绘制调用的地方,这个Canvas对象是由onDraw()回调方法传入的。

Android framework只会在必要的时候调用onDraw()方法。每次想要进行绘制的时候,必须要调用View对象的invalidate()方法来使得这个View对象失效。这表明您骁勇让View通过调用onDraw方法进行绘制(尽管不能保证每次调用invalidate方法后都会瞬间进行回调onDraw方法)。

注意:为了在一个线程中而不是主Activity的线程中发出一个失效请求,必须调用postInvalidate()。

有关继承View类的更多信息,请阅读创建定制化的组件(http://developer.android.com/guide/topics/ui/custom-components.html)

示例程序,请看Snake游戏,它在SDK示例代码文件:<your-sdk-directory>/samples/Snake/.。

On a SurfaceView

SurfaceView对象是一个特殊的View类的子类,它在View层次树内提供了一个专用的图形绘制平面。这个图形绘制表面的主要目的是给应用程序提供一个辅助线程,以便应用程序不需要等待完成对系统的View层次树的绘制。相反,引用SurfaceView对象的辅助线程能够按照自己的节奏,把自己绘制在Canvas对象上。

首先需要创建一个继承SurfaceView类的子类。该子类还应该实现SurfaceHolder.Callback类,它是一个能够通知底层Surface类所发生的信息的接口。如Surface的创建、变化或销毁等。这些事件对于了解什么时候能够开始绘制图形、是否需要基于新的表面属性来进行调整、以及什么时候终止图形绘制和杀死某些任务,是至关重要的。在SurfaceView子类的内部也是定义辅助线程类的好地方,它会执行所有的把图形绘制到Canvas对象上的处理。

不要直接处理Surface对象,应该通过SurfaceHolder对象来处理它。因此,在SurfaceView子类被初始化的时候,要通过调用getHolder()方法来获得SurfaceHolder对象。然后应该通过调用addCallback()方法,来通知SurfaceHolder对象,它所能够接收SurfaceHolder回调对象(SurfaceHolder.Callback),然后再重写SurfaceView子类内部的每个SurfaceHolder.CallBacke方法。

为了能够在辅助线程内把图形绘制到Surface对象的Canvas对象上,必须把SurfaceHondler对象和用lockCanvas()方法获取的Canvas对象传递给辅助线程。现在就能够用给定的SurfaceHolder对象和Canvas对象开始图形绘制工作了,一旦用该Canvas对象完成了图形绘制任务,就要调用unlockCanvasAndPost()方法,把绘图用Canvas对象传递给该方法。现在Surface对象就会离开绘制图形的Canvas对象。每次想要重新绘制图形时,都要执行这个锁定和解锁的过程。

注意:每个通过SurfaceHolder对象获取的Canvas对象,它之前的状态都会被保留。为了正确的处理该图形,必须重新绘制整个Surface对象。例如,能够清除之前用drawColor()方法填充在Canvas对象中的颜色,或者是用drawBitmap()方法设置的背景图片。否则,就会看到之前被执行的图形绘制的轨迹。

示例应用程序,请看Lunar Lander游戏,它在SDK的示例文件夹:<your-sdk-directory>/samples/LunarLander/。

热点排行