2015-11-02 24 views
6

私はカスタムビューを持っており、onDraw()ではビットマップマスキングを実行しようとしています。私はsquareBitmap(赤色)を全景に塗りつぶしていて、マスクとして機能するcircleBitmap(青色)を持っています。私はモードを使用しています:PorterDuff.Mode.DST_INAndroidビットマップマスキング(Xfermode)は、背景が不透明な黒い背景を残します

私が期待しているのは、赤く塗りつぶされたサークルです。私はそれを得るが、私はまた黒い不透明な背景を得る。私はこの不透明な背景を望んでいない、むしろ透明でなければならない。 Figure 1は私が得た結果であり、Figure 2は私が探している結果です。

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

私のコード:(私はこの質問の目的のためにonDraw()内部のすべてを移動した)私が間違っているつもりです

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


?この黒い不透明な背景をどうやって避けることができますか?

+0

'の代わりに' DST_IN'のDST_OUT'をお試しください。または 'SRC_IN'。 –

+0

@ FrankN.Steinいいえ、動作していません。今、私は黒い塗りつぶされた円と赤い背景を取得します。バックグラウンドは 'squareBitmap'のために赤ですが、なぜ黒丸ですか?理想的には、円は透明でなければならず、従って青色(背景レイアウトの色)でなければならない。 – Henry

+0

ここに答えがあります:http://ssp.impulsetrain.com/porterduff.html –

答えて

11

Xfermodeを完成させるために、図面をオフスクリーンビットマップにリダイレクトする必要があります。だから私の次の問題を修正しました。

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

はしかし、その後、再び、saveLayerdocumentationは、それが高価であるため、このメソッドを使用しないように言います。この方法の代わりにharware layerを使用することをお勧めします。提供される範囲は、大きい場合は特に、この方法を使用して

避け 又はCLIP_TO_LAYER_SAVE_FLAGはsaveFlags パラメータから省略された場合。ビュー上でハードウェアレイヤーを使用することをお勧めします xfermode、カラーフィルター、またはアルファを適用すると、この方法よりも多くのことが実行されるため、 となります。したがって

、intead saveLayer方法の、私は次のように追加して、それを修正することができました:

setLayerType(LAYER_TYPE_HARDWARE, q); 
+0

ビットマップ、マスク、使用されているペイントとXferModeの描画を示す完全な例を提供していただけますか?ありがとう! – thumbmunkeys

+1

私の質問のコードは完全な例です。私は 'Viewを拡張する 'クラスを持っています。そして、私は質問にあるonDraw()メソッドを持っています。私がそれを動作させるために追加した唯一のものは、答え: 'setLayerType'です。実際の世界のシナリオでこれを見てみたいかもしれません:http://stackoverflow.com/a/33483600/4747587 – Henry

+0

すばやい返事をいただきありがとうございます! – thumbmunkeys