前言:
之前换工作的时候,发现从事金融行业APP开发比较赚钱,为了钱,最近一直在学习,换工作之前在银行工作,虽然也算是金融行业但是却没有证券行业等的收益高,但在银行业务开发中金融行业也能够使用的其中之一就是,手写签名+公章功能的实现。
原理:
从业务逻辑上来说,就是我们提供一个可绘制的面板,让用户可以绘制,绘制完成后,进行写入文件保存或者加盖公章合成图片,然后上传后台,这里图片压缩处理逻辑省略。
绘制面板原理:
绘制面板自定义view的原理:在view中用监听OnTouch()事件,这里我把手当做鼠标来看,我们需要判断鼠标的抬起移动按下操作
1)没有绘制:没有进入OnTouch()监听,也就是鼠标[手]没有接触自定义view
2)什么时候绘制:
【1】手指点下屏幕时调用,使用画笔绘制起点
【2】手指在屏幕上滑动时调用,会记录之前和现在手势的位置,进行绘制,如果,之前位置和手势的位置相差大于3的时候,生成贝塞尔绘制曲线,为了看起来线条流畅,一般,贝塞尔曲线的操作点为起点和终点的一半,二次贝塞尔,实现平滑曲线;手势x, 手势Y为操作点,之前,贝塞尔曲线的操作点为起点和终点的一半xy为终点,我相信很多亲看到的算法都和小编说的一样哈。
【3】手指在屏幕上抬起的时候,绘制【2】操作得到的画笔中的内容
3)至于图片保存,就是比较常见的也是比较基础的bitmap or other object 写入File,可选择自己擅长的样式
绘制面板自定义view代码:
write_panel_layout.xml
代码如下:
package com.electronic.signature.view;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.support.annotation.ColorInt;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* 绘制Path的View 用于签名
*
* @author fuqinming
*/
@SuppressLint("ClickableViewAccessibility")
public class LinePathView extends View {
private static final String TAG = LinePathView.class.getSimpleName();
private Context mContext;
private float mX;
private float mY;
private final Paint mGesturePaint = new Paint();
private final Path mPath = new Path();
private Canvas cacheCanvas;
private Bitmap cachebBitmap;
private boolean isTouched = false;
private int mPaintWidth = 10;
private int mPenColor = Color.BLACK;
private int mBackColor = Color.TRANSPARENT;
public LinePathView(Context context) {
super(context);
init(context);
}
public LinePathView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public LinePathView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public void init(Context context) {
this.mContext = context;
mGesturePaint.setAntiAlias(true);
mGesturePaint.setStyle(Style.STROKE);
mGesturePaint.setStrokeWidth(mPaintWidth);
mGesturePaint.setColor(mPenColor);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
cachebBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
cacheCanvas = new Canvas(cachebBitmap);
cacheCanvas.drawColor(mBackColor);
isTouched = false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDown(event);
break;
case MotionEvent.ACTION_MOVE:
isTouched = true;
touchMove(event);
break;
case MotionEvent.ACTION_UP:
cacheCanvas.drawPath(mPath, mGesturePaint);
mPath.reset();