Learn OpenGL ES

Learn how to develop mobile graphics using OpenGL ES 2

Listening to Android Touch Events, and Acting on Them

Basic blending (additive blending of RGB cubes).
Basic blending.

We started listening to touch events in Android Lesson Five: An Introduction to Blending, and in that lesson, we listened to touch events and used them to change our OpenGL state.

To listen to touch events, you first need to subclass GLSurfaceView and create your own custom view. In that view, you create a default constructor that calls the superclass, create a new method to take in a specific renderer (LessonFiveRenderer in this case) instead of the generic interface, and override onTouchEvent(). We pass in a concrete renderer class, because we will be calling specific methods on that class in the onTouchEvent() method.

On Android, the OpenGL rendering is done in a separate thread, so we’ll also look at how we can safely dispatch these calls from the main UI thread that is listening to the touch events, over to the separate renderer thread.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class LessonFiveGLSurfaceView extends GLSurfaceView
{
    private LessonFiveRenderer mRenderer;

    public LessonFiveGLSurfaceView(Context context)
    {
        super(context);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        if (event != null)
        {
            if (event.getAction() == MotionEvent.ACTION_DOWN)
            {
                if (mRenderer != null)
                {
                    // Ensure we call switchMode() on the OpenGL thread.
                    // queueEvent() is a method of GLSurfaceView that will do this for us.
                    queueEvent(new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            mRenderer.switchMode();
                        }
                    });

                    return true;
                }
            }
        }

        return super.onTouchEvent(event);
    }

    // Hides superclass method.
    public void setRenderer(LessonFiveRenderer renderer)
    {
        mRenderer = renderer;
        super.setRenderer(renderer);
    }
}

And the implementation of switchMode() in LessonFiveRenderer:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public void switchMode()
{
    mBlending = !mBlending;

    if (mBlending)
    {
        // No culling of back faces
        GLES20.glDisable(GLES20.GL_CULL_FACE);

        // No depth testing
        GLES20.glDisable(GLES20.GL_DEPTH_TEST);

        // Enable blending
        GLES20.glEnable(GLES20.GL_BLEND);
        GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);
    }
    else
    {
        // Cull back faces
        GLES20.glEnable(GLES20.GL_CULL_FACE);

        // Enable depth testing
        GLES20.glEnable(GLES20.GL_DEPTH_TEST);

        // Disable blending
        GLES20.glDisable(GLES20.GL_BLEND);
    }
}

Let’s look a little bit more closely at LessonFiveGLSurfaceView::onTouchEvent(). Something important to remember is that touch events run on the UI thread, while GLSurfaceView creates the OpenGL ES context in a separate thread, which means that our renderer’s callbacks also run in a separate thread. This is an important point to remember, because we can’t call OpenGL from another thread and just expect things to work.

Thankfully, the guys that wrote GLSurfaceView also thought of this, and provided a queueEvent() method that you can use to call stuff on the OpenGL thread. So, when we want to turn blending on and off by tapping the screen, we make sure that we’re calling the OpenGL stuff on the right thread by using queueEvent() in the UI thread.

Further exercises

How would you listen to keyboard events, or other system events, and show an update in the OpenGL context?

2 comments and 1 pingback to “Listening to Android Touch Events, and Acting on Them”

  1. Pingback: Android Lesson Five: An Introduction to Blending | Learn OpenGL ES

  2. salu

    Hai,
    I want to know the object coordinates of the cube.This I am using.But giving Null Exception.How can i rectify it???
    public void handleActionDown(int eventX, int eventY)
    {
    if (eventX >= (x – bitmap[numFaces].getWidth()/2) && (eventX = (y – bitmap[numFaces].getHeight()/2) && (y <= (y + bitmap[numFaces].getHeight()/2 )))
    {
    Log.d("Mytag", "Coords: x=" + eventX + ",y=" + eventY);

    setTouched(true);
    } else
    {
    setTouched(false);
    }
    }
    else
    {
    setTouched(false);
    }

    // TODO Auto-generated method stub

    }

    On surface view it is,
    public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN)
    {

    mcube1.handleActionDown((int)event.getX(), (int)event.getY());
    Log.d("Mytag", "Coords: x=" + event.getX() + ",y=" + event.getY());

    }
    if (event.getAction() == MotionEvent.ACTION_MOVE) {

    if (mcube1.isTouched()) {

    mcube1.setX((int)event.getX());
    mcube1.setY((int)event.getY());
    Log.d("works", "Coords: x=" + event.getX() + ",y=" + event.getY());
    }
    } if (event.getAction() == MotionEvent.ACTION_UP) {

    if (mcube1.isTouched())
    {

    mcube1.setTouched(false);
    Log.d("works", "Coords: x=" + event.getX() + ",y=" + event.getY());
    }
    }
    return true;

  3. štěty

    How can I find out if the user clicked on a position, such as in the lower right corner of the screen. I know I can do in the game.
    Alternatively, could you show me a tutorial on buttons.
    Thank you for your response.

Comments are closed. This site is kept as a historical archive.