Android 如何绘制填充多边形?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2047573/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 04:21:32  来源:igfitidea点击:

How to draw filled polygon?

android

提问by AndroiDBeginner

How to draw filled polygon in Android ?

如何在 Android 中绘制填充多边形?

采纳答案by Adrian Faciu

You need to set the paint object to FILL

您需要将绘制对象设置为 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.

对于更复杂的形状,您需要使用PATH 对象

回答by Androidcoder

Android does not have a handy drawPolygon(x_array, y_array, numberofpoints)action like Java. You have to walk through making a Pathobject 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:

Android 没有drawPolygon(x_array, y_array, numberofpoints)像 Java 那样方便的操作。您必须Path逐点创建对象。例如,要为 3D 地牢墙制作一个填充梯形形状,您可以将所有点放在 x 和 y 数组中,然后代码如下:

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:

要为某个深度添加恒定的线性渐变,您可以编写如下代码。注意 y[0] 被使用了两次以保持梯度水平:

 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, Pathand Canvasdocumentation for more options, such as array defined gradients, adding arcs, and laying a Bitmap over your polygon.

有关更多选项,请参阅PaintPathCanvas文档,例如数组定义的渐变、添加弧和在多边形上放置位图。

回答by Nux

I like to do it in three steps...

我喜欢分三步做...

Step 1. Create a pointy class ;-)

步骤 1. 创建一个尖头类 ;-)

/**
 * 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

步骤 2. 添加绘图方法/函数

/**
 * 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

步骤 3. 画画

    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 :-).

是的,您可能可以更有效地做到这一点,但可能不会更具可读性:-)。

回答by luQ

Draw Polygon with x sides and custom radius:

用 x 边和自定义半径绘制多边形:

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

回答by user1325094

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

顺便说一句 - 我发现一旦你开始创建你的路径,路径中的任何 moveTo 命令都意味着形状没有被填充。

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.

当您考虑它时,Android/Java 会保留未填充的形状,因为 moveTo 将表示多边形的中断。

However I've seen some tutorials like this How to draw a filled triangle in android canvas?

但是我看过一些这样的教程如何在android画布中绘制一个实心三角形?

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.

每个 lineTo 之后都有 moveTo。尽管这可能会导致多边形完整,但 Android 假定 moveTo 表示多边形的中断。

回答by netsplit

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.

老问题,但对任何发现此问题的人来说都是一个技巧。如果您包含具有所需多边形的字体作为字形,则可以使用 drawText 函数绘制多边形。

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.

缺点是你必须提前知道你需要什么形状。好处是如果您提前知道,您可以包含一个不错的形状库。此代码假设您的项目的 assets/fonts 文件夹中有一个名为 shape 的字体。

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

回答by Daniel Nyamasyo

Try this, or see the full demo

试试这个,或者看完整的演示

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

回答by Abed

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

此类可用于绘制任何类型的多边形。只需调用drawPolygonPath()onDraw() 方法。

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
    }
}