Class for the scribble/memo pad
//package com.neugent.aethervoice.ui;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.view.MotionEvent;
import android.view.View;
/**
* Class for the scribble/memo pad
*
* @author Amando Jose Quinto II
*
*/
public class Scribble extends View {
private static final int INVALID_POINTER_ID = -1;
/** The paint used in drawing the path. **/
private final Paint mPaint;
/** The canvas for the path to be drawn. **/
private static Canvas mCanvas;
/** The path 1 to be drawn. **/
private final Path mPath1;
/** The path 2 to be drawn. **/
private final Path mPath2;
/** The paint used by the bitmap **/
private final Paint mBitmapPaint;
/** Bitmap for the screen **/
private final Bitmap mBitmap = Bitmap.createBitmap(480, 390,
Bitmap.Config.ARGB_8888);
/** The flag for erasing the canvas. **/
private boolean mErase = false;
/** The starting point for x-coordinate. **/
private float mX1;
/** The starting point for y-coordinate. **/
private float mY1;
/** The starting point for x-coordinate. **/
private float mX2;
/** The starting point for y-coordinate. **/
private float mY2;
/** The tolerance of the finger movement. **/
private static final float TOUCH_TOLERANCE = 4;
private int mActivePointerId = INVALID_POINTER_ID;
/**
* Instantiate the Scribble.
*
* @param context
* The application context
*/
public Scribble(final Context context) {
super(context);
Scribble.mCanvas = new Canvas(mBitmap);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mPath1 = new Path();
mPath2 = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(6);
}
@Override
protected void onSizeChanged(final int w, final int h, final int oldw,
final int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
/**
* Draw/Erases the path determined by the user
*
* @see android.view.View#onDraw(android.graphics.Canvas)
*/
@Override
protected void onDraw(final Canvas canvas) {
if (mErase) {
final Paint p = new Paint();
p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
Scribble.mCanvas.drawRect(0, 0, getWidth(), getHeight(), p);
mErase = false;
} else {
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath1, mPaint);
canvas.drawPath(mPath2, mPaint);
}
}
/**
*
*/
public void eraseAll() {
mErase = true;
invalidate();
}
/**
* @param x
* the x-coordinate
* @param y
* the y-coordinate
*
* @see android.view.View#onTouchEvent(MotionEvent)
* @see android.view.MotionEvent#ACTION_DOWN
*/
private void touch_start(final float x, final float y, final int index) {
switch(index){
case 0:
mPath1.reset();
mPath1.moveTo(x, y);
mX1 = x;
mY1 = y;
break;
case 1:
mPath2.reset();
mPath2.moveTo(x, y);
mX2 = x;
mY2 = y;
break;
}
}
/**
* Draws the path.
*
* @param x
* the x-coordinate
* @param y
* the y-coordinate
*
* @see android.view.View#onTouchEvent(MotionEvent)
* @see android.view.MotionEvent#ACTION_MOVE
*/
private void touch_move(final float x, final float y, int pointerIndex) {
switch(pointerIndex){
case 0:
if (Math.abs(x - mX1) >= Scribble.TOUCH_TOLERANCE || Math.abs(y - mY1) >= Scribble.TOUCH_TOLERANCE) {
mPath1.quadTo(mX1, mY1, (x + mX1) / 2, (y + mY1) / 2);
mX1 = x;
mY1 = y;
}
break;
case 1:
if (Math.abs(x - mX2) >= Scribble.TOUCH_TOLERANCE || Math.abs(y - mY2) >= Scribble.TOUCH_TOLERANCE) {
mPath2.quadTo(mX2, mY2, (x + mX2) / 2, (y + mY2) / 2);
mX2 = x;
mY2 = y;
}
break;
}
}
/**
* Finishes the path.
*
* @see android.view.View#onTouchEvent(MotionEvent)
* @see android.view.MotionEvent#ACTION_UP
*/
private void touch_up(int index) {
switch(index){
case 0:
mPath1.lineTo(mX1, mY1);
// commit the path to our offscreen
Scribble.mCanvas.drawPath(mPath1, mPaint);
// kill this so we don't double draw
mPath1.reset();
break;
case 1:
mPath2.lineTo(mX2, mY2);
// commit the path to our offscreen
Scribble.mCanvas.drawPath(mPath2, mPaint);
// kill this so we don't double draw
mPath2.reset();
break;
}
}
@Override
public boolean onTouchEvent(final MotionEvent event) {
final int action = event.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:{
final float x = event.getX();
final float y = event.getY();
// Save the ID of this pointer
mActivePointerId = event.getPointerId(0);
touch_start(x, y, 0);
invalidate();
break;
} case MotionEvent.ACTION_POINTER_DOWN:{
final int pointerIndex2 = event.findPointerIndex(event.getPointerCount() - 1);
final float x = event.getX(pointerIndex2);
final float y = event.getY(pointerIndex2);
touch_start(x, y, 1);
invalidate();
break;
} case MotionEvent.ACTION_MOVE:{
final int count = event.getPointerCount();
// Find the index of the active pointer and fetch its position
final int pointerIndex = event.findPointerIndex(mActivePointerId);
final int pointerIndex2 = event.findPointerIndex(count - 1);
final float x = event.getX(pointerIndex);
final float y = event.getY(pointerIndex);
touch_move(x, y, pointerIndex);
if(count > 1 && pointerIndex2 != pointerIndex){
final float x2 = event.getX(pointerIndex2);
final float y2= event.getY(pointerIndex2);
touch_move(x2, y2, pointerIndex2);
}
invalidate();
break;
} case MotionEvent.ACTION_UP:
mActivePointerId = INVALID_POINTER_ID;
// System.out.println("AetherVoice ++++++++++++++++++++++++++ ACTION_UP");
if(event.getPointerCount() < 2)
touch_up(0);
break;
case MotionEvent.ACTION_CANCEL:
mActivePointerId = INVALID_POINTER_ID;
// System.out.println("AetherVoice +++++++++++++++++ ACTION_CANCEL");
break;
case MotionEvent.ACTION_POINTER_UP:
// System.out.println("AetherVoice ++++++++++++++++++ ACTION_POINTER_UP");
final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = event.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mActivePointerId = event.getPointerId(newPointerIndex);
touch_up(0);
mPath1.moveTo(mX2, mY2);
mX1 = mX2;
mY1 = mY2;
}
// System.out.println("AetherVoice ++++++++++++++++++++++ mActivePointerId "+mActivePointerId);
touch_up(1);
break;
}
//invalidate();
return true;
}
}
Related examples in the same category