Skip to content

Instantly share code, notes, and snippets.

@ixiyang
Created April 25, 2014 02:51
Show Gist options
  • Save ixiyang/11276417 to your computer and use it in GitHub Desktop.
Save ixiyang/11276417 to your computer and use it in GitHub Desktop.
from androiddev
/*
* Copyright 2014 Gabriele Mariotti
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package it.gmariotti.android.example.shapefinger;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* @author Gabriele Mariotti ([email protected])
*/
public class DrawingView extends View {
public static final int LINE = 1;
public static final int RECTANGLE = 3;
public static final int SQUARE = 4;
public static final int CIRCLE = 5;
public static final int TRIANGLE = 6;
public static final int SMOOTHLINE = 2;
public static final float TOUCH_TOLERANCE = 4;
public static final float TOUCH_STROKE_WIDTH = 5;
public int mCurrentShape;
protected Path mPath;
protected Paint mPaint;
protected Paint mPaintFinal;
protected Bitmap mBitmap;
protected Canvas mCanvas;
/**
* Indicates if you are drawing
*/
protected boolean isDrawing = false;
/**
* Indicates if the drawing is ended
*/
protected boolean isDrawingEnded = false;
protected float mStartX;
protected float mStartY;
protected float mx;
protected float my;
public DrawingView(Context context) {
super(context);
init();
}
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DrawingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
if (isDrawing){
switch (mCurrentShape) {
case LINE:
onDrawLine(canvas);
break;
case RECTANGLE:
onDrawRectangle(canvas);
break;
case SQUARE:
onDrawSquare(canvas);
break;
case CIRCLE:
onDrawCircle(canvas);
break;
case TRIANGLE:
onDrawTriangle(canvas);
break;
}
}
}
protected void init() {
mPath = new Path();
mPaint = new Paint(Paint.DITHER_FLAG);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(getContext().getResources().getColor(android.R.color.holo_blue_dark));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(TOUCH_STROKE_WIDTH);
mPaintFinal = new Paint(Paint.DITHER_FLAG);
mPaintFinal.setAntiAlias(true);
mPaintFinal.setDither(true);
mPaintFinal.setColor(getContext().getResources().getColor(android.R.color.holo_orange_dark));
mPaintFinal.setStyle(Paint.Style.STROKE);
mPaintFinal.setStrokeJoin(Paint.Join.ROUND);
mPaintFinal.setStrokeCap(Paint.Cap.ROUND);
mPaintFinal.setStrokeWidth(TOUCH_STROKE_WIDTH);
}
protected void reset() {
mPath = new Path();
countTouch=0;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mx = event.getX();
my = event.getY();
switch (mCurrentShape) {
case LINE:
onTouchEventLine(event);
break;
case SMOOTHLINE:
onTouchEventSmoothLine(event);
break;
case RECTANGLE:
onTouchEventRectangle(event);
break;
case SQUARE:
onTouchEventSquare(event);
break;
case CIRCLE:
onTouchEventCircle(event);
break;
case TRIANGLE:
onTouchEventTriangle(event);
break;
}
return true;
}
//------------------------------------------------------------------
// Line
//------------------------------------------------------------------
private void onDrawLine(Canvas canvas) {
float dx = Math.abs(mx - mStartX);
float dy = Math.abs(my - mStartY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
canvas.drawLine(mStartX, mStartY, mx, my, mPaint);
}
}
private void onTouchEventLine(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDrawing = true;
mStartX = mx;
mStartY = my;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
invalidate();
break;
case MotionEvent.ACTION_UP:
isDrawing = false;
mCanvas.drawLine(mStartX, mStartY, mx, my, mPaintFinal);
invalidate();
break;
}
}
//------------------------------------------------------------------
// Smooth Line
//------------------------------------------------------------------
private void onTouchEventSmoothLine(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDrawing = true;
mStartX = mx;
mStartY = my;
mPath.reset();
mPath.moveTo(mx, my);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
float dx = Math.abs(mx - mStartX);
float dy = Math.abs(my - mStartY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mStartX, mStartY, (mx + mStartX) / 2, (my + mStartY) / 2);
mStartX = mx;
mStartY = my;
}
mCanvas.drawPath(mPath, mPaint);
invalidate();
break;
case MotionEvent.ACTION_UP:
isDrawing = false;
mPath.lineTo(mStartX, mStartY);
mCanvas.drawPath(mPath, mPaintFinal);
mPath.reset();
invalidate();
break;
}
}
//------------------------------------------------------------------
// Triangle
//------------------------------------------------------------------
int countTouch =0;
float basexTriangle =0;
float baseyTriangle =0;
private void onDrawTriangle(Canvas canvas){
if (countTouch<3){
canvas.drawLine(mStartX,mStartY,mx,my,mPaint);
}else if (countTouch==3){
canvas.drawLine(mx,my,mStartX,mStartY,mPaint);
canvas.drawLine(mx,my,basexTriangle,baseyTriangle,mPaint);
}
}
private void onTouchEventTriangle(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
countTouch++;
if (countTouch==1){
isDrawing = true;
mStartX = mx;
mStartY = my;
} else if (countTouch==3){
isDrawing = true;
}
invalidate();
break;
case MotionEvent.ACTION_MOVE:
invalidate();
break;
case MotionEvent.ACTION_UP:
countTouch++;
isDrawing = false;
if (countTouch<3){
basexTriangle=mx;
baseyTriangle=my;
mCanvas.drawLine(mStartX,mStartY,mx,my,mPaintFinal);
} else if (countTouch>=3){
mCanvas.drawLine(mx,my,mStartX,mStartY,mPaintFinal);
mCanvas.drawLine(mx,my,basexTriangle,baseyTriangle,mPaintFinal);
countTouch =0;
}
invalidate();
break;
}
}
//------------------------------------------------------------------
// Circle
//------------------------------------------------------------------
private void onDrawCircle(Canvas canvas){
canvas.drawCircle(mStartX, mStartY, calculateRadius(mStartX, mStartY, mx, my), mPaint);
}
private void onTouchEventCircle(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDrawing = true;
mStartX = mx;
mStartY = my;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
invalidate();
break;
case MotionEvent.ACTION_UP:
isDrawing = false;
mCanvas.drawCircle(mStartX, mStartY, calculateRadius(mStartX,mStartY,mx,my), mPaintFinal);
invalidate();
break;
}
}
/**
*
* @return
*/
protected float calculateRadius(float x1, float y1, float x2, float y2) {
return (float) Math.sqrt(
Math.pow(x1 - x2, 2) +
Math.pow(y1 - y2, 2)
);
}
//------------------------------------------------------------------
// Rectangle
//------------------------------------------------------------------
private void onDrawRectangle(Canvas canvas) {
drawRectangle(canvas,mPaint);
}
private void onTouchEventRectangle(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDrawing = true;
mStartX = mx;
mStartY = my;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
invalidate();
break;
case MotionEvent.ACTION_UP:
isDrawing = false;
drawRectangle(mCanvas,mPaintFinal);
invalidate();
break;
}
;
}
private void drawRectangle(Canvas canvas,Paint paint){
float right = mStartX > mx ? mStartX : mx;
float left = mStartX > mx ? mx : mStartX;
float bottom = mStartY > my ? mStartY : my;
float top = mStartY > my ? my : mStartY;
canvas.drawRect(left, top , right, bottom, paint);
}
//------------------------------------------------------------------
// Square
//------------------------------------------------------------------
private void onDrawSquare(Canvas canvas) {
onDrawRectangle(canvas);
}
private void onTouchEventSquare(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
isDrawing = true;
mStartX = mx;
mStartY = my;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
adjustSquare(mx, my);
invalidate();
break;
case MotionEvent.ACTION_UP:
isDrawing = false;
adjustSquare(mx, my);
drawRectangle(mCanvas,mPaintFinal);
invalidate();
break;
}
}
/**
* Adjusts current coordinates to build a square
* @param x
* @param y
*/
protected void adjustSquare(float x, float y) {
float deltaX = Math.abs(mStartX - x);
float deltaY = Math.abs(mStartY - y);
float max = Math.max(deltaX, deltaY);
mx = mStartX - x < 0 ? mStartX + max : mStartX - max;
my = mStartY - y < 0 ? mStartY + max : mStartY - max;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment