2015-09-21 11 views
6

Ich versuche, ein herzförmiges Canvas mit Pfad in Android zu zeichnen. Der Code lautet wie folgt:Android - Fill Path mit Farbe teilweise

@Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 


     // Fill the canvas with background color 
     canvas.drawColor(Color.WHITE); 
     // paint.setShader(null); 

     // Defining of the heart path starts 
     path.moveTo(left + WIDTH/2, top + HEIGHT/4); // Starting point 
     // Create a cubic Bezier cubic left path 
     path.cubicTo(left+WIDTH/5,top, 
       left+WIDTH/4,top+4*HEIGHT/5, 
       left+WIDTH/2, top+HEIGHT); 
     // This is right Bezier cubic path 
     path.cubicTo(left + 3 * WIDTH/4, top + 4 * HEIGHT/5, 
       left + 4 * WIDTH/5, top, 
       left + WIDTH/2, top + HEIGHT/4); 

     paint.setShader(new LinearGradient(0, canvas.getHeight()/4, canvas.getWidth(), canvas.getHeight()/4, new int[]{Color.RED, Color.YELLOW, Color.GREEN}, new float[]{0, 0.6f, 1}, Shader.TileMode.CLAMP)); 

     canvas.drawPath(path, paint); 

     heart_outline_paint.setColor(getResources().getColor(R.color.heart_outline_color)); // Change the boundary color 
     heart_outline_paint.setStrokeWidth(4); 
     heart_outline_paint.setStyle(Paint.Style.STROKE); 
     canvas.drawPath(path, heart_outline_paint); 



    } 

Ich bin in der Lage Herz ohne Frage zu ziehen, und ich bin in der Lage Farbe im Innern des Herzens mit der Fill Option in Paint zu füllen. Aber ich sollte in der Lage sein, das Herz gemäß einiger Daten dynamisch zu füllen, und es kann nicht die ganze Zeit voll gefüllt werden. Was ich habe, ist so weit wie folgt erreicht:

Heart Shape with Filled Color

ich eine umfangreiche Suche gemacht und stieß auf eine Menge Dinge ähnlich. Einige von denen:

  1. Android fill in part of a path?
  2. filling a circle gradually from bottom to top android

ich auch über das Konzept kam die Leinwand zu Bitmap umzuwandeln und Füllfarbe in der Bitmap mit Flood Fill Algorithm, die Benutzer können Farben im Inneren des füllen Bitmap. Ich möchte jedoch nicht, dass die Bitmap die Farbe füllt, während sie sich im Inneren des Herzens berührt, sondern während eines Tastendrucks füllt.

Ich dachte, dass filling a circle gradually from bottom to top android würde mir helfen, geben aber es macht Gebrauch von einem Kreis, und ich bin nicht in Canvas-versiert, die mich bei der Anpassung des Kreises Code auf eine solche Form sehr schwach macht.

Wenn jemand einige Ideen oder Einsichten hat, wie dies zu erreichen ist, wird es sehr hilfreich sein. Prost. Danke im Voraus.

S.S: Ich habe auch versucht, einige Tricks mit setShader in Paint, aber nichts würde mir geben, was ich will.

EDIT:

Ich stolperte über eine Idee, ein Rechteck über das Herz mit einer anderen Farbe gleich den Hintergrund der Leinwand zu ziehen, so dass es aussehen wird, seine Hälfte gefüllt !! Ich arbeite immer noch an der Idee und bin mir nicht sicher, wie genau das für mich sein wird. Wenn jemand eine bessere Idee hat, sind Sie herzlich willkommen.

enter image description here

+0

'" Aber ich sollte in der Lage sein, das Herz dynamisch nach einigen Daten zu füllen und es kann nicht die ganze Zeit voll gefüllt werden. "' Was in der Praxis bedeutet? – pskink

+0

Wie das Herz muss 10% oder 20% je nach den vom Benutzer erworbenen Punkten gefüllt werden. – San

Antwort

1

Ich verwendete clipPath Funktion in Canvas zur Verfügung, um zu erreichen, was ich brauchte. Ich zeichne das Herz mit der obigen Methode und zeichne ein Rechteck darüber, und ich verwende die clipPath Funktion, um die Region außerhalb des Herzens auszuschneiden.

 public static double filled_amount = .90; 
    path.moveTo(left_x_moveto, left_y_moveto); 
    path.cubicTo(left_x1, left_y1, left_x2, left_y2, left_x3, left_y3); 
    path.cubicTo(right_x2, right_y2, right_x1, right_y1, left_x_moveto, left_y_moveto); 
    path.close(); 
    Rect rect = new Rect((int)(canvas.getWidth()*.10),(int)(canvas.getHeight()*filled_amount),(int) canvas.getWidth(), (int) canvas.getHeight()); 
     canvas.clipPath(path); 
     paint.setColor(Color.WHITE); 
     paint.setStyle(Paint.Style.FILL); 
     canvas.drawPath(path, paint); 
     canvas.drawRect(rect, rect_paint); 
     heart_outline_paint.setColor(getResources().getColor(R.color.heart_outline_color)); // Change the boundary color 
     heart_outline_paint.setStrokeWidth(15); 
     heart_outline_paint.setStyle(Paint.Style.STROKE); 
     canvas.drawPath(path, heart_outline_paint); 

Dies wird mir das gewünschte Ergebnis der dynamischen Füllung des Herzens geben. Wenn Sie den Wert filled_amount dynamisch ändern und invalidate() aufrufen, sieht das so aus, als ob das Herz dynamisch gefüllt wird.

@ Henrys Antwort könnte eine bessere sein, aber das hat den Trick für mich getan, und ich schaue nicht tief in die Kanten, so ein bisschen Zickzack hier und da ist in Ordnung.

1

Sie könnten Bitmap Masking verwenden, um ein teilweise gefülltes Herz zu bekommen. Was Sie hier idealerweise tun, ist die Verwendung einer Bitmap, um die andere zu maskieren.

In Ihrem Fall könnten Sie ein gefülltes Rechteck in der Leinwand haben und Sie haben dann die heart Form in einem neuen Bitmap, um als die Maske zu fungieren. Sie könnten dann dynamisch die Füllung des Herzens ändern, indem Sie die Höhe des Hintergrundrechtecks ​​ändern.

Siehe hierzu: https://stackoverflow.com/a/33483600/4747587. Dieses enthält die Implementierung von , die teilweise einen Star füllt. Die Idee ist dieselbe.

+0

Vielen Dank für Ihre Antwort, die ich mit Path in Canvas und der ClipPath-Funktion erreicht hatte. – San

+0

Ja. Aber der 'clipPath' unterstützt kein Anti-Aliasing. Basierend auf einer anderen Form können Sie beginnen, Zick-Zack-Kanten zu sehen. Wenn Sie nicht zu viele Details haben und die Form eine passende ist, dann wäre 'clipPath' gut. – Henry

+0

Ich bin nicht so sehr in Details, also funktioniert clipPath perfekt für mich, danke für Ihren wertvollen Vorschlag. – San