Creating a new project
Create a new project in the same way as we did for Sub Hunter but call it Canvas Demo
. If you have the Sub Hunter project open now you can select File | New Project and create a project using the following options.
As we did before, be sure the Empty Activity option is selected on the Add an Activity to Mobile screen before clicking Next. Also, be sure to uncheck Generate Layout File and Backwards Compatibility (AppCompat). Don't worry about naming the Activity this is just a mini app to play around with we will not be returning to it.
Note
The complete code for this mini-app can be found in the download bundle in the Chapter 5/Canvas Demo
folder.
Coding the Canvas demo app
To get started, add the highlighted code, after the class declaration but before the onCreate
method. This is what the code will look like after this step.
public class MainActivity extends Activity { // Here are all the objects(instances) // of classes that we need to do some drawing ImageView myImageView; Bitmap myBlankBitmap; Canvas myCanvas; Paint myPaint; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } }
Notice that each of the four new classes is underlined in red. This is because we need to add the appropriate import
statements. You could copy them from the first page of this chapter but much quicker would be to place the mouse pointer on each error in turn then hold the ALT key and tap the Enter key. If prompted, from the pop-up options, select Import class.
Once you have done this for each of ImageView
, Bitmap
, Canvas
, and Paint
, all the errors will be gone, and the relevant import
statements will have been added to the top of the code.
Now that we have declared instances of the required classes we can initialize them. Add the following code to the onCreate
method after the call to super.onCreate…
as shown in this next code.
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Initialize all the objects ready for drawing // We will do this inside the onCreate method int widthInPixels = 800; int heightInPixels = 600; // Create a new Bitmap myBlankBitmap = Bitmap.createBitmap(widthInPixels, heightInPixels, Bitmap.Config.ARGB_8888); // Initialize the Canvas and associate it // with the Bitmap to draw on myCanvas = new Canvas(myBlankBitmap); // Initialize the ImageView and the Paint myImageView = new ImageView(this); myPaint = new Paint(); }
This code is the same as we saw when we were discussing Canvas
in theory. Even though we are not going any deeper about classes now it might be worth exploring the Bitmap
class initialization.
Exploring the Bitmap initialization
Bitmaps, more typically in games are used to represent game objects like the player, backgrounds, bombs, etc. Here we are simply using it to draw upon. In later projects, we will use all sorts of bitmaps to represent everything from spaceships to enemies.
The method that needs explaining is the createBitmap
method. The parameters from left to right are:
- The width (in pixels),
- The Height (in pixels)
- The bitmap configuration
Bitmaps can be configured in a number of different ways. The ARGB_8888 configuration means that each pixel is represented by 4 bytes of memory.
Note
There are a number of bitmap formats that Android can use. This one is perfect for a good range of color and will ensure that the bitmaps we use and the color we request will be drawn as intended. There are higher and lower configurations but ARGB_8888 is perfect for the entirety of this book.
Now we can do the actual drawing.
Drawing on the screen
Add this next highlighted code after the initialization of myPaint
and inside the closing curly brace of the onCreate
method.
myPaint = new Paint(); // Draw on the Bitmap // Wipe the Bitmap with a blue color myCanvas.drawColor(Color.argb(255, 0, 0, 255)); // Re-size the text myPaint.setTextSize(100); // Change the paint to white myPaint.setColor(Color.argb(255, 255, 255, 255)); // Draw some text myCanvas.drawText("Hello World!",100, 100, myPaint); // Change the paint to yellow myPaint.setColor(Color.argb(255, 212, 207, 62)); // Draw a circle myCanvas.drawCircle(400, 250, 100, myPaint); }
The previous code uses myCanvas.drawColor
to fill the screen with color.
The myPaint.setTextSize
defines the size of the text that will be drawn next. The myPaint.setColor
method determines what color any future drawing will be. The myCanvas.drawText
actually draws the text to the screen.
Analyze the arguments passed into drawText
and we can see that the text will say "Hello World!" and it will be drawn 100 pixels from the left and 100 pixels from the top of our Bitmap
(myBitmap
).
Next, we use setColor
again to change the color that will be used for drawing. Finally, we use the drawCircle
method to draw a circle that is at 400 pixels from the left and 100 pixels from the top. The circle will have a radius of 100 pixels.
I reserved explaining the Color.argb
method until now.
Explaining Color.argb
The Color class, unsurprisingly helps us manipulate and represent colors. The argb
method used previously returns a color constructed using the alpha (opacity/transparency), red, green, blue model. This model uses values ranging from zero(no color) to 255(full color) for each element. It is important to note although on reflection it might seem obvious, the colors mixed are intensities of light and are quite different to what happens when we mix paint for example.
Tip
To devise an argb value and explore this model further take a look at this handy website. https://www.rapidtables.com/web/color/RGB_Color.html. The site helps you pick the RGB values you can then experiment with the alpha values.
The value used to clear the drawing surface was 255, 0, 0, 255
. These values mean full opacity (solid color), no red, no green and full blue. This makes a blue color.
The next call to the argb
method is in the first call to setColor
where we are setting the required color for the text. The values 255, 255, 255, 255
means full opacity, full red, full green, full blue. When you combine light with these values you get white.
The final call to argb
is in the final call to setColor
when we are setting the color to draw the circle. 255, 21, 207, 62
makes a sun-yellow color.
The last step before we can run the code is to add the call to the setContentView
method which places passes our ImageView
(myImageView
) as the view to be set as the content for this app. Here are the final lines of code highlighted after the code we have already added but before the closing curly brace of onCreate
.
// Associate the drawn upon Bitmap with the ImageView myImageView.setImageBitmap(myBlankBitmap); // Tell Android to set our drawing // as the view for this app // via the ImageView setContentView(myImageView);
Finally, we tell the Activity
class to use myImageView
by calling setContentView
.
This is what the Canvas
demo looks like with the emulator rotated to portrait. We can see an 800 by 800-pixel drawing. In all our games, we will see how we can utilize the entire screen.
In this example, we just draw to a Bitmap but in the Sub Hunter game, we want to draw to the entire screen, so a discussion of the Android coordinate system will be useful.