2016-08-08 6 views
1

Ich ziehe meine Stimme über diese. Ich habe eine Hintergrund-Bitmap, die ich mit einer anderen Bitmap überlagern möchte, die transparente Ausschnitte hat. Ich habe kein Problem damit, wenn der Ausschnitt eine Grundform ist, aber ich brauche den Ausschnitt als Schnittpunkt zweier Kreise (eine Art Blattform). Ich habe versucht, eine dritte Bitmap zu erstellen, um eine Ausschnittsvorlage zu erstellen, aber ich kann nicht einmal eine saubere Darstellung des Ausschnitts erhalten, geschweige denn, dass er als Ausschnittvorlage funktioniert.Transparenz aus der Interstektion

Wer weiß, wie man so etwas macht? Hier ist mein (vereinfachte) Versuch:

@Override 
public void draw(Canvas canvas) { 
    float w = canvas.getWidth(); 
    float h = canvas.getHeight(); 

    // just used to set some proportions 
    float off = 300f; 

    Paint paint = new Paint(); 

    // make a background bitmap with a yellow to green gradient 
    Bitmap bitmapBkg = Bitmap.createBitmap((int) w, (int) h, Bitmap.Config.ARGB_8888); 
    Canvas canvasBkg = new Canvas(bitmapBkg); 
    paint.reset(); 
    paint.setShader(new LinearGradient(0, h/2 - off, 0, h/2 + off, Color.YELLOW, Color.GREEN, Shader.TileMode.CLAMP)); 
    canvasBkg.drawRect(new RectF(0, 0, w, h), paint); 

    // make an overlay bitmap with a red to magenta gradient which will have the cutouts 
    Bitmap bitmapOver = Bitmap.createBitmap((int) w, (int) h, Bitmap.Config.ARGB_8888); 
    Canvas canvasOver = new Canvas(bitmapOver); 
    paint.reset(); 
    paint.setShader(new LinearGradient(0, h/2 - off, 0, h/2 + off, Color.RED, Color.MAGENTA, Shader.TileMode.CLAMP)); 
    canvasOver.drawRect(new RectF(0, 0, w, h), paint); 

    // make a bitmap of intersecting circles to be used as the cutout shape 
    Bitmap bitmapCut = Bitmap.createBitmap((int) w, (int) h, Bitmap.Config.ARGB_8888); 
    Canvas canvasCut = new Canvas(bitmapCut); 

    paint.reset(); 
    paint.setColor(Color.BLACK); 
    //paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); 
    canvasCut.drawCircle(w/2 - (off/2), h/2, off, paint); 

    paint.reset(); 
    paint.setColor(Color.BLACK); 
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); 
    canvasCut.drawCircle(w/2 + (off/2), h/2, off, paint); 

    // apply cutout to overlay 
    paint.reset(); 
    paint.setColor(Color.BLACK); 
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP)); 
    canvasOver.drawBitmap(bitmapCut, 0, 0, paint); 

    // draw background and overlay onto main canvas 
    paint.reset(); 
    paint.setColor(Color.BLACK); 
    canvas.drawBitmap(bitmapBkg, 0, 0, paint); 
    canvas.drawBitmap(bitmapOver, 0, 0, paint); 
} 

Hier wird ein Bild von dem, was ich erhalte:

enter image description here

Was ich versuche, den äußeren Teil würde auch Rot-Magenta zu erhalten; nur die Augenform in der Mitte sollte gelbgrün sein.

+0

Vielleicht die Bilder kombinieren, indem Sie PorterDuff ausnutzen? http://stackoverflow.com/questions/8280027/what-does-porterduff-mode-mean-in-android-graphics-what-does-it-do –

+0

Das ist, was ich versucht habe zu verwenden. – trans

+0

Und was ist schief gelaufen? –

Antwort

0

Der Trick bestand darin, eine weitere Ebene hinzuzufügen.

// make a secondary overlay that cuts out the whole circles 
    Bitmap bitmapOver2 = Bitmap.createBitmap((int) w, (int) h, Bitmap.Config.ARGB_8888); 
    Canvas canvasOver2 = new Canvas(bitmapOver2); 
    paint.reset(); 
    paint.setShader(new LinearGradient(0, h/2 - off, 0, h/2 + off, Color.RED, Color.MAGENTA, Shader.TileMode.CLAMP)); 
    canvasOver2.drawRect(new RectF(0, 0, w, h), paint); 
    paint.reset(); 
    paint.setColor(Color.BLACK); 
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 
    canvasOver2.drawCircle(w/2 - (off/2), h/2, off, paint); 
    canvasOver2.drawCircle(w/2 + (off/2), h/2, off, paint); 

Anwendung es etwa so:

// draw background and overlay onto main canvas 
    paint.reset(); 
    paint.setColor(Color.BLACK); 
    canvas.drawBitmap(bitmapBkg, 0, 0, paint); 
    canvas.drawBitmap(bitmapOver2, 0, 0, paint); 
    canvas.drawBitmap(bitmapOver, 0, 0, paint); 

Im Grunde ist es ein bisschen wie ein Trick ist. Er zeichnet den Hintergrund der mittleren Ebene zweimal, einmal mit vollen Kreisausschnitten und einmal mit dem Ausschnitt in Augenform. Die beiden passen genau zusammen, um den gewünschten Effekt zu erzielen.

Natürlich @Rotwang, Sie haben wahrscheinlich Recht. Mit Path und arcTo() wäre eine viel bessere Lösung. Der einzige Grund, warum ich diesen Ansatz vermieden habe, ist b/c arcTo() ist ein API 21+ Feature. Bis jetzt habe ich versucht, die API auf 17+ zu halten. Aber wenn jemand andere eine arcTo() Lösung für die Vollständigkeit zur Verfügung stellen möchte, wäre das cool zu vergleichen.