Handling Touch Events

Users can interact with your program by touching the screen.

[Unlike Jeroos and LightBots, this page is oriented towards programming with more general Actors and Worlds, which can be a lot more engaging when you provide ways for a person to interact with the program as it runs.]

Creating interactive programs involves handling user interactions, where a person "touches" the screen (on an Android device) or moves a mouse. Greenfoot4Sofia uses an Android-based interaction model--all of the interactions described in this section can be performed by a person using a finger on the screen of an Android device. Since Greenfoot4Sofia programs can also run on your desktop computer, there you can use the mouse or keyboard to perform the same kinds of actions.

One of the most basic interaction mechanisms you can use in a Greenfoot4Sofia program is simple directional input. Android provides support for a Directional Pad (or D-pad), and a few (rare) Android devices actually have a physical D-pad attached. In Sofia, the D-pad is presented as a semi-transparent circular overlay in the lower left of the screen that you can press with your thumb or finger.

The D-pad (or thumbstick) allows you to use your finger to touch on the north, south, east, or west sides of a thumb control on-screen. On your PC's keyboard, you can use the arrow keys, or the W/A/S/D keys, which Greenfoot4Sofia treats the same way as the on-screen D-pad on an Android device.

The D-pad can be used for 4-way (or 8-way) directional control. You can also touch right in the center of the D-pad, which you may use as a trigger mechanism or for other purposes.

Sofia uses an event handling strategy for responding to user input. If you wish for one of your objects (an actor or the world) to respond to user input, all you have to do is add an event handling method to the corresponding class. An event handling method is a method with a special name that is called automatically when an event occurs. You do not write any code yourself to call these methods--instead, think of these methods as being "directly wired" to the D-pad. They are automatically called by the D-pad when a finger presses on the pad.

Add any of the following methods in any actor or world class to respond to D-pad actions:

DirectionMethod NameOn KeyboardArrow Keys
up public void dpadNorthIsDown() wup-arrow
up/right public void dpadNortheastIsDown() w + dup-arrow + right-arrow
right public void dpadEastIsDown() dright-arrow
down/right public void dpadSoutheastIsDown() s + ddown-arrow + right-arrow
down public void dpadSouthIsDown() sdown-arrow
down/left public void dpadSouthwestIsDown() s + adown-arrow + left-arrow
left public void dpadWestIsDown() aleft-arrow
up/left public void dpadNorthwestIsDown() w + aup-arrow + left-arrow
center public void dpadCenterIsDown() space bar

In your actor (or world) class, you need only write the actions you want to carry out in the body of the corresponding event handling method, and that method will be called automatically by the D-pad when the D-pad is pressed.

While the D-pad is a natural approach to use when you need simple directional input, as you develop more sophisticated programs you may want to incorporate other types of user interactions. On an Android screen, a person can touch with his or her finger anywhere--on a specific actor or on the background. To handle these kinds of interactions, Sofia supports a number of additional event handling methods that you can add to your classes.

First, note that you can add "touch" interactivity to any of your classes--both world classes and actors. Methods for handling touches on specific objects have names that begin with "onTouch...", "onTap...", etc.

Second, note that you can write methods that receive notification when the user "touches" a specific actor (or the world/background), or receive notication when a touch happens "anywhere"--that is, on anything at all rather than on a specific object. Methods for handling touches regardless of what object is underneath the touch location have names that begin with "onScreenTouch...", "onScreenTap...", etc.

The finger/touch event handling methods you can add to any actor or world class are:

Method NameCalled When ...
public void onTap() When a finger tap (press and release) is completed on an object.
public void onDoubleTap() When two finger taps are completed on an object in short succession.
public void onTouchDown() When a finger press occurs on an object (called for taps, as well as drag-style actions).
public void onTouchMove() When a finger movement occurs on an object (necessarily after the finger has been pressed on the object, and before the finger is released).
public void onTouchUp() When a finger on an object is released from the screen (called for taps, as well as for the end of drag-style actions).
public void onScreenTap() When a finger tap (press and release) is completed anywhere on the screen.
public void onScreenDoubleTap() When two finger taps are completed anywhere on the screen in short succession.
public void onScreenTouchDown() When a finger press occurs anywhere on the screen (called for taps, as well as drag-style actions).
public void onScreenTouchMove() When a finger movement occurs anywhere on the screen (necessarily after the finger has been pressed on the object, and before the finger is released).
public void onScreenTouchUp() When a finger on an object is released from the screen (called for taps, as well as for the end of drag-style actions).

These basic methods cover all of the touch events that you can receive in an actor or world class. All of the touch methods described above can be written without parameters. Such methods are called automatically whenever the corresponding touch action occurs.

Sometimes, however, it isn't enough to know that something was "touched"--you need to know where the touch occurred. All of the touch methods described can also be written with parameters that receive the location where the touch occurred if you wish.

Suppose you are interested in writing a method that is invoked whenever the user taps anywhere on the screen. Then you could use either of the following parameter profiles for your event handling method:

public void onScreenTap()
{
    // Called to indicate the tap occurred.
    // This method has no parameters, so there is no information about
    // *where* the tap happened.
}

public void onScreenTap(int x, int y)
{
    // Called to indicate the tap occurred at grid location (x, y).
    // Useful if you need to know the cell coordinates where the tap occurred.
}

The vast majority of student programs will use one of the two forms shown above (both parameter alternatives work with every touch-based event handling method). In some situations, however, you may want more exact location information, or may wish to have the location information presented in a different way. For more advanced users, all of the event handling methods support all of the following parameter styles, in addition to the two shown above:

public void onScreenTap(Point p)
{
    // Called to indicate the tap occurred at grid location (x, y).
    // This is exactly the same as the (int x, int y) version, except
    // that it receives the integer grid coordinates in the form of an
    // android.graphics.Point object.
}

public void onScreenTap(float x, float y)
{
    // Called to indicate the tap occurred at grid location (x, y), but
    // with greater accuracy.  The location (2.0, 3.0) is the exact
    // center of the grid cell at (2, 3), but this method gives you the
    // exact location of the tap, such as (1.765, 3.225) (which would
    // be in the lower left portion of the cell in this example).
}

public void onScreenTap(PointF point)
{
    // Called to indicate the tap occurred at grid location (x, y).
    // This is exaclt the same as the (float x, float y) version, except
    // that it receives the float grid coordinates in the form of
    // an android.graphics.PointF object.
}

Sofia is happy to use any of these parameter choices--it is up to you to decide which form you wish to receive the location information in, if at all, when you write your event handling code. Use the parameter declaration that best fits your own needs in the code you write.