¿Cómo dibujar un triángulo relleno en el lienzo de Android?

87

Así que estoy dibujando este triángulo en mapas de Android usando el siguiente código en mi método de dibujo:

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

El pointX_returned son las coordenadas que obtengo de los campos. Son básicamente latitudes y longitudes. El resultado es un bonito triángulo, pero la información privilegiada está vacía y, por lo tanto, puedo ver el mapa. ¿Hay alguna forma de llenarlo de alguna manera?

Pavel
fuente
Como publiqué en mi respuesta, simplemente no muevaTo () después de cada lineTo (), eso es todo lo que hay.
oli.G
Sé que es una pregunta antigua que ya tiene una respuesta aceptada (incorrecta), y también publicó su solución final que funciona ... pero no está diciendo por qué funciona, y espero que mi comentario pueda ahorrarle a alguien el tiempo que ' acabo de gastar en esto :)
oli.G

Respuestas:

41

Probablemente necesite hacer algo como:

Paint red = new Paint();

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

Y use este color para su camino, en lugar de su ARGB. Asegúrese de que el último punto de su camino termine en el primero, también tiene sentido.

¡Dime si funciona por favor!

Nicolas C.
fuente
Desafortunadamente, esto no ayuda
oli.G
@Nicolas ¿Qué usar en lugar de ARGB, si tenemos que personalizar el color con valor RGB en lugar de usar valores predefinidos?
pallav bohara
75

Ok, lo he hecho. Estoy compartiendo este código en caso de que alguien más lo necesite:

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;

¡Gracias por la pista Nicolas!

Pavel
fuente
7
Estoy bastante seguro de que no necesitas el último lineTo(). close()lo hace automáticamente.
Timmmm
@Timmmm He probado, tienes razón, no necesitas la última línea Para (). Gracias.
banxi1988
Muchas gracias. No sé por qué tuve tantos problemas para dibujar un triángulo, pero he pasado los últimos 20 minutos con varios errores en este pequeño problema.
Achal Dave
1
Aquí está el método simple para copiar y pegar (basado en el código de @ Pavel): gist.github.com/ZirconCode/59cae1e2615279eafb29
ZirconCode
1
si cambió patha una variable de instancia, recuerde llamar path.reset()después canvas.drawPath().
Sira Lam
11

también puedes usar 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());
GBouerat
fuente
2
No creo que esta solución maneje formas rellenas. (no puedo probar, no tengo mi IDE en este momento)
Nicolas C.
3
Esta parece ser la solución con más rendimiento, pero desafortunadamente este método no es compatible con vistas aceleradas por hardware. Puede deshabilitar la aceleración de hardware, pero luego pierde sus ganancias de rendimiento: developer.android.com/guide/topics/graphics/hardware-accel.html
SurlyDre
8

ingrese la descripción de la imagen aquí

esta función muestra cómo crear un triángulo a partir de un mapa de bits. Es decir, cree una imagen recortada de forma triangular. Pruebe el siguiente código o descargue el ejemplo de demostración

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

La función anterior devuelve una imagen triangular dibujada en un lienzo. Lee mas

Daniel Nyamasyo
fuente
7

Usando la respuesta de @ Pavel como guía, aquí hay un método de ayuda si no tiene los puntos pero tiene x, y, alto y ancho de inicio. También puede dibujar invertido / al revés, lo cual es útil para mí ya que se usó como final de un gráfico de barras vertical.

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

}
Faajir
fuente
¡Esto está funcionando! No olvide utilizar paint.setAntiAlias ​​(verdadero) para obtener un triángulo suave.
Boldijar Paul
2
¿Qué es la llamada drawVertices?
PsiX
3

Necesita eliminar path.moveTo después de la primera inicial.

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();
kaftanati
fuente
No tengo 3 puntos pero solo tengo un punto x nad y ¿cómo puedo dibujar un triángulo desde ese punto?
Pranav
2

No moveTo()después de cadalineTo()

En otras palabras, elimine todos moveTo()excepto el primero.

En serio, si solo copio y pego el código de OP y elimino las moveTo()llamadas innecesarias , funciona.

No es necesario hacer nada más.


EDITAR: Sé que el OP ya publicó su "solución de trabajo final", pero no dijo por qué funciona. La razón real me sorprendió bastante, así que sentí la necesidad de agregar una respuesta.

oli.G
fuente
Deberías haber agregado un comentario para esto. Ésta no es una respuesta.
Angad Singh