Android Open Source - TestTouch Touch Surface View






From Project

Back to project page TestTouch.

License

The source code is released under:

Apache License

If you think the Android project TestTouch listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.evosysdev.testtouch;
/*from www . java  2s . c  o  m*/
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Paint.Style;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * Simple View to draw touches
 * 
 * @author tajobe
 * 
 */
public class TouchSurfaceView extends SurfaceView implements Runnable
{
    private static final int HISTORY_LEN, FRAME_TIME;
    private static final String TAG;
    
    static
    {
        HISTORY_LEN = 10000; // number of touch points to keep in history
        FRAME_TIME = 20; // length of time(ms) for a frame(between draws)
        TAG = "Drawing"; // log tag/thread name
    }
    
    private Touch[] touches; // array of recorded touches
    private int i, // current touch index
            colors[]; // array of colors for drawing
    private boolean showLegend; // should we display color legend
    private volatile boolean updated; // have there been touches since last draw
    
    private Thread drawing; // drawing thread
    private SurfaceHolder surface; // drawing surface
    private Paint paint; // paint to avoid constantly reallocating paint objects
    
    /**
     * Construct TouchView
     * 
     * @param context
     *            context of this view
     * @param attrs
     *            attributes of view
     */
    public TouchSurfaceView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        
        // create touch history array
        touches = new Touch[HISTORY_LEN];
        
        // init colors array(need non-null)
        colors = new int[0];
        
        // default legend to on
        showLegend = true;
        
        // create paint
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Style.FILL_AND_STROKE);
        paint.setTextSize(20);
        
        // get surface holder
        surface = this.getHolder();
    }
    
    /**
     * Resume drawing
     */
    public void resume()
    {
        // only start drawing if we aren't already
        if (drawing == null)
        {
            updated = true;
            drawing = new Thread(this, TAG);
            drawing.start();
        }
    }
    
    /**
     * Pause drawing
     */
    public void pause()
    {
        // stop if we are drawing
        if (drawing != null)
        {
            // interrupt drawing thread
            drawing.interrupt();
            
            try
            {
                drawing.join(); // wait for thread to die
                drawing = null; // nullify for later
            }
            catch (InterruptedException e)
            {
                Log.w(TAG, "Error pausing thread!", e);
            }
        }
    }
    
    /**
     * Run drawing thread
     */
    @Override
    public void run()
    {
        Canvas c = null;
        long time = 0, took = 0;
        
        try
        {
            while (!drawing.isInterrupted())
            {
                time = SystemClock.currentThreadTimeMillis(); // frame start
                                                              // time
                
                // ensure we have a valid surface to draw to and avoid
                // unnecessary
                // draws by only drawing if something has changed
                if (surface.getSurface().isValid() && updated)
                {
                    c = surface.lockCanvas(); // grab canvas
                    drawTouches(c); // draw
                    updated = false;
                    surface.unlockCanvasAndPost(c); // inform we are done with
                                                    // canvas
                }
                
                took = SystemClock.currentThreadTimeMillis() - time; // length
                                                                     // of frame
                
                // took less time than expected for frame, sleep remaining time
                if (took < FRAME_TIME) Thread.sleep(FRAME_TIME - took);
            }
        }
        catch (InterruptedException e)
        {
            // expected on pause if in sleep
        }
    }
    
    /**
     * Draw touches
     * 
     * View draw callback called when invalidated
     * 
     * @param c
     *            canvas to draw on
     */
    private void drawTouches(Canvas c)
    {
        // clear canvas
        c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        
        // draw color legend
        if (showLegend)
        {
            float labelHeight = 35;
            float labelsTop = (c.getHeight() / 2)
                    - ((labelHeight * colors.length) / 2);
            paint.setStrokeWidth(0);
            for (int i = 0; i < colors.length; i++)
            {
                float y = labelsTop + i * labelHeight;
                paint.setColor(colors[i]);
                c.drawRect(10, y, 40, y + 30, paint);
                paint.setColor(Color.WHITE);
                c.drawText("F" + (i + 1), 45, y + 30, paint);
            }
        }
        
        // draw touches
        paint.setStrokeWidth(2);
        for (Touch touch : touches)
        {
            // have not filled past here, skip rest of loop
            if (touch == null) break;
            
            paint.setColor(colors[touch.index]);
            c.drawPoint(touch.x, touch.y, paint);
        }
    }
    
    /**
     * Handle touch event and add touch point
     */
    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        int pointers = event.getPointerCount();
        
        // update pointers/colors for number of touches
        updatePointerColors(pointers);
        
        // we only care about move events and currently handling up to 5 fingers
        if (event.getActionMasked() == MotionEvent.ACTION_MOVE)
        {
            // go through each pointer in the event
            for (int pointer = 0; pointer < pointers; pointer++)
            {
                // get and add history since last touch event
                for (int g = 0; g < event.getHistorySize(); g++)
                {
                    addTouch(pointer,
                            event.getHistoricalX(pointer, g),
                            event.getHistoricalY(pointer, g),
                            event.getHistoricalPressure(pointer, g));
                }
                
                // add pointer touch event
                addTouch(pointer,
                        event.getX(pointer),
                        event.getY(pointer),
                        event.getPressure(pointer));
            }
        }
        updated = true;
        
        return true;
    }
    
    /**
     * Update colors when we have more pointers
     * 
     * @param pointers
     *            number of pointers on event
     */
    private void updatePointerColors(int pointers)
    {
        if (colors.length < pointers)
        {
            colors = new int[pointers];
            
            // hsv "heatmap" colors for touches
            float[] hsv =
            {
                    0, 1, 1
            };
            float step = 300f / pointers;
            
            // create "heatmap"
            for (int i = 0; i < pointers; i++)
            {
                hsv[0] = 60 + step * i;
                colors[i] = Color.HSVToColor(hsv);
            }
        }
    }
    
    /**
     * Record a touch
     * 
     * @param index
     *            touch index(pointer)
     * @param x
     *            x coord of touch
     * @param y
     *            y coord of touch
     * @param pressure
     *            pressure of touch
     */
    private void addTouch(int index, float x, float y, float pressure)
    {
        // add touch and increment index
        touches[i++] = new Touch(index, x, y, pressure);
        
        // wrap around if we have reached the end of our array
        if (i == touches.length) i = 0;
    }
    
    /**
     * Reset touches
     */
    public void reset()
    {
        touches = new Touch[HISTORY_LEN]; // reset touches
        i = 0; // reset index
        colors = new int[0]; // reset colors
        updated = true; // inform we have updated
    }
    
    /**
     * Set if we should be showing the legend or not
     * 
     * @param showLegend
     *            should legend be shown
     */
    public void showLegend(boolean showLegend)
    {
        this.showLegend = showLegend;
        updated = true;
    }
    
    /**
     * Hold touch data
     * 
     * @author taylor
     * 
     */
    class Touch
    {
        int index;
        float x, y, pressure;
        
        /**
         * Construct touch data
         * 
         * @param index
         *            index of touch(pointer)
         * @param x
         *            x coord of touch
         * @param y
         *            y coord of touch
         * @param pressure
         *            pressure of touch
         */
        Touch(int index, float x, float y, float pressure)
        {
            this.index = index;
            this.x = x;
            this.y = y;
            this.pressure = pressure;
        }
    }
}




Java Source Code List

com.evosysdev.testtouch.TouchSurfaceView.java
com.evosysdev.testtouch.TouchTestActivity.java