Drawable

The previous project drew a circle, a square, a point, and a path that formed a triangle. The triangle was the hardest because it was not built-in. Let’s package the triangle as a Drawable object that can be drawn onto a Canvas as easily as a circle or a square.

Class Canvas has the methods drawCircle and drawRect. But we will not draw the triangle by adding a drawTriangle method to class Canvas. We will make no change to this class. Instead, we will invent a drawable object called a TriangleDrawable. A Canvas already has the ability to draw any drawable object.

And now that the triangle code has been packaged, we’ll make it equilateral. This will require a bit of trigonometry. We’ll also draw some text.

Class CortlandtView is named after Cortlandt Homes in The Fountainhead 4:9. “The entire plan was a composition in triangles.”

Source code in Drawable.zip

  1. MainActivity.java. The Activity object creates a CortlandtView object.
  2. CortlandtView.java. The CortlandtView object creates three TriangleDrawable objects and draws them on the Canvas.
  3. TriangleDrawable.java. Class TriangleDrawable is a subclass of class Drawable. It has a constructor and a draw method. The first three arguments of the constructor are float by analogy with the arguments of drawCircle and drawRect, and because the arguments of moveTo and lineTo are float.
  4. activity_main.xml. Unused and ignored.
  5. AndroidManifest.xml
  6. build.gradle (Module: app)

Create the project

The previous project created a subclass of the existing class View (i.e., android.view.View). This project’s class CortlandtView is a subclass of android.view.View, and class TriangleDrawable is a subclass of android.graphics.drawable.Drawable.

Create class TriangleDrawable

In the Android Studio project view, select the folder edu.nyu.scps.drawable. This folder already contains MainActivity.java.
File → New → Java Class
Create New Class
Name: TriangleDrawable
Kind: Class (as opposed to Interface, etc.)
OK

The new file TriangleDrawable.java already contains

public class TriangleDrawable {
}
Edit it to
public class TriangleDrawable extends Drawable {
}

The superclass Drawable is an abstract class: it has four missing methods. The simplest way to implement these methods is to pull down
Code → Implement Methods…
Select Methods to Implement
Press OK to implement the four methods draw, setAlpha, setColorFilter, and getOpacity.

Create class CortlandtView

In the Android Studio project view, select the folder edu.nyu.scps.drawable.
File → New… → UI Component → Custom View
Creates a new custom view that extends android.view.View and exposes custom attributes.
Package Name: edu.nyu.scps.drawable
View Class: CortlandtView
Finish

Things to try

  1. Our drawable displayed of a triangle and a piece of text. Could you make a drawable that dispays a triangle and a circle? How about a rocket ship consisting of a triangular nose cone, a rectangular body, and two fins?

  2. We just created a Drawable in a .java file. Now let’s create a Drawable in an XML file. It will be a simple Drawable that consists of a red circle. See Shape Drawable.
    1. In the Android Studio project view, Go to res/drawable and create a new file named circle.xml. Control-click on res/drawable and select
      New → Drawable resource file
      Choose Destination Directory
      …/app/src/main/res/drawble
      OK

      New Drawable Resource File
      File name: circle.xml
      root element: shape
      OK
    2. The circle.xml file should contain the following. The solid color is opaque red (αrgb).
      <?xml version="1.0" encoding="utf-8"?>
      
      <shape xmlns:android="http://schemas.android.com/apk/res/android"
      	android:shape="oval" >
      
      	<solid android:color="#FFFF0000" />
      </shape>
      
    3. In the onDraw method of CortlandtView, change the type of radius to int.
      		//Get the contents of the circle.xml file.
      		Resources resources = getResources();
      		Drawable circle = resources.getDrawable(R.drawable.circle);
      		circle.setBounds(-radius, -radius, radius, radius);
      
      		circle.draw(canvas);