How to draw an arrow using android graphic class?

4

How can i draw an arrow using the graphics class?

Im using android graphics class and basically im trying to show a path on a map. So i need to print an arrow head on the canvas. Help me to figure out!

Thank you!

This is one of the methods i have used to draw a line. i want to print an arrow head on the edge of each and every line.

//       ArrayList<Point> ArrayListPoints = new ArrayList<Point>(); // Assign the shortest path here

//       ArrayListPoints.add(new Point(262,100));
//       ArrayListPoints.add(new Point(262,165));
//       ArrayListPoints.add(new Point(346,165));
//       ArrayListPoints.add(new Point(420,165));

       ArrayList<Point> ArrayListPointsFINAL;

    ArrayListPointsFINAL = storePath.ArrayListPoints;

    if(ArrayListPointsFINAL == null){
        System.out.println("ArrayListPointsFINAL is NULL");
    }
    else{

    ArrayList<Float> ArrayList_X = new ArrayList<Float>();
     ArrayList<Float> ArrayList_Y = new ArrayList<Float>();
     //int size = get.ArrayListPoints.size();

    for(int i=0; i<ArrayListPointsFINAL.size(); i++){
        ArrayList_X.add(Float.parseFloat(String.valueOf(ArrayListPointsFINAL.get(i).x)));
        ArrayList_Y.add(Float.parseFloat(String.valueOf(ArrayListPointsFINAL.get(i).y)));
          }   

    for(int i=1; i<ArrayList_X.size(); i++){
        Paint myPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        myPaint.setStrokeWidth(8/*1 /getResources().getDisplayMetrics().density*/);
        myPaint.setColor(0xffff0000);   //color.RED
       // myPaint.setStyle(myPaint);

       canvas.drawLine(ArrayList_X.get(i), ArrayList_Y.get(i), ArrayList_X.get(i-1), ArrayList_Y.get(i-1),myPaint);       

    }
android
graphics
android-canvas
draw
asked on Stack Overflow Aug 15, 2012 by Ruby • edited Jan 31, 2014 by Kara

7 Answers

9

Hope you'll still find this useful; here's how I draw an arrow head:

    private void fillArrow(Canvas canvas, float x0, float y0, float x1, float y1) {

    paint.setStyle(Paint.Style.FILL);

    float deltaX = x1 - x0;
    float deltaY = y1 - y0;
    float frac = (float) 0.1;

    float point_x_1 = x0 + (float) ((1 - frac) * deltaX + frac * deltaY);
    float point_y_1 = y0 + (float) ((1 - frac) * deltaY - frac * deltaX);

    float point_x_2 = x1;
    float point_y_2 = y1;

    float point_x_3 = x0 + (float) ((1 - frac) * deltaX - frac * deltaY);
    float point_y_3 = y0 + (float) ((1 - frac) * deltaY + frac * deltaX);

    Path path = new Path();
    path.setFillType(Path.FillType.EVEN_ODD);

    path.moveTo(point_x_1, point_y_1);
    path.lineTo(point_x_2, point_y_2);
    path.lineTo(point_x_3, point_y_3);
    path.lineTo(point_x_1, point_y_1);
    path.lineTo(point_x_1, point_y_1);
    path.close();

    canvas.drawPath(path, paint);
}

Given a line with end points at p(x0, y0) and p(x1, y1), the method draws an arrow head with its vertex at p(x1, y1).

The variable

frac : 0 < frac < 1

determines the size of the arrow head.

answered on Stack Overflow Nov 16, 2012 by Igwe Kalu • edited Jan 8, 2020 by Igwe Kalu
3

When I used Igwe Kalu's solution, the size of the arrow head varied according to the distance between the points.

Here is my solution for making the arrow head a constant size, independent of the distance between the points.

private void fillArrow(Canvas canvas, float x0, float y0, float x1, float y1) {
    paint.setStyle(Paint.Style.FILL);

    float deltaX = x1 - x0;
    float deltaY = y1 - y0;
    double distance = Math.sqrt((deltaX * deltaX) + (deltaY * deltaY));
    float frac = (float) (1 / (distance / 30));

    float point_x_1 = x0 + (float) ((1 - frac) * deltaX + frac * deltaY);
    float point_y_1 = y0 + (float) ((1 - frac) * deltaY - frac * deltaX);

    float point_x_2 = x1;
    float point_y_2 = y1;

    float point_x_3 = x0 + (float) ((1 - frac) * deltaX - frac * deltaY);
    float point_y_3 = y0 + (float) ((1 - frac) * deltaY + frac * deltaX);

    Path path = new Path();
    path.setFillType(Path.FillType.EVEN_ODD);

    path.moveTo(point_x_1, point_y_1);
    path.lineTo(point_x_2, point_y_2);
    path.lineTo(point_x_3, point_y_3);
    path.lineTo(point_x_1, point_y_1);
    path.lineTo(point_x_1, point_y_1);
    path.close();

    canvas.drawPath(path, paint);
}
answered on Stack Overflow Apr 1, 2015 by David Boyd
1

Same is worked ... But for illustration.. call the below method in onDraw.. so that you could see how it working...

private void fillArrow(Canvas canvas, float x0, float y0, float x1, float y1) {
    Paint paint = new Paint();
    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.FILL);

    float deltaX = x1 - x0;
    float deltaY = y1 - y0;
    float distance = (float) Math.sqrt((deltaX * deltaX)
            + (deltaY * deltaY));
    float frac = (float) (1 / (distance / 15));

    float point_x_1 = x0 + (float) ((1 - frac) * deltaX + frac * deltaY);
    float point_y_1 = y0 + (float) ((1 - frac) * deltaY - frac * deltaX);

    float point_x_2 = x1;
    float point_y_2 = y1;

    float point_x_3 = x0 + (float) ((1 - frac) * deltaX - frac * deltaY);
    float point_y_3 = y0 + (float) ((1 - frac) * deltaY + frac * deltaX);

    float midOfArrow_x = (point_x_1 + point_x_3) / 2;
    float midOfArrow_y = (point_y_1 + point_y_3) / 2;

    Path path = new Path();
    path.setFillType(Path.FillType.EVEN_ODD);

    path.moveTo(point_x_1, point_y_1);
    path.lineTo(point_x_2, point_y_2);
    path.lineTo(point_x_3, point_y_3);
    path.lineTo(point_x_1, point_y_1);
    // path.lineTo(point_x_1, point_y_1);
    path.close();

    path.transform(mMatrix);
    canvas.drawPath(path, paint);

    paint = new Paint();
    paint.setColor(Color.RED);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeWidth(9);
    path = new Path();

    path.moveTo(x0, y0);
    path.lineTo(midOfArrow_x, midOfArrow_y);
    path.transform(mMatrix);
    canvas.drawPath(path, paint);

    paint = new Paint();
    paint.setColor(Color.WHITE);
    paint.setStyle(Paint.Style.STROKE);

    canvas.drawCircle(x0, y0, 10, paint);

    canvas.drawCircle(midOfArrow_x, midOfArrow_y, 10, paint);

    paint.setColor(Color.RED);
    canvas.drawCircle(point_x_1, point_y_1, 10, paint);

    paint.setColor(Color.GREEN);
    canvas.drawCircle(point_x_2, point_y_2, 10, paint);

    paint.setColor(Color.BLUE);
    canvas.drawCircle(point_x_3, point_y_3, 10, paint);

}
answered on Stack Overflow Aug 7, 2015 by Venkateswara Rao
0

