Create a new project to explore the topic of drawing with Canvas
. We will reuse what we just learned, and this time we will also draw to the Bitmap
.
Create a new project and call it Canvas Demo
. This time, be sure to choose the Empty Activity option 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 an app to play around with. We will not be returning to it.
Notice that Android Studio has not created an XML layout, and furthermore it has not added a line of code in MainActivity.java
that calls setContentView
. If you ran the app at this stage, you would get a blank black screen.
In addition, we are using the Vanilla version of Activity
class, and MainActivity
therefore extends Activity
instead of AppCompatActivity
, as we have been using previously.
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 in Android Studio 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 it would be much quicker to place the mouse pointer on each error in turn and 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. It is worth exploring the Bitmap
class initialization, as it is not straightforward.
Bitmaps, more typically in graphics-based apps and games, are used to represent objects such as different brushes to paint with, the player, backgrounds, game objects, and so on. Here we are simply using it to draw upon. In the next project, we will use bitmaps to represent the subject of our drawing, not just the surface to draw upon.
The method that needs explaining is the createBitmap
method. The parameters from left to right are as follows:
Bitmaps can be configured in several different ways. The ARGB_8888
configuration means that each pixel is represented by 4 bytes of memory.
There are a few 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 both the entirety of this chapter and the Snake game in the penultimate chapter of the book.
Now we can do the actual drawing.
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 that 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 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.
The Color
class, unsurprisingly, helps us manipulate and represent color. The argb
method used previously returns a color constructed using the alpha (opacity/transparency), red, green, and 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—that the colors mixed are intensities of light and are quite different to what happens when we mix paint, for example.
To devise an argb value and explore this model further, 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 values used to clear the drawing surface were 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
mean 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
, where 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 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 when you run it. We can see an 800 by 800-pixel drawing. In the next chapter, we will use more advanced techniques to utilize the entire screen, and we will also learn about threads to make the graphics move in real time:
It would help to understand the result of the coordinates we use in our Canvas drawing methods if you better understood the Android coordinate system.
3.137.199.182