I need to make a arrow head in a line that is defined by a lot of points, that the user will drawn.
I hope that I could be clear about what is my question.
Thanks.
Note: All the questions/answers that I saw here were to resolve the problem of a line that was defined by two points, taken in the ACTION_DOWN and ACTION_UP. It's different in my case, because I need to take the first point while the line is being drawn.
This is my onTouch() method. It just draw a line defined by where the user touches in the screen.
public boolean onTouch(View v, MotionEvent event) {
if(getEditMode()) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
break;
case MotionEvent.ACTION_MOVE:
path.lineTo(eventX, eventY);
break;
case MotionEvent.ACTION_UP:
//Here i have to draw an arrow.
drawCanvas.drawPath(path, paint);
path.reset();
invalidate();
break;
}
invalidate();
return true;
} else {
return false;
}
}
So, I found a solution.
I store all the points that construct the line in an arraylist.
After I took a point of the line that would be in the 0.9 * arraylist.size() as reference to draw an arrowhead that follow the line direction.
Here is my onTouch() method and the funciont that I used to draw the arrow.
public boolean onTouch(View v, MotionEvent event) {
if(getEditMode()) {
float eventX = event.getX();
float eventY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
path.moveTo(eventX, eventY);
pList.clear(); // When I start a line need to clear the previous coorfinates.
break;
}
case MotionEvent.ACTION_MOVE: {
int hSize = event.getHistorySize();
path.lineTo(eventX, eventY);
PointF aux, auxH;
if(darrow) {
if(hSize > 0) { // If movement is too fast.
for(int i = 0; i < hSize; i++) {
auxH = new PointF(event.getHistoricalX(i), event.getHistoricalY(i));
pList.add(auxH);
}
}
aux = new PointF(eventX, eventY);
pList.add(aux);
}
break;
}
case MotionEvent.ACTION_UP: {
pend.x = eventX;
pend.y = eventY;
if(darrow) { // If need to draw an arrow head to the end of the line;
arrowPath = drawArrow(pend); // Store the right arrowhead to a path.
}
drawCanvas.drawPath(path, paint);
drawCanvas.drawPath(arrowPath, paint);
path.reset();
arrowPath.reset();
invalidate();
break;
}
}
invalidate();
return true;
} else {
return false;
}
}
And the drawArrow(PointF) function:
private Path drawArrow(PointF pfinal) {
float dx, dy;
PointF p1, p2;
PointF pstart;
Path auxPath = new Path();
if(pList.size() > 0) {
PointF[] auxArray = pList.toArray(new PointF[pList.size()]);
int index = (int)(auxArray.length * 0.9);
Log.d(msg, "Size: " + auxArray.length + " | index: " + index);
pstart = auxArray[index];
dx = pfinal.x - pstart.x;
dy = pfinal.y - pstart.y;
float length = (float)Math.sqrt(dx * dx + dy * dy);
float unitDx = dx / length;
float unitDy = dy / length;
final int arrowSize = 10;
p1 = new PointF(
(float)(pfinal.x - unitDx * arrowSize - unitDy * arrowSize),
(float)(pfinal.y - unitDy * arrowSize + unitDx * arrowSize));
p2 = new PointF(
(float)(pfinal.x - unitDx * arrowSize + unitDy * arrowSize),
(float)(pfinal.y - unitDy * arrowSize - unitDx * arrowSize));
auxPath.moveTo(pfinal.x, pfinal.y);
auxPath.lineTo(p1.x, p1.y);
auxPath.moveTo(pfinal.x, pfinal.y);
auxPath.lineTo(p2.x, p2.y);
auxPath.close();
}
return auxPath;
}