You can draw a Bitmap instead and apply a matrix to it.

answered on Stack Overflow Aug 15, 2012 by Dmitry Zaytsev
0

// using a custom View, you can draw using path primitives:

  private Paint mPaint;                 // paint object
  private Path mPathGrid;                   // path object

    @Override
    protected void onDraw(Canvas canvas) 
    {

        if (mPaint == null)
         mPaint = new Paint();                   // cache your paint object
            if (mPathGrid == null)
     mPathGrid = new Path();                 // and your path

        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAntiAlias(true);

        // a white arrow pointing down
        mPaint.setColor(Color.WHITE);
        mPaint.setStrokeWidth(2);
        mPathGrid.reset();
        mPathGrid.moveTo(100.0, 100.0);         // 100,100 is starting point of path

                // "draw" the outline of your arrow... play "connect the dots"...
        mPathGrid.lineTo(100.0 + 10.0f, 100.0);
        mPathGrid.lineTo(100.0 + 10.0f, 100.0 - 5.0f);
        mPathGrid.lineTo(100.0 + 13.0f, 100.0 - 5.0f);
        mPathGrid.lineTo(100.0 + 10.0f, 100.0 - 8.0f);
        mPathGrid.lineTo(100.0 + 7.0f, 100.0 - 5.0f);
        mPathGrid.lineTo(100.0 + 10.0f, 100.0 - 5.0f);
        canvas.drawPath(mPathGrid, mPaint);

        super.onDraw(canvas);
    }

I saw this in your code:

for(int i=1; i<ArrayList_X.size(); i++)
{ 
        Paint myPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
        myPaint.setStrokeWidth(8/*1 /getResources().getDisplayMetrics().density*/); 
        myPaint.setColor(0xffff0000);   //color.RED 
       // myPaint.setStyle(myPaint); 

       canvas.drawLine(ArrayList_X.get(i), ArrayList_Y.get(i), ArrayList_X.get(i-1), ArrayList_Y.get(i-1),myPaint);        

    } 

don't create new Paint objects within a loop like this, you only need one! And you only need to set properties like stroke width, color, etc, once.

answered on Stack Overflow Aug 15, 2012 by CSmith • edited Aug 15, 2012 by CSmith
0

I suggest you create an arrow bitmap and with the following code from my post here, you can turn the arrow with ease.

I hope this helps.

answered on Stack Overflow Aug 15, 2012 by Luke Taylor • edited May 23, 2017 by Community
0

I try this code it has been working perfectly

Here is my code...

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();

     //   isDrawing = true;
        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;
}       
answered on Stack Overflow Nov 30, 2012 by Kevin Rameshwaran

User contributions licensed under CC BY-SA 3.0