CIS 350 Software Engineering - Spring 2012

Android Programming Exercise #3

Introduction
In this exercise, you create an application that draws 2D shapes and allows the user to interact with them. When the user touches a shape, its color changes; when the user releases, the color changes back. The user can also drag the shape to another location in the screen. However, if the user drags a shape such that it overlaps another one, it will "snap" back to another location.

This exercise will focus on:


Step 1. Create a new Android project
Create an Android project in Eclipse. Give the project a meaningful name (something like "Shapes") and choose a meaningful Java package name (e.g. "edu.upenn.cis350").


Step 2. Set up the skeleton code
In class last week, you briefly saw how to create your own View class and how to use its onDraw method. Download ShapesView.java and add it to your project. Then modify main.xml so that it looks like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<edu.upenn.cis350.ShapesView 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:layout_weight="1"
 />
</LinearLayout>

Run the application in the emulator; you should see a red rectangle in the upper left corner, and a blue circle with a green shadow in the middle.

See Tuesday's lecture notes or "Canvas and Drawables" in the developer guide if you need help.


Step 3. Modify the custom View
In your ShapesView class, change the onDraw method so that it uses the Canvas to create a blue 50x50 square starting at coordinates (100, 100).

Feel free to play around with different methods in the Paint class to get different visual effects, or in the Canvas class.

Run your application again and make sure that the blue square (or whatever you created) appears in the View.


Step 4. Change the shape's color when touched
In your ShapesView class, implement the onTouchEvent method. This is the method that is automatically called by Android when the user interacts with the View. The signature of the method should be:

public boolean onTouchEvent(MotionEvent event)
The MotionEvent includes info about the type of event (the "action"), where it occurred, and when it occurred. Takke a look at the MotionEvent API to get more information about the different methods you need to use.

In your case, when the onTouchEvent receives a MotionEvent in which the "action" is MotionEvent.ACTION_DOWN, determine whether the location of the MotionEvent (i.e., its x/y coordinate) is within the bounds of the shape. If so, change the color of the shape you drew in Step 3 to yellow (or whatever you'd like). Note that in order to do this, you will have to modify your onDraw method so that the Paint color is variable, and your onTouchEvent method will need to call "invalidate();" in order to redraw the View.

When the onTouchEvent method detects a MotionEvent.ACTION_UP action, draw the shape again in its original color.

The onTouchEvent method should return true to indicate that your code handled it (i.e., the touch event was within the bounds of the rectangle), and false otherwise.

Run the application and see that you are correctly detecting whether the touch is within the bounds of the shape, and that you are correctly changing the color.


Step 5. Move the shape by dragging
Modify the onTouchEvent method so that, when the user touches within the bounds of the shape, you not only change the color, but also allow the user to "drag" the shape by detecting the new x/y coordinate of the MotionEvent and redrawing the shape at the appropriate location. When the user releases the shape, its color should go back to the original.

This part is tricky! Give yourself time to figure this out and ask for help if you need it.

Depending on how you implement this, you may find that the upper righthand corner of the shape "snaps" to the location of the touch. Fix this so that the user can drag it from any location within the bounds of the shape.

Note that because the emulator is so slow, the shape will lag behind the motion of the pointer; there's probably nothing you can do about that.


Step 6. Detect collisions between shapes
Now create another shape in the View, and allow the user to drag either of them (this will require lots of reworking of the onDraw and onTouchEvent methods). However, if the user drags one shape on top of another such that their bounds overlap, and then releases the shape, it "snaps" back to another location. That location can be anywhere in the View, but it would probably make more sense to either go back to where you originally started, or move it to another location that is next to, but not on top of, the other shape.

This will require lots of reworking of the onDraw and onTouchEvent methods, and you may want to consider create new classes to represent the shapes, and new methods to determine things like whether they're overlapping or which shape was clicked on.