Une solution facile, comme vous l'avez mentionné, consiste à relier simplement les points par une ligne droite. Voici le code pour le faire :
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);
}
Assurez-vous que vous changez votre peinture de remplissage à course :
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
paint.setColor(Color.WHITE);
Une autre option consiste à relier les points par iterpolation en utilisant la méthode 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);
}
Il en résulte tout de même quelques arêtes vives.
Si vous êtes vraiment ambitieux, vous pouvez commencer à calculer les splines cubiques comme suit :
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);
}
J'ai également constaté qu'il fallait modifier les éléments suivants pour éviter de dupliquer les événements de mouvement :
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);
}
et ajoutez les valeurs dx et dy à la classe Point :
class Point {
float x, y;
float dx, dy;
@Override
public String toString() {
return x + ", " + y;
}
}
Cela produit des lignes lisses, mais il faut parfois relier les points à l'aide d'une boucle. En outre, pour les longues sessions de dessin, cette méthode devient gourmande en ressources informatiques.
J'espère que cela vous aidera... c'est amusant de jouer avec.
Modifier
J'ai réalisé un projet rapide démontrant ces différentes techniques, y compris l'implémentation de la signature suggérée de Square. Profitez-en : https://github.com/johncarl81/androiddraw
0 votes
Si les lignes droites s'avèrent "insuffisantes" pour votre objectif, vous pouvez envisager l'ajustement des courbes : stackoverflow.com/questions/878200/java-curve-fitting-library
0 votes
Merci, cela semble utile. Je n'avais pas pensé à utiliser des splines. Principalement parce que je suppose que cela utilise beaucoup plus de ressources. Est-ce que c'est aussi disponible pour Android
2 votes
Vous avez
Path.quadTo
,Path.cubicTo
... stackoverflow.com/questions/3811529/0 votes
stackoverflow.com/questions/11328848/