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:
- line 57: canvas = mSurfaceHolder.lockCanvas()
I get the surface where I draw - lines 60-81
I draw the background and the circles - line 82: mSurfaceHolder.unlockCanvasAndPost(canvas)
the drawing is completed and the changes to the surface are shown
You can download the example here.
Leave a Reply