Как вы упомянули, простое решение - просто соединить точки прямой линией. Вот код для этого:
public void onDraw(Canvas canvas) {
Path path = new Path();
boolean first = true;
for(Point point : points){
if(first){
first = false;
path.moveTo(point.x, point.y);
}
else{
path.lineTo(point.x, point.y);
}
}
canvas.drawPath(path, paint);
}
убедитесь, что вы изменили свою краску с заливки на обводку:
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
paint.setColor(Color.WHITE);
Другой вариант - соединить точки с помощью итерполяции, используя метод quadTo:
public void onDraw(Canvas canvas) {
Path path = new Path();
boolean first = true;
for(int i = 0; i < points.size(); i += 2){
Point point = points.get(i);
if(first){
first = false;
path.moveTo(point.x, point.y);
}
else if(i < points.size() - 1){
Point next = points.get(i + 1);
path.quadTo(point.x, point.y, next.x, next.y);
}
else{
path.lineTo(point.x, point.y);
}
}
canvas.drawPath(path, paint);
}
Это все еще приводит к некоторым острым краям.
Если вы действительно амбициозны, вы можете начать вычислять кубические сплайны следующим образом:
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();
Log.d(TAG, "point: " + point);
return true;
}
return super.onTouchEvent(event);
}
и добавьте значения dx & dy к классу Point:
class Point {
float x, y;
float dx, dy;
@Override
public String toString() {
return x + ", " + y;
}
}
Это дает плавные линии, но иногда приходится соединять точки, используя петлю.
Кроме того, для длинных сеансов рисования это становится вычислительно сложным для вычисления.
Надеюсь, это поможет ... забавным вещам, с которыми можно поиграть.
Редактировать
Я собрал быстрый проект, демонстрирующий эти различные методы, в том числе предлагаемую реализацию подписи Square. Наслаждайтесь: https://github.com/johncarl81/androiddraw