Android 如何绘制填充多边形?

Android 如何绘制填充多边形?,android,Android,如何在Android中绘制填充多边形?您需要将绘制对象设置为填充 Paint paint = new Paint(); paint.setStyle(Paint.Style.FILL); 然后你可以画你想要的任何东西,它就会被填满 canvas.drawCircle(20, 20, 15, paint); canvas.drawRectangle(60, 20, 15, paint); 等等 对于更复杂的形状,您需要使用。Android没有方便的drawPolygon(x\u数组、y\u数组

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

您需要将绘制对象设置为填充

Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
然后你可以画你想要的任何东西,它就会被填满

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


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

Android没有方便的
drawPolygon(x\u数组、y\u数组、numberofpoints)
类似Java的操作。你必须一点一点地创建一个
路径
对象。例如,要为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);
要为某个深度添加恒定的线性渐变,可以编写如下代码。注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);

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

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

仔细想想,Android/Java会让形状保持未填充状态是有道理的,因为moveTo表示多边形中的一个断点

不过我看过一些类似的教程


在每行的后面都有moveTo。即使这可能会导致一个完整的多边形,Android也会假设moveTo代表多边形中的一个断点。

我喜欢分三步完成

第1步。创建一个尖头类;-)

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

是的,你可能会做得更有效,但可能不会更具可读性:-)。

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

缺点是你必须提前知道你需要什么形状。好的方面是,如果你提前知道你可以包括一个好的形状库。此代码假定您在项目的资产/字体文件夹中有一种称为“形状”的字体

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

使用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();
}
private void drawPolygon(画布mCanvas、浮点x、浮点y、浮点半径、浮点边、浮点星形缠结、布尔逆时针、绘制){
如果(边<3){return;}
浮点a=((浮点)Math.PI*2)/边*(逆时针?-1:1);
mCanvas.save();
mCanvas.translate(x,y);
mCanvas.rotate(startAngle);
路径路径=新路径();
路径移动到(半径,0);
对于(int i=1;i
试试这个,或者


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


你不需要使用
Path.lineTo(x0,y0)
而只需调用
Path.close()
自动添加结束线段。这段代码有一些严重的问题:首先,Android中已经有两个
Point
PointF
类,所以你真的不需要重新创建自己的类。其次,您确实希望避免在View.draw()方法中分配对象,并且您提供的示例对单个绘图进行了大量的分配。这取决于您要绘制多少个矩形。但我同意这不是最有效的方法。但是高效通常意味着使代码不那么可用或可读,或者两者兼而有之。有可能用图标(标记)填充这个多边形吗?在图标之间有一些填充和指定的空间?这正是我想要的
            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);
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();
}
    Paint paint = new Paint();
    paint.setColor(Color.parseColor("#BAB399"));
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
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
    }
}