Android 电子签名和文字抄录(封装成sdk) 银行签名和微信涂鸦实例

应用场景:

1.以前去银行办理业务都得去柜台,填N张表格,写N多个签名。随着智能机的普及、移动终端app的使用场景越来越广泛。手机银行app也给越来越多的人办理银行业务提供便捷,妈妈再也不用但是我们去银行排队浪费时间了。然而,有的业务该走的流程必须得走,所以电子签名的需求也就凸显出来。

2.小孩的作业

3.微信里面的涂鸦功能

 

 

sdk的封装东西

1.so库

2.jar

3.assert目录存放资源文件

 

 

客户端实现功能

1.可以保存,生成图片

2.可以取消

3.可以清除

4.生成签名图片 把view转成bitmap

5.图片压缩

 

流程

1.客户端生成加密串

2.通过接口得到加密串解密,这个时候回调用国家ca认证,有法律效应

3.把得到的信息图片和模板生成pdf文件

 

 public SignatureView(Context context, AttributeSet attrs) {

  super(context, attrs);

 

  TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SignatureView, 0, 0);

 

  // Configurable parameters

  try {

   mMinWidth = a.getDimensionPixelSize(R.styleable.SignatureView_minWidth, convertDpToPx(3));

   mMaxWidth = a.getDimensionPixelSize(R.styleable.SignatureView_maxWidth, convertDpToPx(7));

   mVelocityFilterWeight = a.getFloat(R.styleable.SignatureView_velocityFilterWeight, 0.9f);

   mPaint.setColor(a.getColor(R.styleable.SignatureView_penColor, Color.BLACK));

  } finally {

   a.recycle();

  }

 

  // Fixed parameters

  mPaint.setAntiAlias(true);

  mPaint.setStyle(Paint.Style.STROKE);

  mPaint.setStrokeCap(Paint.Cap.ROUND);

  mPaint.setStrokeJoin(Paint.Join.ROUND);

 

  // Dirty rectangle to update only the changed portion of the view

  mDirtyRect = new RectF();

 

  clear();

 }

 

 /**

  * Set the pen color from a given resource. If the resource is not found,

  * {@link android.graphics.Color#BLACK} is assumed.

  * 

  * @param colorRes

  * the color resource.

  */

 public void setPenColorRes(int colorRes) {

  try {

   setPenColor(getResources().getColor(colorRes));

  } catch (Resources.NotFoundException ex) {

   setPenColor(getResources().getColor(Color.BLACK));

  }

 }

 

 /**

  * Set the pen color from a given color.

  * 

  * @param color

  * the color.

  */

 public void setPenColor(int color) {

  mPaint.setColor(color);

 }

 

 /**

  * Set the minimum width of the stroke in pixel.

  * 

  * @param minWidth

  * the width in dp.

  */

 public void setMinWidth(float minWidth) {

  mMinWidth = convertDpToPx(minWidth);

 }

 

 /**

  * Set the maximum width of the stroke in pixel.

  * 

  * @param maxWidth

  * the width in dp.

  */

 public void setMaxWidth(float maxWidth) {

  mMaxWidth = convertDpToPx(maxWidth);

 }

 

 /**

  * Set the velocity filter weight.

  * 

  * @param velocityFilterWeight

  * the weight.

  */

 public void setVelocityFilterWeight(float velocityFilterWeight) {

  mVelocityFilterWeight = velocityFilterWeight;

 }

 

 public void clear() {

  mPoints = new ArrayList<TimedPoint>();

  mLastVelocity = 0;

  mLastWidth = (mMinWidth + mMaxWidth) / 2;

  mPath.reset();

 

  if (mSignatureBitmap != null) {

   mSignatureBitmap = null;

   ensureSignatureBitmap();

  }

 

  setIsEmpty(true);

 

  invalidate();

 }

 

 @Override

 public boolean onTouchEvent(MotionEvent event) {

  if (!isEnabled())

   return false;

 

  float eventX = event.getX();

  float eventY = event.getY();

 

  switch (event.getAction()) {

  case MotionEvent.ACTION_DOWN:

   getParent().requestDisallowInterceptTouchEvent(true);

   mPoints.clear();

   mPath.moveTo(eventX, eventY);

   mLastTouchX = eventX;

   mLastTouchY = eventY;

   addPoint(new TimedPoint(eventX, eventY));

 

  case MotionEvent.ACTION_MOVE:

   resetDirtyRect(eventX, eventY);

   addPoint(new TimedPoint(eventX, eventY));

   break;

 

  case MotionEvent.ACTION_UP:

   resetDirtyRect(eventX, eventY);

   addPoint(new TimedPoint(eventX, eventY));

   getParent().requestDisallowInterceptTouchEvent(true);

   setIsEmpty(false);

   break;

 

  default:

   return false;

  }

 

  // invalidate();

  invalidate((int) (mDirtyRect.left - mMaxWidth), (int) (mDirtyRect.top - mMaxWidth),

    (int) (mDirtyRect.right + mMaxWidth), (int) (mDirtyRect.bottom + mMaxWidth));

 

  return true;

 }

 

 @Override

 protected void onDraw(Canvas canvas) {

  if (mSignatureBitmap != null) {

   canvas.drawBitmap(mSignatureBitmap, 0, 0, mPaint);

  }

 }

 

 public void setOnSignedListener(OnSignedListener listener) {

  mOnSignedListener = listener;

 }

 

 public boolean isEmpty() {

  return mIsEmpty;

 }

 

 public Bitmap getSignatureBitmap() {

  Bitmap originalBitmap = getTransparentSignatureBitmap();

  Bitmap whiteBgBitmap = Bitmap.createBitmap(originalBitmap.getWidth(), originalBitmap.getHeight(),

    Bitmap.Config.ARGB_8888);

  Canvas canvas = new Canvas(whiteBgBitmap);

  canvas.drawColor(Color.WHITE);

  canvas.drawBitmap(originalBitmap, 0, 0, null);

  return whiteBgBitmap;

 }

 

 public void setSignatureBitmap(Bitmap signature) {

  clear();

  ensureSignatureBitmap();

 

  RectF tempSrc = new RectF();

  RectF tempDst = new RectF();

 

  int dWidth = signature.getWidth();

  int dHeight = signature.getHeight();

  int vWidth = getWidth();

  int vHeight = getHeight();

 

  // Generate the required transform.

  tempSrc.set(0, 0, dWidth, dHeight);

  tempDst.set(0, 0, vWidth, vHeight);

 

  Matrix drawMatrix = new Matrix();

  drawMatrix.setRectToRect(tempSrc, tempDst, Matrix.ScaleToFit.CENTER);

 

  Canvas canvas = new Canvas(mSignatureBitmap);

  canvas.drawBitmap(signature, drawMatrix, null);

  setIsEmpty(false);

  invalidate();

 }

 

 public Bitmap getTransparentSignatureBitmap() {

  ensureSignatureBitmap();

  return mSignatureBitmap;

 }

 

 public Bitmap getTransparentSignatureBitmap(boolean trimBlankSpace) {

 

  if (!trimBlankSpace) {

   return getTransparentSignatureBitmap();

  }

 

  ensureSignatureBitmap();

 

  int imgHeight = mSignatureBitmap.getHeight();

  int imgWidth = mSignatureBitmap.getWidth();

 

  int backgroundColor = Color.TRANSPARENT;

 

  int xMin = Integer.MAX_VALUE, xMax = Integer.MIN_VALUE, yMin = Integer.MAX_VALUE, yMax = Integer.MIN_VALUE;

 

  boolean foundPixel = false;

 

  // Find xMin

  for (int x = 0; x < imgWidth; x++) {

   boolean stop = false;

   for (int y = 0; y < imgHeight; y++) {

    if (mSignatureBitmap.getPixel(x, y) != backgroundColor) {

     xMin = x;

     stop = true;

     foundPixel = true;

     break;

    }

   }

   if (stop)

    break;

  }

 

  // Image is empty...

  if (!foundPixel)

   return null;

 

  // Find yMin

  for (int y = 0; y < imgHeight; y++) {

   boolean stop = false;

   for (int x = xMin; x < imgWidth; x++) {

    if (mSignatureBitmap.getPixel(x, y) != backgroundColor) {

     yMin = y;

     stop = true;

     break;

    }

   }

   if (stop)

    break;

  }

 

  // Find xMax

  for (int x = imgWidth - 1; x >= xMin; x--) {

   boolean stop = false;

   for (int y = yMin; y < imgHeight; y++) {

    if (mSignatureBitmap.getPixel(x, y) != backgroundColor) {

     xMax = x;

     stop = true;

     break;

    }

   }

   if (stop)

    break;

  }

 

  // Find yMax

  for (int y = imgHeight - 1; y >= yMin; y--) {

   boolean stop = false;

   for (int x = xMin; x <= xMax; x++) {

    if (mSignatureBitmap.getPixel(x, y) != backgroundColor) {

     yMax = y;

     stop = true;

     break;

    }

   }

   if (stop)

    break;

  }

 

  return Bitmap.createBitmap(mSignatureBitmap, xMin, yMin, xMax - xMin, yMax - yMin);

 }

 

 private void addPoint(TimedPoint newPoint) {

  mPoints.add(newPoint);

  if (mPoints.size() > 2) {

   // To reduce the initial lag make it work with 3 mPoints

   // by copying the first point to the beginning.

   if (mPoints.size() == 3)

    mPoints.add(0, mPoints.get(0));

 

   ControlTimedPoints tmp = calculateCurveControlPoints(mPoints.get(0), mPoints.get(1), mPoints.get(2));

   TimedPoint c2 = tmp.c2;

   tmp = calculateCurveControlPoints(mPoints.get(1), mPoints.get(2), mPoints.get(3));

   TimedPoint c3 = tmp.c1;

   Bezier curve = new Bezier(mPoints.get(1), c2, c3, mPoints.get(2));

 

   TimedPoint startPoint = curve.startPoint;

   TimedPoint endPoint = curve.endPoint;

 

   float velocity = endPoint.velocityFrom(startPoint);

   velocity = Float.isNaN(velocity) ? 0.0f : velocity;

 

   velocity = mVelocityFilterWeight * velocity + (1 - mVelocityFilterWeight) * mLastVelocity;

 

   // The new width is a function of the velocity. Higher velocities

   // correspond to thinner strokes.

   float newWidth = strokeWidth(velocity);

 

   // The Bezier's width starts out as last curve's final width, and

   // gradually changes to the stroke width just calculated. The new

   // width calculation is based on the velocity between the Bezier's

   // start and end mPoints.

   addBezier(curve, mLastWidth, newWidth);

 

   mLastVelocity = velocity;

   mLastWidth = newWidth;

 

   // Remove the first element from the list,

   // so that we always have no more than 4 mPoints in mPoints array.

   mPoints.remove(0);

  }

 }

 

 private void addBezier(Bezier curve, float startWidth, float endWidth) {

  ensureSignatureBitmap();

  float originalWidth = mPaint.getStrokeWidth();

  float widthDelta = endWidth - startWidth;

  float drawSteps = (float) Math.floor(curve.length());

 

  for (int i = 0; i < drawSteps; i++) {

   // Calculate the Bezier (x, y) coordinate for this step.

   float t = ((float) i) / drawSteps;

   float tt = t * t;

   float ttt = tt * t;

   float u = 1 - t;

   float uu = u * u;

   float uuu = uu * u;

 

   float x = uuu * curve.startPoint.x;

   x += 3 * uu * t * curve.control1.x;

   x += 3 * u * tt * curve.control2.x;

   x += ttt * curve.endPoint.x;

 

   float y = uuu * curve.startPoint.y;

   y += 3 * uu * t * curve.control1.y;

   y += 3 * u * tt * curve.control2.y;

   y += ttt * curve.endPoint.y;

 

   // Set the incremental stroke width and draw.

   mPaint.setStrokeWidth(startWidth + ttt * widthDelta);

   mSignatureBitmapCanvas.drawPoint(x, y, mPaint);

   expandDirtyRect(x, y);

  }

 

  mPaint.setStrokeWidth(originalWidth);

 }

 

   * view转bitmap
     */
   public Bitmap viewConversionBitmap(View v) {
        int w = v.getWidth();
        int h = v.getHeight();

        Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bmp);

        c.drawColor(Color.WHITE);
        /** 如果不设置canvas画布为白色,则生成透明 */

        v.layout(0, 0, w, h);
        v.draw(c);

        return bmp;
    }

 

