How to draw filled polygon?

Android

Android Problem Overview


How to draw filled polygon in Android ?

Android Solutions


Solution 1 - Android

Android does not have a handy drawPolygon(x_array, y_array, numberofpoints) action like Java. You have to walk through making a Path object point by point. For example, to make a filled trapezoid shape for a 3D dungeon wall, you could put all your points in x and y arrays then code as follows:

Paint wallpaint = new Paint();
wallpaint.setColor(Color.GRAY);
wallpaint.setStyle(Style.FILL);

Path wallpath = new Path();
wallpath.reset(); // only needed when reusing this path for a new build
wallpath.moveTo(x[0], y[0]); // used for first point
wallpath.lineTo(x[1], y[1]);
wallpath.lineTo(x[2], y[2]);
wallpath.lineTo(x[3], y[3]);
wallpath.lineTo(x[0], y[0]); // there is a setLastPoint action but i found it not to work as expected

canvas.drawPath(wallpath, wallpaint);

To add a constant linear gradient for some depth, you could code as follows. Note y[0] is used twice to keep the gradient horizontal:

 wallPaint.reset(); // precaution when resusing Paint object, here shader replaces solid GRAY anyway
 wallPaint.setShader(new LinearGradient(x[0], y[0], x[1], y[0], Color.GRAY, Color.DKGRAY,TileMode.CLAMP)); 
 		 	
 canvas.drawPath(wallpath, wallpaint);

Refer to Paint, Path and Canvas documentation for more options, such as array defined gradients, adding arcs, and laying a Bitmap over your polygon.

Solution 2 - Android

You need to set the paint object to FILL

Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);

Then you can draw whatever you want, and it will be filled.

canvas.drawCircle(20, 20, 15, paint);
canvas.drawRectangle(60, 20, 15, paint);

etc.

For more complex shapes you need to use the PATH object.

Solution 3 - Android

I like to do it in three steps...

Step 1. Create a pointy class ;-)

/**
 * Simple point
 */
private class Point {

	public float x = 0;
	public float y = 0;

	public Point(float x, float y) {
		this.x = x;
		this.y = y;
	}
}

Step 2. Add a method/function for drawing

/**
 * Draw polygon
 *
 * @param canvas The canvas to draw on
 * @param color  Integer representing a fill color (see http://developer.android.com/reference/android/graphics/Color.html)
 * @param points Polygon corner points
 */
private void drawPoly(Canvas canvas, int color, Point[] points) {
	// line at minimum...
	if (points.length < 2) {
		return;
	}

	// paint
	Paint polyPaint = new Paint();
	polyPaint.setColor(color);
	polyPaint.setStyle(Style.FILL);

	// path
	Path polyPath = new Path();
	polyPath.moveTo(points[0].x, points[0].y);
	int i, len;
	len = points.length;
	for (i = 0; i < len; i++) {
		polyPath.lineTo(points[i].x, points[i].y);
	}
	polyPath.lineTo(points[0].x, points[0].y);

	// draw
	canvas.drawPath(polyPath, polyPaint);
}

Step 3. Draw

	drawPoly(canvas, 0xFF5555ee,
			new Point[]{
				new Point(10, 10),
				new Point(15, 10),
				new Point(15, 20)
			});

Yes, you could probably do it more efficiently, but probably not much more readable :-).

Solution 4 - Android

Draw Polygon with x sides and custom radius:

private void drawPolygon(Canvas mCanvas, float x, float y, float radius, float sides, float startAngle, boolean anticlockwise, Paint paint) {

    if (sides < 3) { return; }

    float a = ((float) Math.PI *2) / sides * (anticlockwise ? -1 : 1);
    mCanvas.save();
    mCanvas.translate(x, y);
    mCanvas.rotate(startAngle);
    Path path = new Path();
    path.moveTo(radius, 0);
    for(int i = 1; i < sides; i++) {
        path.lineTo(radius * (float) Math.cos(a * i), radius * (float) Math.sin(a * i));
    }
    path.close();
    mCanvas.drawPath(path, paint);
    mCanvas.restore();
}

Solution 5 - Android

BTW - I discovered that once you begin creating your path, any moveTo commands within the path will mean that the shape is left unfilled.

It makes sense when you think about it, that Android/Java would leave the shape unfilled as the moveTo would represent a break in the polygon.

