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?


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!


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!


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

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


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

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

}

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

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.


Você deveria ter adicionado um comentário para isso. Isso não é uma resposta.
— Angad Singh
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.