下载地址如下:

https://github.com/gcacace/android-signaturepad

 

总结:

1.电子签名模糊的原理?

生成的图片被缩放了

2.电子签名有锯齿的问题?

因为没有用贝塞尔曲线

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
龙飞签名设计2.2绿化去水印版 软件大小:12MB 软件授权:免费软件 软件语言:简体中文 更新时间: 2011-12-28 应用平台: Vista/Win2003/WinXP/Win2000/Win9X/Win7/ 龙飞签名设计软件让签名设计实现了自动化,只要输入你的姓名,软件立即生你的签名!并且可以自己设置签名的背景、颜色、大小、位置等,让你的签名更加绚丽多彩,DIY你的签名吧。   高速发展的社会对签名的需求不断增加,高层人士需要签名,普通人也一样需要签名,合同、文件需要签名、参加会议、宴会需要签名、去银行取钱、汇款同样需要签名,互联网的邮箱、QQ、论坛等也都需要签名签名的用途非常的广泛,怎样使签名大众化,能够随手可得,而且签名的质量说得过去,龙飞签名设计根据这个出发点设计开发了这套签名软件,让它服务于社会,让人们的签名漂亮起来。   1、输入姓名自动生手工效果公文签名、一笔签名(该2款签名为龙飞签名独创)。可以一次性生8款签名,包括公文签、一笔签、英文签、篆印体(阳文)、篆印体(阴文)、硬行体、草书体、行草体。   2、以往的签名软件生的名字是单独的字,软件生的公文签是互连的字,并且造型美观。   3、软件生的公文签和英文签是由签名设计师陈继世手工书写后编辑整理形的软件。   4、提供复姓设计。   5、签名可以保存并可以打印。   说明:   1、因免费版的字库字数比正式版的少,生签名可能会有缺字现象,欲购买用正式版生签名,若您想设计更好的签名请联系龙飞签名,龙飞签名为您量身定做纯手工签名。   2、如需要了解更多龙飞签名设计软件的使用方法等情况,请点击软件界面右下角的“使用必读”按钮。   升级说明:   1、增加字库字:公文签和一笔签增加了部分生僻字及复姓。   2、修复:修复了篆印体,2字的姓名后加“之”;界面有所修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值