Como desenhar um triângulo preenchido na tela do Android?

87

Então, estou desenhando este triângulo nos mapas do Android usando o código abaixo no meu método de desenho:

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

O pointX_returned são as coordenadas que estou obtendo dos campos. Eles são basicamente latitudes e longitudes. O resultado é um belo triângulo, mas o insider está vazio e, portanto, posso ver o mapa. Existe uma maneira de preenchê-lo de alguma forma?

Pavel
fonte
Como postei em minha resposta, apenas não mova para () após cada lineTo (), isso é tudo que há.
oli.G
Eu sei que é uma pergunta antiga que já tem uma resposta (incorreta) aceita, e você também postou sua solução final que funciona ... mas você não está dizendo por que funciona, e espero que meu comentário possa economizar o tempo de alguém. acabei de gastar nisso :)
oli.G

Respostas:

41

Você provavelmente precisa fazer algo como:

Paint red = new Paint();

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

E use essa cor para o seu caminho, em vez do seu ARGB. Certifique-se de que o último ponto do seu caminho termine no primeiro, isso também faz sentido.

Diga-me se funciona, por favor!

Nicolas C.
fonte
Infelizmente, isso não ajuda
oli.G
@Nicolas O que usar em vez de ARGB, se tivermos que personalizar a cor com valor RGB em vez de usar valores predefinidos?
pallav bohara
75

Ok, eu fiz isso. Estou compartilhando este código caso outra pessoa precise dele:

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;

Obrigado pela dica Nicolas!

Pavel
fonte
7
Tenho certeza de que você não precisa do último lineTo(). close()faz isso automaticamente.
Timmmm
@Timmmm testei, você está certo, não precisa do último lineTo (). Obrigado.
banxi1988
Muito obrigado. Não sei por que tive tantos problemas para desenhar um triângulo, mas passei os últimos 20 minutos com vários bugs neste pequeno problema.
Achal Dave
1
Este é o método simples para copiar e colar (com base no código de @Pavel
ZirconCode
1
se você mudou pathpara uma variável de instância, lembre-se de chamar path.reset()depois canvas.drawPath().
Sira Lam
11

você também pode usar o vértice:

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
fonte
2
Não acho que esta solução lida com formas preenchidas. (não posso testar, não tenho meu IDE no momento)
Nicolas C.
3
Esta parece ser a solução com melhor desempenho, mas infelizmente esse método não é compatível com visualizações aceleradas por hardware. Você pode desativar a aceleração de hardware, mas perderá seus ganhos de desempenho: developer.android.com/guide/topics/graphics/hardware-accel.html
SurlyDre
8

insira a descrição da imagem aqui

esta função mostra como criar um triângulo a partir de um bitmap. Ou seja, crie uma imagem recortada em forma triangular. Experimente o código abaixo ou baixe o exemplo de demonstração

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

A função acima retorna uma imagem triangular desenhada na tela. Consulte Mais informação

Daniel Nyamasyo
fonte
7

Usando a resposta de @Pavel como guia, aqui está um método auxiliar se você não tiver os pontos, mas tiver início x, ye altura e largura. Também posso desenhar invertido / de cabeça para baixo - o que é útil para mim, pois foi usado como final do 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
fonte
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);

}
Faakhir
fonte
Isso está funcionando! Não se esqueça de usar paint.setAntiAlias ​​(true) para obter um triângulo suave.
Boldijar Paul
2
Qual é a chamada de drawVertices?
PsiX
3

Você precisa remover path.moveTo após a primeira 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
fonte
Eu não tenho 3 pontos, mas tenho apenas um ponto x nad y, como posso desenhar um triângulo a partir desse ponto.
Pranav
2

Não moveTo()depois de cadalineTo()

Em outras palavras, remova todos, moveTo()exceto o primeiro.

Sério, se eu apenas copiar e colar o código do OP e remover as moveTo()chamadas desnecessárias , ele funciona.

Nada mais precisa ser feito.


EDIT: Eu sei que o OP já postou sua "solução final de trabalho", mas ele não disse por que funciona. O motivo real foi bastante surpreendente para mim, então senti a necessidade de adicionar uma resposta.

oli.G
fonte
Você deveria ter adicionado um comentário para isso. Isso não é uma resposta.
Angad Singh