How to draw a filled triangle in android canvas?

JavaAndroidGoogle MapsAndroid Canvas

Java Problem Overview


So I'm drawing this triangle in android maps using the code below in my draw method:

paint.setARGB(255, 153, 29, 29);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);

Path path = new Path();
path.moveTo(point1_returned.x, point1_returned.y);
path.lineTo(point2_returned.x, point2_returned.y);
path.moveTo(point2_returned.x, point2_returned.y);
path.lineTo(point3_returned.x, point3_returned.y);
path.moveTo(point3_returned.x, point3_returned.y);
path.lineTo(point1_returned.x, point1_returned.y);
path.close();
    	
canvas.drawPath(path, paint);

The pointX_returned are the coordinates which I'm getting from the fields. They are basically latitudes and longitudes. The result is a nice triangle but the insider is empty and therefore I can see the map. Is there a way to fill it up somehow?

Java Solutions


Solution 1 - Java

Ok I've done it. I'm sharing this code in case someone else will need it:

super.draw(canvas, mapView, true);
	
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
	
paint.setStrokeWidth(2);
paint.setColor(android.graphics.Color.RED);		
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);
	
Point point1_draw = new Point();		
Point point2_draw = new Point();  	
Point point3_draw = new Point();
	
mapView.getProjection().toPixels(point1, point1_draw);
mapView.getProjection().toPixels(point2, point2_draw);
mapView.getProjection().toPixels(point3, point3_draw);
	
Path path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(point1_draw.x,point1_draw.y);
path.lineTo(point2_draw.x,point2_draw.y);
path.lineTo(point3_draw.x,point3_draw.y);
path.lineTo(point1_draw.x,point1_draw.y);
path.close();
	
canvas.drawPath(path, paint);

//canvas.drawLine(point1_draw.x,point1_draw.y,point2_draw.x,point2_draw.y, paint);
	
return true;

Thanks for the hint Nicolas!

Solution 2 - Java

You probably need to do something like :

Paint red = new Paint();

red.setColor(android.graphics.Color.RED);
red.setStyle(Paint.Style.FILL);

And use this color for your path, instead of your ARGB. Make sure the last point of your path ends on the first one, it makes sense also.

Tell me if it works please !

Solution 3 - Java

you can also use vertice :

private static final int verticesColors[] = {
	Color.LTGRAY, Color.LTGRAY, Color.LTGRAY, 0xFF000000, 0xFF000000, 0xFF000000
};
float verts[] = {
	point1.x, point1.y, point2.x, point2.y,	point3.x, point3.y
};
canvas.drawVertices(Canvas.VertexMode.TRIANGLES, verts.length, verts, 0, null, 0, verticesColors,	0, null, 0, 0, new Paint());

Solution 4 - Java

Using @Pavel's answer as guide, here's a helper method if you don't have the points but have start x,y and height and width. Also can draw inverted/upside down - which is useful for me as it was used as end of vertical barchart.

 private void drawTriangle(int x, int y, int width, int height, boolean inverted, Paint paint, Canvas canvas){

        Point p1 = new Point(x,y);
        int pointX = x + width/2;
        int pointY = inverted?  y + height : y - height;

        Point p2 = new Point(pointX,pointY);
        Point p3 = new Point(x+width,y);


        Path path = new Path();
        path.setFillType(Path.FillType.EVEN_ODD);
        path.moveTo(p1.x,p1.y);
        path.lineTo(p2.x,p2.y);
        path.lineTo(p3.x,p3.y);
        path.close();

        canvas.drawPath(path, paint);
    }

Solution 5 - Java

enter image description here

this function shows how to create a triangle from bitmap. That is, create triangular shaped cropped image. Try the code below or download demo example

 public static Bitmap getTriangleBitmap(Bitmap bitmap, int radius) {
        Bitmap finalBitmap;
        if (bitmap.getWidth() != radius || bitmap.getHeight() != radius)
            finalBitmap = Bitmap.createScaledBitmap(bitmap, radius, radius,
                    false);
        else
            finalBitmap = bitmap;
        Bitmap output = Bitmap.createBitmap(finalBitmap.getWidth(),
                finalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, finalBitmap.getWidth(),
                finalBitmap.getHeight());

        Point point1_draw = new Point(75, 0);
        Point point2_draw = new Point(0, 180);
        Point point3_draw = new Point(180, 180);

        Path path = new Path();
        path.moveTo(point1_draw.x, point1_draw.y);
        path.lineTo(point2_draw.x, point2_draw.y);
        path.lineTo(point3_draw.x, point3_draw.y);
        path.lineTo(point1_draw.x, point1_draw.y);
        path.close();
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(Color.parseColor("#BAB399"));
        canvas.drawPath(path, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(finalBitmap, rect, rect, paint);

        return output;
    }

The function above returns an triangular image drawn on canvas. Read more

Solution 6 - Java

private void drawArrows(Point[] point, Canvas canvas, Paint paint) {
		
    float [] points  = new float[8];    		 
    points[0] = point[0].x;    	 
    points[1] = point[0].y;    	 
    points[2] = point[1].x;    	 
    points[3] = point[1].y;      	
    points[4] = point[2].x;    	 
    points[5] = point[2].y;    	     	 
    points[6] = point[0].x;    	 
    points[7] = point[0].y;
		
    canvas.drawVertices(VertexMode.TRIANGLES, 8, points, 0, null, 0, null, 0, null, 0, 0, paint);
	Path path = new Path();
	path.moveTo(point[0].x , point[0].y);
	path.lineTo(point[1].x,point[1].y);
 	path.lineTo(point[2].x,point[2].y);
	canvas.drawPath(path,paint);
		
}

Solution 7 - Java

You need remove path.moveTo after first initial.

Path path = new Path();
path.moveTo(point1_returned.x, point1_returned.y);
path.lineTo(point2_returned.x, point2_returned.y);
path.lineTo(point3_returned.x, point3_returned.y);
path.lineTo(point1_returned.x, point1_returned.y);
path.close();

Solution 8 - Java

Don't moveTo() after each lineTo()

In other words, remove every moveTo() except the first one.

Seriously, if I just copy-paste OP's code and remove the unnecessary moveTo() calls, it works.

Nothing else needs to be done.


EDIT: I know the OP already posted his "final working solution", but he didn't state why it works. The actual reason was quite surprising to me, so I felt the need to add an answer.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPavelView Question on Stackoverflow
Solution 1 - JavaPavelView Answer on Stackoverflow
Solution 2 - JavaNicolas C.View Answer on Stackoverflow
Solution 3 - JavaGBoueratView Answer on Stackoverflow
Solution 4 - JavascottyabView Answer on Stackoverflow
Solution 5 - JavaDaniel NyamasyoView Answer on Stackoverflow
Solution 6 - JavaFaakhirView Answer on Stackoverflow
Solution 7 - JavakaftanatiView Answer on Stackoverflow
Solution 8 - Javaoli.GView Answer on Stackoverflow