Handling the multi-touch in a surface view

In the previous post Handling the multi-touch in a view I’ve used a class that extends a View to show the circles where the screen is touched, here I display the same example but using a SurfaceView.

The SurfaceView is more suited than the View when the updates are frequent beacause it uses a separate thread from the UI thread.
The files in this example and in that one in Handling the multi-touch in a view are equal or almost except TouchView.java replaced by TouchSurfaceView.java then I don’t write here these files and their comments and screenshot.

TouchSurfaceView.java

package eu.lucazanini.circlesurfaceview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class TouchSurfaceView extends SurfaceView implements
	SurfaceHolder.Callback {

    private final static String TAG = TouchSurfaceView.class.getName();
    private Circle circleOne, circleTwo;;
    private Thread mDrawingThread;
    private final SurfaceHolder mSurfaceHolder;
    private volatile boolean running = false;

    public TouchSurfaceView(Context context, AttributeSet attrs) {
	super(context, attrs);

	circleOne = new Circle();
	circleTwo = new Circle();

	mSurfaceHolder = getHolder();
	mSurfaceHolder.addCallback(this);
    }

    public void setCircleOne(float x, float y, int action) {
	circleOne.setX(x);
	circleOne.setY(y);
	circleOne.setAction(action);
    }

    public void setCircleTwo(float x, float y, int action) {
	circleTwo.setX(x);
	circleTwo.setY(y);
	circleTwo.setAction(action);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
	    int height) {
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
	mDrawingThread = new Thread(new Runnable() {

	    @Override
	    public void run() {
		running = true;
		while (running) {
		    if (mSurfaceHolder.getSurface().isValid()) {
			Canvas canvas = mSurfaceHolder.lockCanvas();
			if (canvas != null) {

			    Paint paint = new Paint();

			    // draw white canvas
			    paint.setStyle(Paint.Style.FILL);
			    paint.setColor(Color.WHITE);
			    canvas.drawRect(0, 0, getWidth(), getHeight(),
				    paint);

			    // draw the circles
			    paint.setAntiAlias(true);
			    if (circleOne != null
				    && circleOne.getAction() != -1) {
				paint.setColor(Color.RED);
				canvas.drawCircle(circleOne.getX(),
					circleOne.getY(), 100, paint);
			    }
			    if (circleTwo != null
				    && circleTwo.getAction() != -1) {
				paint.setColor(Color.GREEN);
				canvas.drawCircle(circleTwo.getX(),
					circleTwo.getY(), 100, paint);
			    }
			    mSurfaceHolder.unlockCanvasAndPost(canvas);
			}
		    }
		}
	    }
	});
	running = true;
	mDrawingThread.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
	running = false;
	while (true) {
	    try {
		mDrawingThread.join();
		return;
	    } catch (Exception e) {
		Log.e(TAG, e.toString());
	    }
	}
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
	int widthMode = MeasureSpec.getMode(widthMeasureSpec);
	int widthSize = MeasureSpec.getSize(widthMeasureSpec);
	int heightMode = MeasureSpec.getMode(heightMeasureSpec);
	int heightSize = MeasureSpec.getSize(heightMeasureSpec);

	setMeasuredDimension(widthSize, heightSize);
    }

}

This class handles the drawing of the background and circles in the method surfaceCreated().
Note this class implements the interface SurfaceHolder.Callback to receive information about changes to the surface.
In the constructor TouchSurfaceView at the lines 27 and 28 I initialize SurfaceHolder and I implement the Callback.
In the method surfaceCreated() and inside the thread mDrawingThread I perfomr the following steps:

  1. line 57: canvas = mSurfaceHolder.lockCanvas()
    I get the surface where I draw
  2. lines 60-81
    I draw the background and the circles
  3. line 82: mSurfaceHolder.unlockCanvasAndPost(canvas)
    the drawing is completed and the changes to the surface are shown

You can download the example here.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.