2015-11-02 10 views
6

Ich habe eine benutzerdefinierte Ansicht und in der onDraw(), versuche ich, Bitmap-Maskierung durchzuführen. Ich habe eine squareBitmap (rote Farbe), die die gesamte Ansicht füllt, und ich habe eine circleBitmap (blaue Farbe), die als Maske fungiert. Ich verwende den Modus: PorterDuff.Mode.DST_IN.Android Bitmap-Maskierung (Xfermode) hinterlässt einen undurchsichtigen schwarzen Hintergrund hinter

Das Ergebnis, das ich erwarte, ist ein RED gefüllter Kreis. Ich bekomme das, aber ich bekomme auch einen undurchsichtigen SCHWARZEN Hintergrund. Ich möchte diesen undurchsichtigen Hintergrund nicht, sondern sollte transparent sein. Figure 1 ist das Ergebnis, das ich habe, und Figure 2 ist das Ergebnis, das ich suche.

Figure 1 : The Result I gotFigure 2: The Result that I am looking for

Mein Code: (Ich habe alles in onDraw() für die Zwecke dieser Frage bewegt)

protected void onDraw(Canvas canvas) { 

    final int width = canvas.getWidth(); 
    final int height = canvas.getHeight(); 

    Bitmap circleBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 
    Canvas circleCanvas = new Canvas(circleBitmap); 
    Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); 
    p.setStyle(Paint.Style.FILL_AND_STROKE); 
    p.setColor(Color.BLUE); 
    circleCanvas.drawCircle(width/2, height/2, width/2, p); 

    p.setColor(Color.RED); 
    Bitmap squareBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888); 
    Canvas squareCanvas = new Canvas(squareBitmap); 
    final Rect squareRect = new Rect(0, 0, width, height); 
    squareCanvas.drawRect(squareRect, p); 

    Paint q = new Paint(Paint.ANTI_ALIAS_FLAG); 
    canvas.drawBitmap(squareBitmap, 0, 0, q); 
    q.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); 
    canvas.drawBitmap(circleBitmap, 0, 0, q); 
    q.setXfermode(null); 
} 


Wohin gehe ich falsch? Wie kann ich diesen schwarzen undurchsichtigen Hintergrund vermeiden?

+0

Try 'DST_OUT' statt' DST_IN'. Oder 'SRC_IN'. –

+0

@ FrankN.Stein Nein, es funktioniert nicht. Jetzt bekomme ich den schwarz gefüllten Kreis und einen roten Hintergrund. Der Hintergrund ist rot wegen der 'QuadratBitmap', aber warum ist der Kreis schwarz? Idealerweise sollte der Kreis transparent sein und daher blau sein (die Farbe des Hintergrundlayouts). – Henry

+0

Sie sollten hier eine Antwort finden: http://ssp.impulsetrain.com/porterduff.html –

Antwort

11

Es scheint, dass, um die Xfermode erledigt zu bekommen, muss ich die Zeichnung zu einem Offscreen-Bitmap umleiten. Also fügte folgendes hinzu, behob mein Problem.

canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), q); 

Aber dann wieder, sagt die documentation von saveLayer mit dieser Methode zu vermeiden, da es teuer ist. Es wird empfohlen, anstelle dieser Methode harware layer zu verwenden.

Vermeiden dieses Verfahren verwendet, insbesondere wenn die vorgesehenen Grenzen sind groß, oder wenn der CLIP_TO_LAYER_SAVE_FLAG aus dem Parameter saveFlags weggelassen. Es wird empfohlen, einen Hardware-Layer in einer Ansicht auf einen xfermod, Farbfilter oder Alpha zu verwenden, da es viel besser als diese Methode durchführen wird.

Daher intead von saveLayer Methode konnte ich es beheben, indem Sie das folgende:

setLayerType(LAYER_TYPE_HARDWARE, q); 
+0

Würde es Ihnen etwas ausmachen, das komplette Beispiel zu liefern, das Bitmap, Maske und die verwendete Farbe und den XferMode zeigt? Vielen Dank! – thumbmunkeys

+1

Der Code in meiner Frage ist das vollständige Beispiel. Ich habe eine Klasse, die View erweitert. Und ich habe die 'onDraw()' Methode, die ich in der Frage habe. Das einzige, was ich hinzugefügt habe, um es zum Laufen zu bringen, ist in der Antwort: 'setLayerType'. Vielleicht möchten Sie einen Blick auf dieses Szenario werfen: http://StackOverflow.com/a/33483600/4747587 – Henry

+0

das ist großartig, danke für die schnelle Antwort! – thumbmunkeys