L'obiettivo è semplicemente quello di disegnare una bitmap e sopra la parte superiore di essa disegnare forme che cancellano l'area sottostante della bitmap.PorterduffXfermode: cancella una sezione di una bitmap
Ho creato una semplice dimostrazione del codice di concetto per cercare di capire come esattamente dovrei andare su questo. Nelle varie discussioni qui ho trovato numerosi suggerimenti su come utilizzare:
android.graphics.PorterDuff.Mode.CLEAR
Il codice sotto crea semplicemente uno schermo con uno sfondo blu e aggiunge una visualizzazione personalizzata. Questa vista disegna sulla sua tela uno sfondo rosa, l'immagine bitmap (con un leggero bordo per mostrare lo sfondo rosa) e cerchi gialli sovrapposti che rappresentano ciascun PorterDuffXfermode.
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Paint.Style;
import android.graphics.PorterDuff.Mode;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.RelativeLayout;
public class Test extends Activity {
Drawing d = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
RelativeLayout.LayoutParams rlp = null;
// Create the view for the xfermode test
d = new Drawing(this);
rlp = new RelativeLayout.LayoutParams(600, 900);
rlp.addRule(RelativeLayout.CENTER_IN_PARENT);
d.setLayoutParams(rlp);
RelativeLayout rl = new RelativeLayout(this);
rl.setBackgroundColor(Color.rgb(0, 0, 255));
rl.addView(d);
// Show the layout with the test view
setContentView(rl);
}
public class Drawing extends View {
Paint[] pDraw = null;
Bitmap bm = null;
public Drawing(Context ct) {
super(ct);
// Generate bitmap used for background
bm = BitmapFactory.decodeFile("mnt/sdcard/Pictures/test.jpg");
// Generate array of paints
pDraw = new Paint[16];
for (int i = 0; i<pDraw.length; i++) {
pDraw[i] = new Paint();
pDraw[i].setARGB(255, 255, 255, 0);
pDraw[i].setStrokeWidth(20);
pDraw[i].setStyle(Style.FILL);
}
// Set all transfer modes
pDraw[0].setXfermode(new PorterDuffXfermode(Mode.CLEAR));
pDraw[1].setXfermode(new PorterDuffXfermode(Mode.DARKEN));
pDraw[2].setXfermode(new PorterDuffXfermode(Mode.DST));
pDraw[3].setXfermode(new PorterDuffXfermode(Mode.DST_ATOP));
pDraw[4].setXfermode(new PorterDuffXfermode(Mode.DST_IN));
pDraw[5].setXfermode(new PorterDuffXfermode(Mode.DST_OUT));
pDraw[6].setXfermode(new PorterDuffXfermode(Mode.DST_OVER));
pDraw[7].setXfermode(new PorterDuffXfermode(Mode.LIGHTEN));
pDraw[8].setXfermode(new PorterDuffXfermode(Mode.MULTIPLY));
pDraw[9].setXfermode(new PorterDuffXfermode(Mode.SCREEN));
pDraw[10].setXfermode(new PorterDuffXfermode(Mode.SRC));
pDraw[11].setXfermode(new PorterDuffXfermode(Mode.SRC_ATOP));
pDraw[12].setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
pDraw[13].setXfermode(new PorterDuffXfermode(Mode.SRC_OUT));
pDraw[14].setXfermode(new PorterDuffXfermode(Mode.SRC_OVER));
pDraw[15].setXfermode(new PorterDuffXfermode(Mode.XOR));
}
@Override
public void onDraw(Canvas canv) {
// Background colour for canvas
canv.drawColor(Color.argb(255, 255, 0, 255));
// Draw the bitmap leaving small outside border to see background
canv.drawBitmap(bm, null, new RectF(15, 15, getMeasuredWidth() - 15, getMeasuredHeight() - 15), null);
float w, h;
w = getMeasuredWidth();
h = getMeasuredHeight();
// Loop, draws 4 circles per row, in 4 rows on top of bitmap
// Drawn in the order of pDraw (alphabetical)
for(int i = 0; i<4; i++) {
for(int ii = 0; ii<4; ii++) {
canv.drawCircle((w/8) * (ii * 2 + 1), (h/8) * (i * 2 + 1), w/8 * 0.8f, pDraw[i*4 + ii]);
}
}
}
}
}
Questo è il risultato del test:
modo cancellazione è alto a sinistra, che mostra come il nero.
In un altro esempio in cui stavo cercando di usarlo avevo un DialogFragment in cui la modalità CLEAR cancellava l'intero DialogFragment in modo da poter vedere l'attività sottostante. Da qui il motivo per cui ho usato molti colori di sfondo diversi in questo test.
Questo potrebbe forse cancellare i pixel dell'intera attività come quell'altro esempio mi ha indotto a credere? Avrei pensato che solo i pixel della tela relativi alla vista potevano essere cancellati, ma nel mio altro esempio i pixel della vista personalizzata, della vista immagine sottostante e dello sfondo DialogFragment erano stati cancellati.
Qualcuno potrebbe aiutarmi a capire cosa sta succedendo esattamente e perché sto andando così terribilmente storto?
Grazie.
MODIFICA: Ho riprodotto un esempio che conferma i miei sospetti. Quando si aggiunge questa vista personalizzata esatta, ma in un DialogFragment, l'attività sottostante diventa visibile.
Questo sembra un indicatore abbastanza chiaro per me che il Mode.CLEAR
è in qualche modo cancellando la tela dei punti di vista sotto come bene? La mia ipotesi sarebbe il nero nel primo esempio è quello della visualizzazione di livello superiore?
Sto pensando che sto facendo qualcosa di molto sbagliato da qualche parte: S
Grazie ... ha reso la mia giornata! –
rallenterà il disegno, non è vero? – sandrstar
Questa dovrebbe essere la risposta accettata. Super utile. Grazie! –