Oct 202012
 
Article Android

Drawing on a View

The android libraries include the Canvas class. This class implements many methods métodos (drawLine, drawRect, drawCircle,…) to draw graphics on the screen. The easiest way of drawing graphics in an android device is drawing them on the Canvas associated to a View.

This is true for apps that need to draw static graphics or slow-movement graphics. But for some games and other kind of applications where graphics performance is key, android offers a specialized class named SurfaceView. We will comment this class later in this post.

Every View object in an application has an associated Canvas object. This Canvas object is passed as an argument to the onDraw calls made by the system when the View needs to be displayed. Therefore, drawing on the Canvas can be done by overriding the onDraw method. The code below is a simple example:

Inside the onCreate method of the TestGraphics main program, a ‘paint’ object is initialized with the desired configuration of colour, line width, etc. Next, in line 24 the paint object is associated to an instance of a class ‘Panel’ that extends from class View. The Panel class is defined later, starting at line 27.

In the implementation of the Panel class, the onDraw method that overrides the default draws a circle, a line and a text with the canvas dimensions. When this application is run in the emulator, the resulting screen is:

If we want to draw again in the Canvas while the application is running, we need to call the View method “invalidate()”. This results in the system making another call to the View’s onDraw method.

Note: To request a refresh of the graphics from a different thread, instead of a call to invalidate() we need to make a call to postInvalidate().

 

 

Drawing on a SurfaceView

 

SurfaceView is a subclass of the View class, optimized for good performance of graphical operations. Instances of this class must be handled from a secondary execution thread, to avoid the operations performed by them having to wait for the regular processing of the View hierarchy performed by the system.

We start creating a subclass of the SurfaceView class named 'MySurface', implementing the SurfaceHolder.Callback interface. This interface defines three methods “surfaceCreated”, “surfaceDestroyed” and “surfaceChanged”. The system callss these methods every time the drawing surface is created, destroyed of modified in some way.

Inside the constructor of MySurface, a call needs to be made to SurfaceHolder.addCallback(this) to indicate that this class will process the surface creation, destruction and modification events.

As we can see in the above code, a class ‘DrawThread’ (extending from class Thread) is also required to perform the graphical operations on the SurfaceView. El código fuente de esta clase se incluye normalmente en el interior de la clase SurfaceView. Being a Thread, the execution of this this class is independent and runs in parallel with other processes that the application might be executing.

The thread is created with a call to “new DrawThread()” from inside the constructor of MySurface. The execution of the thread starts with the call to  thread.start() done in the  “surfaceCreated” method.

Inside DrawThread, the drawing area is accessed through an instance of SurfaceHolder obtained with a call to getHolder() in the MySurface constructor.

To start drawing, the methods get a reference to the canvas with a call to the SurfaceHolder.lockCanvas() method. Using this reference the desired drawing methods (drawLine, drawText,…) are invoked. Finally, the result is displayed with a call to the method unlockCanvasAndPost():

 

Normally, the drawing starts initializing the whole area with a background color with a call to drawColor(), or with a background image with a call to drawBitmap().

The complete code of the MySurface class is:

 

 Posted by at 7:27 pm

 Leave a Reply

(required)

(required)