¿Cómo dibujo una punta de flecha (en Android)?

Soy bastante nuevo en Android y he estado jugando con Canvas. Intento dibujar una flecha, pero solo estoy teniendo suerte con el dibujo del eje, ninguna de las puntas de flecha está funcionando.

He buscado un poco y encontré un ejemplo de Java, pero Android no tiene GeneralPath o AffineTransform .

En este momento, mi código se parece a lo siguiente (la punta de flecha no se parece en nada a una punta de flecha):

 public class DrawableView extends View { Context mContext; private int centerX; private int centerY; private int radius; private double arrLength; private double arrHeading; private int margin = 10; public DrawableView(Context context) { super(context); mContext = context; } @Override protected void onDraw(Canvas canvas) { //Paint Background Paint background = new Paint(); background.setColor(getResources().getColor(R.color.background); canvas.drawRect(0, 0, getWidth(), getHeight(), background); //Set vars for Arrow Paint Paint paint = new Paint(); paint.setColor(getResources().getColor(R.color.arrowColor); centerX = getWidth() / 2; centerY = getHeight() / 2; arrLength = radius - 10; if(centerX < centerY) radius = centerX - margin; else radius = centerY - margin; //Draw Shaft int[] xy = findArrowPos(arrLength, arrHeading); canvas.drawLine(centerX, centerY, xy[0], xy[1], paint); //Draw ArrowHead //This is where I'm confused } private int[] findArrowPos(double length, double angle) { int[] points = new int[2]; double theta = Math.toRadians(angle); points[0] = centerX + (int) (length * Math.cos(theta)); points[1] = centerY + (int) (length * Math.sin(theta)); return points; } } 

He echado un vistazo a los siguientes hilos de orientación:
* http://www.java-forums.org/awt-swing/6241-how-u-rotate-arrow-mark-line-moves-accordingly.html
* ¿Cómo dibujar una línea de flecha dirigida en Java?

¿Qué le parece usar “Path myPath = new Path ()”? donde daría las posiciones xey para crear un triángulo usando líneas y llenándolo. Puedes leer sobre esto, aquí hay un ejemplo que tomé de alguna parte.

 // create and draw triangles // use a Path object to store the 3 line segments // use .offset to draw in many locations // note: this triangle is not centered at 0,0 paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(2); paint.setColor(Color.RED); Path path = new Path(); path.moveTo(0, -10); path.lineTo(5, 0); path.lineTo(-5, 0); path.close(); path.offset(10, 40); canvas.drawPath(path, paint); path.offset(50, 100); canvas.drawPath(path, paint); // offset is cumlative // next draw displaces 50,100 from previous path.offset(50, 100); canvas.drawPath(path, paint); 

Intento este código, ha estado funcionando perfectamente.

 enter code here switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPath.reset(); mPath.moveTo(x, y); mX = x; mY = y; startPoint = new PointF(event.getX(), event.getY()); endPoint = new PointF(); invalidate(); break; case MotionEvent.ACTION_MOVE: float dx = Math.abs(x - mX); System.out.println("action move"); float dy = Math.abs(y - mY); if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { // currentDrawingPath.path.quadTo(mX,mY,(x + mX)/2, (y + mY)/2); } mX = x; mY = y; endPoint.x = event.getX(); endPoint.y = event.getY(); isDrawing = true; invalidate(); break; case MotionEvent.ACTION_UP: mPath.lineTo(mX, mY); float deltaX = endPoint.x-startPoint.x; float deltaY = endPoint.y-startPoint.y; float frac = (float) 0.1; float point_x_1 = startPoint.x + (float) ((1 - frac) * deltaX + frac * deltaY); float point_y_1 = startPoint.y + (float) ((1 - frac) * deltaY - frac * deltaX); float point_x_2 = endPoint.x; float point_y_2 = endPoint.y; float point_x_3 = startPoint.x + (float) ((1 - frac) * deltaX - frac * deltaY); float point_y_3 = startPoint.y + (float) ((1 - frac) * deltaY + frac * deltaX); mPath.moveTo(point_x_1, point_y_1); mPath.lineTo(point_x_2, point_y_2); mPath.lineTo(point_x_3, point_y_3); mPath.lineTo(point_x_1, point_y_1); mPath.lineTo(point_x_1, point_y_1); mCanvas.drawPath(mPath, ppaint); endPoint.x = event.getX(); endPoint.y = event.getY(); isDrawing = false; invalidate(); break; default: break; } 

He estado teniendo el mismo problema, necesito una flecha para apuntar en cierta dirección. Después de jugar con algoritmos de dibujo, decidí que el método más simple es usar un bitmap y simplemente usar una matriz para rotarlo, por ejemplo

 ImageView image = (ImageView) findViewById(R.id.bitmap_image); Bitmap bMap = BitmapFactory.decodeResource(getResources(), R.drawable.test); Matrix mat = new Matrix(); mat.postRotate(90); Bitmap bMapRotate = Bitmap.createBitmap(bMap, 0, 0, bMap.getWidth(), bMap.getHeight(), mat, true); image.setImageBitmap(bMapRotate); 

entonces su bitmap puede ser cualquier flecha de aspecto elegante que desee.

Si está buscando la solución para dibujar miles de flechas en un segundo, con líneas de cabeza de longitud fija, pruebe esta función (dibuja solo puntas de flecha):

 private void fillArrow(Paint paint, Canvas canvas, float x0, float y0, float x1, float y1) { paint.setStyle(Paint.Style.STROKE); int arrowHeadLenght = 10; int arrowHeadAngle = 45; float[] linePts = new float[] {x1 - arrowHeadLenght, y1, x1, y1}; float[] linePts2 = new float[] {x1, y1, x1, y1 + arrowHeadLenght}; Matrix rotateMat = new Matrix(); //get the center of the line float centerX = x1; float centerY = y1; //set the angle double angle = Math.atan2(y1 - y0, x1 - x0) * 180 / Math.PI + arrowHeadAngle; //rotate the matrix around the center rotateMat.setRotate((float) angle, centerX, centerY); rotateMat.mapPoints(linePts); rotateMat.mapPoints(linePts2); canvas.drawLine(linePts [0], linePts [1], linePts [2], linePts [3], paint); canvas.drawLine(linePts2 [0], linePts2 [1], linePts2 [2], linePts2 [3], paint); } 

Basado en https://gamedev.stackexchange.com/questions/44456/drawing-lines-on-android-with-matrix

Mi código de dibujo de flecha, tal vez puede ser de alguna utilidad para alguien:

  /** * Draw an arrow * change internal radius and angle to change appearance * - angle : angle in degrees of the arrows legs * - radius : length of the arrows legs * @author Steven Roelants 2017 * * @param paint * @param canvas * @param from_x * @param from_y * @param to_x * @param to_y */ private void drawArrow(Paint paint, Canvas canvas, float from_x, float from_y, float to_x, float to_y) { float angle,anglerad, radius, lineangle; //values to change for other appearance *CHANGE THESE FOR OTHER SIZE ARROWHEADS* radius=10; angle=15; //some angle calculations anglerad= (float) (PI*angle/180.0f); lineangle= (float) (atan2(to_y-from_y,to_x-from_x)); //tha line canvas.drawLine(from_x,from_y,to_x,to_y,paint); //tha triangle Path path = new Path(); path.setFillType(Path.FillType.EVEN_ODD); path.moveTo(to_x, to_y); path.lineTo((float)(to_x-radius*cos(lineangle - (anglerad / 2.0))), (float)(to_y-radius*sin(lineangle - (anglerad / 2.0)))); path.lineTo((float)(to_x-radius*cos(lineangle + (anglerad / 2.0))), (float)(to_y-radius*sin(lineangle + (anglerad / 2.0)))); path.close(); canvas.drawPath(path, paint); } 

Use un camino como se muestra a continuación y ajuste las coordenadas en consecuencia:

 // Construct a wedge-shaped path Path mPath = new Path(); mPath.moveTo(0, -50); mPath.lineTo(-20, 60); mPath.lineTo(0, 50); mPath.lineTo(20, 60); mPath.close();