0

我想创建一个类来为我的 Android 应用程序捕获人类签名。到目前为止我有这个代码:

public class DrawView extends View implements OnTouchListener {
    private static final String TAG = "DrawView";

    List<Point> points = new ArrayList<Point>();
    Paint paint = new Paint();
    long oldTime = 0;

    public DrawView(Context context) {
        super(context);
        setFocusable(true);
        setFocusableInTouchMode(true);

        this.setOnTouchListener(this);

        // paint.setColor(Color.BLACK);
        // paint.setAntiAlias(true);

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(2);
        paint.setColor(Color.BLACK);
    }

    @Override
    public void onDraw(Canvas canvas) {
        Path path = new Path();

        if (points.size() > 1) {
            for (int i = points.size() - 2; i < points.size(); i++) {
                if (i >= 0) {
                    Point point = points.get(i);

                    if (i == 0) {
                        Point next = points.get(i + 1);
                        point.dx = ((next.x - point.x) / 3);
                        point.dy = ((next.y - point.y) / 3);
                    } else if (i == points.size() - 1) {
                        Point prev = points.get(i - 1);
                        point.dx = ((point.x - prev.x) / 3);
                        point.dy = ((point.y - prev.y) / 3);
                    } else {
                        Point next = points.get(i + 1);
                        Point prev = points.get(i - 1);
                        point.dx = ((next.x - prev.x) / 3);
                        point.dy = ((next.y - prev.y) / 3);
                    }
                }
            }
        }

        boolean first = true;
        for (int i = 0; i < points.size(); i++) {
            Point point = points.get(i);
            if (first) {
                first = false;
                path.moveTo(point.x, point.y);
            } else {

                Point prev = points.get(i - 1);
                path.cubicTo(prev.x + prev.dx, prev.y + prev.dy, point.x
                        - point.dx, point.y - point.dy, point.x, point.y);

            }
        }
        canvas.drawPath(path, paint);

    }

    public boolean onTouch(View view, MotionEvent event) {
        if (event.getAction() != MotionEvent.ACTION_UP) {
            Point point = new Point();
            point.x = event.getX();
            point.y = event.getY();
            points.add(point);
            invalidate();
            return true;
        }
        return super.onTouchEvent(event);

    }

    public boolean checkTime() {
        //Check if there was an input 400 ms ago
        long newTime = System.currentTimeMillis();
        long diffirence = newTime - oldTime;
        if (oldTime == 0) {
            oldTime = System.currentTimeMillis();
            return true;
        } else if (diffirence <= 400) {
            oldTime = System.currentTimeMillis();
            return true;
        }
        return false;
    }
}

class Point {
    float x, y;
    float dx, dy;

    @Override
    public String toString() {
        return x + ", " + y;
    }
}

问题是当我再次开始绘制时,即使我停止绘制一段时间,这条线也会连接到最新的点。这对于捕获人类签名当然不是很有用,这就是我创建 checkTime 方法的原因。如果您停止绘图 400 毫秒,则返回 false,当您再次开始绘图时,它将开始一条新线,该线未连接到旧线。我只是不知道如何实现我的方法,我尝试了很多但线路一直连接到最新点,也许有人可以帮助我。

4

2 回答 2

1

在 onTouch 中创建路径并仅在 onDraw 中绘制可能会更快。

将 onTouch 替换为

Path path = new Path();
int prevx=0;
int prevy=0;
int prevdx=0;
int prevdy=0;
public boolean onTouch(View view, MotionEvent event) 
{
   int x = event.getX();
   int y = event.getY();
   int dx = (x-prevx)/3;
   int dy = (y-prevy)/3;
   if(event.getAction() == MotionEvent.ACTION_DOWN)
   {
       path.moveTo(x, y);
   }
   if(event.getAction() == MotionEvent.ACTION_MOVE)
   {
       path.cubicTo(prevx + prevdx, prevy + prevdy, x - dx, y - dy, x, y);
   }
   prevx=x;
   prevy=y;
   prevdx=dx;
   prevdy=dy; 
   invalidate();
   return true;
}

onDraw 将只是

public void onDraw(Canvas canvas)  
{
   canvas.drawPath(path, paint);
}
于 2012-11-05T18:57:16.373 回答
1

我使用了 Lars Vogel的这篇文章,但非常感谢 Marc Van Daele!

这是绘制视图的代码:

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class SingleTouchEventView extends View {
  private Paint paint = new Paint();
  private Path path = new Path();

  public SingleTouchEventView(Context context, AttributeSet attrs) {
    super(context, attrs);

    paint.setAntiAlias(true);
    paint.setStrokeWidth(6f);
    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeJoin(Paint.Join.ROUND);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    canvas.drawPath(path, paint);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    float eventX = event.getX();
    float eventY = event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
      path.moveTo(eventX, eventY);
      return true;
    case MotionEvent.ACTION_MOVE:
      path.lineTo(eventX, eventY);
      break;
    case MotionEvent.ACTION_UP:
      // nothing to do
      break;
    default:
      return false;
    }

    // Schedules a repaint.
    invalidate();
    return true;
  }
} 

您必须调用此活动才能开始绘画:

import android.app.Activity;
import android.os.Bundle;

public class SingleTouchActivity extends Activity {

/** Called when the activity is first created. */

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new SingleTouchEventView(this, null));
  }
} 
于 2012-11-06T20:32:49.687 回答