简体   繁体   English

如何在Android画布中绘制一个填充三角形?

[英]How to draw a filled triangle in android canvas?

So I'm drawing this triangle in android maps using the code below in my draw method: 所以我在android地图中使用下面的代码在我的draw方法中绘制这个三角形:

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. pointX_returned是我从字段中获得的坐标。 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? 有办法以某种方式填补它吗?

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! 感谢尼古拉斯的暗示!

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. 并使用此颜色作为您的路径,而不是您的ARGB。 Make sure the last point of your path ends on the first one, it makes sense also. 确保路径的最后一点在第一点结束,这也是有道理的。

Tell me if it works please ! 告诉我它是否有效!

you can also use vertice : 你也可以使用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());

在此输入图像描述

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 阅读更多

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. 使用@ Pavel的答案作为指导,如果你没有这些点但是有x,y和高度和宽度的起点,这里有一个辅助方法。 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);
    }
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);

}

You need remove path.moveTo after first initial. 首次初始化后,您需要删除path.moveTo。

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

Don't moveTo() after each lineTo() 不要在每个lineTo()之后moveTo() lineTo()

In other words, remove every moveTo() except the first one. 换句话说,删除除第一个之外的每个moveTo()

Seriously, if I just copy-paste OP's code and remove the unnecessary moveTo() calls, it works. 说真的,如果我只是复制粘贴OP的代码并删除不必要的moveTo()调用,它就可以了。

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. 编辑:我知道OP已经发布了他的“最终工作解决方案”,但他没有说明它的工作原理。 The actual reason was quite surprising to me, so I felt the need to add an answer. 实际的原因让我非常惊讶,所以我觉得有必要添加一个答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM