/*
* Copyright (C) 2016 Payworks GmbH (http://www.payworks.com)
*
* The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package io.mpos.ui.paybutton.view;
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.Mode;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class SignatureView extends View {
private static final String TAG = "SignatureView";
private Path mPath;
private Paint mPaint;
private Bitmap mBitmap;
private Canvas mCanvas;
private int bgColor;
private float curX, curY;
private boolean isDragged = false;
private static final int TOUCH_TOLERANCE = 4;
private static final int STROKE_WIDTH = 5;
/**
* The Listener.
*/
private SignatureViewListener mListener;
/**
* The interface Signature view listener.
*/
public interface SignatureViewListener {
/**
* Signature view did draw s Signature.
* Called after views touch up
*
* @param signatureView the signature view
*/
void signatureViewDidDrawSignature(SignatureView signatureView);
/**
* Signature view did clear signature.
*
* @param signatureView the signature view
*/
void signatureViewDidClearSignature(SignatureView signatureView);
}
public SignatureView(Context context) {
super(context);
init();
}
public SignatureView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SignatureView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void setListener(SignatureViewListener listener) {
mListener = listener;
}
private void init() {
setFocusable(true);
bgColor = Color.WHITE;
mPath = new Path();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(bgColor ^ 0x00FFFFFF);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(STROKE_WIDTH);
}
/**
* Set the color of the signature.
*
* @param color the hex representation of the desired color, most likely an instance of Color.*
*/
public void setSigColor(int color) {
mPaint.setColor(color);
}
/**
* Set the color of the signature. For simpler option just us setSigColor(int color).
*
* @param a alpha value
* @param r red value
* @param g green value
* @param b blue value\
*/
public void setSigColor(int a, int r, int g, int b) {
mPaint.setARGB(a, r, g, b);
}
/**
* Clear the view
*/
public void clearSignature() {
Log.d(TAG, "::clearSig:" + "");
if (mCanvas != null) {
mCanvas.drawColor(bgColor);
mCanvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
mPath.reset();
invalidate();
if(mListener != null) {
mListener.signatureViewDidClearSignature(this);
}
}
}
/**
* Get the bitmap backing the view.
*/
public Bitmap getImage() {
return this.mBitmap;
}
public void setImage(Bitmap bitmap) {
this.mBitmap = bitmap;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
int bitW = mBitmap != null ? mBitmap.getWidth() : 0;
int bitH = mBitmap != null ? mBitmap.getWidth() : 0;
// If the width and height of the bitmap are bigger than the
// new defined size, then keep the excess bitmap and return
// (Part of the backing bitmap will be clipped off, but it
// will still exist)
if (bitW >= w && bitH >= h) {
return;
}
if (bitW < w) bitW = w;
if (bitH < h) bitH = h;
// Create a new bitmap and canvas for the new size
Bitmap newBitmap = Bitmap.createBitmap(bitW, bitH, Bitmap.Config.ARGB_8888);
Canvas newCanvas = new Canvas();
newCanvas.setBitmap(newBitmap);
// If the old bitmap exists, redraw it onto the new bitmap
if (mBitmap != null) {
newCanvas.drawBitmap(mBitmap, 0, 0, mPaint);
}
// Replace the old bitmap and canvas with the new one
mBitmap = newBitmap;
mCanvas = newCanvas;
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
canvas.drawPath(mPath, mPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDown(x, y);
break;
case MotionEvent.ACTION_MOVE:
touchMove(x, y);
break;
case MotionEvent.ACTION_UP:
touchUp();
break;
}
invalidate();
return true;
}
private void touchDown(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
curX = x;
curY = y;
isDragged = false;
}
private void touchMove(float x, float y) {
float dx = Math.abs(x - curX);
float dy = Math.abs(y - curY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(curX, curY, (x + curX) / 2, (y + curY) / 2);
curX = x;
curY = y;
isDragged = true;
}
}
private void touchUp() {
if (isDragged) {
mPath.lineTo(curX, curY);
} else {
mPath.lineTo(curX + 2, curY + 2);
}
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
if(mListener != null) {
mListener.signatureViewDidDrawSignature(this);
}
}
}