由於上個星期公司要實現一個功能,是關於合同的,需要用戶簽名,由此引發書寫了這篇文章,此文設計的內容並不複雜,下面是梳理過程
自定義一個View監聽手勢動作,利用Path將手勢軌跡繪製到canvas。然後創建一個CacheCanvas,並設置一個Bitmap,在繪製的到canvas的同時並繪製到cacheCanvas上,以便將其取出,將bitmap存入本地
直接看代碼 SignatureView
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.*;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.io.*;
/**
* @Author MarkYe
* @Email [email protected]
* @Date 2019-06-09
* @Des 手繪簽名View
*/
public class SignatureView extends View {
private Paint mPaint;
private Path mPath;
private Bitmap cacheBitmap;//用戶保存簽名的Bitmap
private Canvas cacheCanvas;//用戶保存簽名的Canvas
private float lift, right, top, bottom;
public SignatureView(Context context) {
this(context, null);
}
public SignatureView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
init();
}
public SignatureView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
//初始化畫筆
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(10);
mPath = new Path();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
cacheBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
cacheCanvas = new Canvas(cacheBitmap);
//設置背景色爲透明
cacheCanvas.drawColor(Color.TRANSPARENT);
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//路徑起點
mPath.moveTo(event.getX(), event.getY());
if (lift == 0) {
lift = event.getX();
}
if (right == 0) {
lift = event.getX();
}
if (top == 0) {
top = event.getX();
}
if (bottom == 0) {
bottom = event.getX();
}
setVertexCoordinates(event.getX(), event.getY());
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(event.getX(), event.getY());
postInvalidate();
setVertexCoordinates(event.getX(), event.getY());
break;
case MotionEvent.ACTION_UP:
//將簽名繪製到緩存畫布上
cacheCanvas.drawPath(mPath, mPaint);
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//繪製簽名路徑
canvas.drawPath(mPath, mPaint);
}
/**
* 重置畫布
*/
public void resetCanvas() {
mPath.reset();
invalidate();
cacheBitmap = null;
cacheCanvas = null;
cacheBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
cacheCanvas = new Canvas(cacheBitmap);
//設置背景色爲透明
cacheCanvas.drawColor(Color.TRANSPARENT);
lift = right = top = bottom = 0;
}
/**
* 設置頂點座標
*/
private void setVertexCoordinates(Float x, Float y) {
if (lift > x)
lift = x;
if (right < x)
right = x;
if (top > y)
top = y;
if (bottom < y)
bottom = y;
}
/**
* 剪裁畫布把多餘的畫布去掉只保留簽名部分
*
* @param blank 邊距
*/
private Bitmap cropCanvas(int blank) {
// left, top, right - left, bottom - top
Log.w("cropCanvas", "lift " + lift);
Log.w("cropCanvas", "right " + right);
Log.w("cropCanvas", "top " + top);
Log.w("cropCanvas", "bottom " + bottom);
try {
return Bitmap.createBitmap(cacheBitmap, (int) lift - blank, (int) top - blank, (int) right + 2 * blank - (int) lift, (int) bottom + 2 * blank - (int) top);
} catch (Exception e) {
e.printStackTrace();
return cacheBitmap;
}
}
/**
* 判斷有沒有簽名
* @return true 有 反之沒有
*/
public boolean isEmpty(){
return mPath.isEmpty();
}
/**
* 保存簽名到本地
*
* @param path 保存路徑
* @param blank 邊距
*/
public void save(String path, int blank) {
Bitmap mBitmap = cropCanvas(blank);
File mFile = new File(path);
try {
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(mFile));
mBitmap.compress(Bitmap.CompressFormat.PNG, 100, bufferedOutputStream);
bufferedOutputStream.flush();
bufferedOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
給大家看看效果圖吧,PS(懶得弄gif了,這是靜態圖)
由於功能比較少,沒有將源碼放到GitHub上,加如需使用直接copySignatureView的代碼就行了。
童鞋們下次再見!
ok. THE END