Wie zeichne ich ein gefülltes Dreieck in Android Canvas?

86

Also zeichne ich dieses Dreieck in Android-Karten mit dem folgenden Code in meiner Zeichenmethode:

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

Die pointX_returned sind die Koordinaten, die ich von den Feldern erhalte. Sie sind im Grunde Breiten- und Längengrade. Das Ergebnis ist ein schönes Dreieck, aber der Insider ist leer und daher kann ich die Karte sehen. Gibt es eine Möglichkeit, es irgendwie aufzufüllen?

Pavel
quelle
Wie ich in meiner Antwort gepostet habe, bewege dich einfach nicht nach jeder Zeile nach (), das ist alles, was es gibt.
oli.G
Ich weiß, dass es sich um eine alte Frage handelt, die bereits eine (falsche) akzeptierte Antwort hat, und Sie haben auch Ihre endgültige Lösung veröffentlicht, die funktioniert ... aber Sie geben nicht an, warum sie funktioniert, und ich hoffe, mein Kommentar kann jemandem die Zeit sparen, die ich habe. '
Ich habe

Antworten:

40

Sie müssen wahrscheinlich etwas tun wie:

Paint red = new Paint();

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

Und verwenden Sie diese Farbe für Ihren Pfad anstelle Ihres ARGB. Stellen Sie sicher, dass der letzte Punkt Ihres Pfades auf dem ersten endet. Dies ist auch sinnvoll.

Sag mir bitte, ob es funktioniert!

Nicolas C.
quelle
Leider hilft das nicht
oli.G
@Nicolas Was soll anstelle von ARGB verwendet werden, wenn die Farbe mit dem RGB-Wert angepasst werden muss, anstatt vordefinierte Werte zu verwenden?
Pallav Bohara
75

Ok, ich habe es geschafft. Ich teile diesen Code für den Fall, dass jemand anderes ihn benötigt:

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;

Danke für den Hinweis Nicolas!

Pavel
quelle
7
Ich bin mir ziemlich sicher, dass Sie den letzten nicht brauchen lineTo(). close()macht das automatisch.
Timmmm
@Timmmm Ich habe getestet, du hast recht, du brauchst nicht die letzte Zeile To (). Danke.
Banxi1988
Ich danke dir sehr. Ich weiß nicht, warum ich so viele Probleme beim Zeichnen eines Dreiecks hatte, aber ich habe die letzten 20 Minuten mit verschiedenen Fehlern an diesem winzigen Problem verbracht.
Achal Dave
1
Hier ist die einfache Methode zum Einfügen von Kopien (basierend auf @ Pavel's Code): gist.github.com/ZirconCode/59cae1e2615279eafb29
ZirconCode
1
wenn Sie geändert pathzu einer Instanzvariablen, denken Sie daran nennen path.reset()nach canvas.drawPath().
Sira Lam
11

Sie können auch Vertice verwenden:

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
quelle
2
Ich glaube nicht, dass diese Lösung gefüllte Formen handhabt. (kann nicht testen, ich habe meine IDE im Moment nicht)
Nicolas C.
3
Dies scheint die leistungsfähigere Lösung zu sein, aber leider wird diese Methode in hardwarebeschleunigten Ansichten nicht unterstützt. Sie können die Hardwarebeschleunigung deaktivieren, verlieren dann aber die Leistungssteigerung: developer.android.com/guide/topics/graphics/hardware-accel.html
SurlyDre
8

Geben Sie hier die Bildbeschreibung ein

Diese Funktion zeigt, wie aus einer Bitmap ein Dreieck erstellt wird. Erstellen Sie also ein dreieckig zugeschnittenes Bild. Probieren Sie den folgenden Code aus oder laden Sie das Demo-Beispiel herunter

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

Die obige Funktion gibt ein dreieckiges Bild zurück, das auf Leinwand gezeichnet wurde. Weiterlesen

Daniel Nyamasyo
quelle
6

Verwenden Sie die Antwort von @ Pavel als Leitfaden. Hier ist eine Hilfsmethode, wenn Sie nicht über die Punkte verfügen, aber Start x, y sowie Höhe und Breite haben. Kann auch invertiert / verkehrt herum zeichnen - was für mich nützlich ist, da es als Ende des vertikalen Balkendiagramms verwendet wurde.

 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
quelle
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
quelle
Das funktioniert! Vergessen Sie nicht, paint.setAntiAlias ​​(true) zu verwenden, um ein glattes Dreieck zu erhalten.
Boldijar Paul
2
Was ist der Aufruf von drawVertices?
PsiX
3

Sie müssen path.moveTo nach der ersten Initiale entfernen.

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
quelle
Ich habe keine 3 Punkte, aber nur einen Punkt x nad y wie kann ich ein Dreieck von diesem Punkt zeichnen.
Pranav
2

Nicht moveTo()nach jedemlineTo()

Mit anderen Worten, entfernen Sie alle moveTo()außer dem ersten.

Im Ernst, wenn ich nur den Code von OP kopiere und einfüge und die unnötigen moveTo()Aufrufe entferne , funktioniert es.

Sonst muss nichts getan werden.


EDIT: Ich weiß, dass das OP bereits seine "endgültige Arbeitslösung" veröffentlicht hat, aber er hat nicht angegeben, warum es funktioniert. Der eigentliche Grund war für mich ziemlich überraschend, daher hatte ich das Bedürfnis, eine Antwort hinzuzufügen.

oli.G
quelle
Sie sollten einen Kommentar dazu hinzugefügt haben. Dies ist keine Antwort.
Angad Singh