However I've seen some tutorials like this https://stackoverflow.com/questions/3501126/how-to-draw-a-filled-triangle-in-android-canvas

which have moveTo's after each lineTo. Even though this may result in an unbroken polygon, Android assumes that a moveTo represents a break in the polygon.

Solution 6 - Android

Old question, but a trick for anyone who finds this. If you include a font with the desired polygon as a glyph you can use the drawText function to draw your polygon.

The downside is you have to know ahead of time what shapes you'll need. The upside it is if you do know ahead of time you can include a nice shape library. This code assumes you have a font called shapes in your assets/fonts folder of your project.

			TypeFace shapesTypeFace = Typeface.createFromAsset(getAssets(), "fonts/shapes.ttf");
			Paint stopSignPaint = new Paint();
			stopSignPaint.setColor(Color.RED);
			//set anti-aliasing so it looks nice
			stopSignPaint.setAntiAlias(true);
			stopSignPaint.setTextSize(200);
			stopSignPaint.setTypeface(shapesTypeFace);
			
			//will show up as a box or question mark since 
			//the current display font doesn't have this glyph. 
			//open the shapes font in a tool like Character Map 
			//to copy and paste the glyph into your IDE
			//saving it as a variable makes it much easier to work with
			String hexagonGlyph = ""
			String triangleGlyph = ""
			
			
			....whatever code you got...
			
			
			//arguments: text, x coordinate, y coordinate, paint
			 canvas.drawText(hexagonGlyph, 200, 100, stopSignPaint);
			 
			//make it into a go sign
			stopSignPaint.setColor(Color.Green);
			 canvas.drawText(hexagonGlyph, 200, 100, stopSignPaint);
			 
			 
			//make a tiny one
			stopSignPaint.setTextSize(20);
			stopSignPaint.setColor(Color.RED);
			 canvas.drawText(hexagonGlyph, 200, 100, stopSignPaint);
			 
			 
			 //make a triangle
			 canvas.drawText(triangleGlyph, 200, 100, stopSignPaint);

Solution 7 - Android

Try this, or see the full demo

    Paint paint = new Paint();
    paint.setColor(Color.parseColor("#BAB399"));
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

Solution 8 - Android

This class can be used to draw any kind of polygons. Just call drawPolygonPath() in onDraw() method.

class PolygonView : View {
    constructor(context: Context?) : super(context) {
        init()
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        init()
    }

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        init()
    }

    private lateinit var paint: Paint
    
    private fun init() {
        paint = Paint().apply {
            color = Color.RED
            isAntiAlias = true
            style = Paint.Style.FILL
            strokeWidth = 10f
        }
    }


    override fun onDraw(canvas: Canvas) {
        canvas.drawPath(drawPolygonPath(8, 150f), paint)
        canvas.drawPath(drawPolygonPath(5, 120f), paint)

    }

    /**
     * @param sides number of polygon sides
     * @param radius side length.
     * @param cx drawing x start point.
     * @param cy drawing y start point.
     * */
    private fun drawPolygonPath(
        sides: Int,
        radius: Float,
        cx: Float = radius,
        cy: Float = radius
    ): Path {
        val path = Path()
        val x0 = cx + (radius * cos(0.0).toFloat())
        val y0 = cy + (radius * sin(0.0).toFloat())
        //2.0 * Math.PI = 2π, which means one circle(360)
        //The polygon total angles of the sides must equal 360 degree.
        val angle = 2 * Math.PI / sides

        path.moveTo(x0, y0)

        for (s in 1 until sides) {

            path.lineTo(
                cx + (radius * cos(angle * s)).toFloat(),
                cy + (radius * sin(angle * s)).toFloat()
            )
        }

        path.close()

        return path
    }
}

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
QuestionAndroiDBeginnerView Question on Stackoverflow
Solution 1 - AndroidAndroidcoderView Answer on Stackoverflow
Solution 2 - AndroidAdrian FâciuView Answer on Stackoverflow
Solution 3 - AndroidNuxView Answer on Stackoverflow
Solution 4 - AndroidluQView Answer on Stackoverflow
Solution 5 - Androiduser1325094View Answer on Stackoverflow
Solution 6 - AndroidnetsplitView Answer on Stackoverflow
Solution 7 - AndroidDaniel NyamasyoView Answer on Stackoverflow
Solution 8 - AndroidAbedView Answer on Stackoverflow