PorterduffXfermode: Wyczyść sekcję bitmapy

Celem jest narysowanie bitmapy i nad czymś, a także narysowanie kształtów, które wymazują bazowy obszar mapy bitowej.

[3]}mam dowód koncepcji, aby spróbować zrozumieć, jak mam się do tego zabrać. Znalazłem wiele wskazówek na temat używania:
android.graphics.PorterDuff.Mode.CLEAR

Poniższy kod tworzy ekran z niebieskim tłem i dodaje własny widok. Ten widok rysuje się na płótnie od dołu do góry: różowe tło, bitmapę z lekkim wstawką, aby pokazać różowe tło, i żółte kółko dla każdego 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]);
                }
            }
        }
    }

}

Oto wynik testu:

Tutaj wpisz opis obrazka

Tryb Wyczyść jest lewym górnym rogu, który pokazuje się jako czarny.

W innym przykładzie, w którym próbowałem tego użyć, miałem DialogFragment, w którym tryb CLEAR wymazał cały DialogFragment, aby aktywność poniżej mogła być widoczna. Stąd też zastosowałem w tym teście wiele różnych kolorów tła.

Czy to może być wyczyszczenie pikseli całego aktywność jak ten inny przykład doprowadził mnie do wiary? Myślałem, że tylko piksele płótna związane z widokiem mogą zostać usunięte, ale w moim innym przykładzie piksele widoku niestandardowego, leżącego u podstaw widoku obrazu i tła DialogFragment zostały wyczyszczone.

Czy ktoś mógłby mi pomóc zrozumieć, co dokładnie się dzieje?

EDIT: Powtórzyłem przykład potwierdzający moje podejrzenia. Podczas dodawania tego dokładnego widoku niestandardowego, ale w DialogFragment, podstawowa aktywność staje się widoczny.

Tutaj wpisz opis obrazka

Wydaje mi się to dość jasnym wskaźnikiem, że Mode.CLEAR w jakiś sposób usuwa płótno widoków pod spodem? Domyślam się, że czarny w pierwszym przykładzie to widok z najwyższego poziomu?

Author: B T, 2012-07-05

3 answers

Problemem jest przyspieszenie sprzętowe. Wyłącz go dla konkretnego widoku, który malujesz za pomocą CLEAR. Jeśli używasz widoku niestandardowego, zrób to w konstruktorach:

if (android.os.Build.VERSION.SDK_INT >= 11) 
{
     setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

Możesz również wywołać setLayerType W referencji widoku.

 41
Author: metaphyze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-08 20:36:24

Nie widzę niczego nieoczekiwanego. W konkretnym przypadku Mode.CLEAR, zarówno kolor, jak i Alfa miejsca docelowego są wyczyszczone, co pozwala na wyświetlenie czarnego tła. To Narzędzie pozwala eksperymentować z różnymi trybami, kolorami i wartościami alfa, a źródło może zaoferować pewien wgląd. Na poniższym (nieco datowanym) obrazku obszary CLEAR ujawniają słabe prążki-szare dostarczone przez delegata platformy PanelUI.

obraz
(źródło: Composite at sites.google.com)

 14
Author: trashgod,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-22 09:17:30

Jak wskazuje Romain Guy: Google stuff musisz pisać na Bitmapie, a nie na płótnie z kołami, które próbujesz wyczyścić, a następnie ustawić go na głównym płótnie w widoku. Więc zrób coś w stylu:

// Generate bitmap used for background
            bm = BitmapFactory.decodeFile("mnt/sdcard/Pictures/test.jpg");

// Create the paint and set the bitmap
Canvas temp = new Canvas(bm.getHeight(), bm.getWidth, Config.ARGB_8888);

// in onDraw()
temp.drawCircle((w / 8) * (ii * 2 + 1), (h / 8) * (i * 2 + 1), w / 8 * 0.8f, pDraw[i*4 + ii]);

// After loop
canvas.drawBitmap(....);
Mam nadzieję, że to pomoże.
 0
Author: AllDayAmazing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-14 19:42:15