如何在Android画布上绘制填充的三角形?

95

所以我正在使用下面的代码在Android地图中绘制此三角形:

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

我从字段中获取的pointX_returned坐标是纬度和经度。结果是一个漂亮的三角形,但内部为空,因此我看不到地图。有没有什么方法可以填充它?


正如我在我的答案中所发布的,只需在每个lineTo()之后不要使用moveTo(),就这样。 - oli.G
我知道这是一个旧问题,已经有一个(不正确的)被接受的答案,而且你也发布了你的最终解决方案,它可以正常工作... 但你没有说明为什么它可以工作,我希望我的评论能够为某个人节省我刚刚花费的时间 :) - oli.G
8个回答

78

好的,我已经完成了。我将分享这段代码,以防其他人需要:

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;

谢谢你的提示,Nicolas!


7
我很确定你不需要最后一个lineTo()close()会自动完成这个动作。 - Timmmm
1
以下是基于@Pavel的代码的简单复制粘贴方法: https://gist.github.com/ZirconCode/59cae1e2615279eafb29 - ZirconCode
请问你能分享一下与三角形绘制相关的全部代码吗?我认为你已经扩展了View类,因此请提供扩展后的类以及使用该类的几行代码。这将对我有很大帮助。 - Shirish Herwade
我只想指出这个代码之所以能够运行,是因为他在每个lineTo()调用后移除了不必要的(事实证明是恶意的)moveTo()调用。 - oli.G
1
如果您将“path”更改为实例变量,请记得在“canvas.drawPath()”之后调用“path.reset()”。 - Sira Lam
显示剩余3条评论

44

你可能需要做类似这样的事情:

Paint red = new Paint();

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

使用这个颜色作为你的路径,而不是你的ARGB。确保你的路径的最后一个点与第一个点相连,这也是有意义的。

请告诉我它是否有效!


很遗憾,这并没有帮助。 - oli.G
@Nicolas 如果我们需要使用RGB值自定义颜色而不是使用预定义的值,那么ARGB的替代方案是什么? - pallav bohara

12

你也可以使用 "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());

2
我认为这个解决方案无法处理填充形状。(无法测试,我此刻没有我的集成开发环境) - Nicolas C.
3
这似乎是更高效的解决方案,但不幸的是,这种方法不支持硬件加速视图。您可以禁用硬件加速,但这样会失去其性能提升:http://developer.android.com/guide/topics/graphics/hardware-accel.html - SurlyDre

10

参考@Pavel的回答,如果您没有点而只有起始坐标、高度和宽度,则可以使用辅助方法。还可以画倒置/倒立 - 这对我很有用,因为它被用作垂直条形图的末尾。

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

9

enter image description here

这个函数展示了如何从位图中创建一个三角形,即创建一个三角形裁剪后的图像。

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

上述函数返回在画布上绘制的三角形图像。


5

不要在每个lineTo()之后使用moveTo()

换句话说,除了第一个moveTo()之外,删除其余所有的moveTo()

如果我只是复制粘贴OP的代码并去掉不必要的moveTo()调用,它就能工作。

没有其他需要做的事情。


编辑:我知道OP已经发布了他的“最终工作解决方案”,但他并没有说明为什么它能工作。实际原因对我来说非常惊人,所以我感觉有必要添加一个答案。


你应该为此添加一个注释。这不是一个答案。 - Angad Singh

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

}

1
这个可行!别忘了使用paint.setAntiAlias(true)来获得平滑的三角形。 - Boldijar Paul
2
drawVertices调用是用来做什么的? - PsiX

3
你需要在第一次初始化后删除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();

我没有三个点,只有一个点的x和y坐标,如何从该点绘制一个三角形。 - Pranav

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接