Android, canvas: jak wyczyścić (usunąć zawartość) canvas (=bitmapy), żyjąc w surfaceView?

Aby zrobić prostą grę, użyłem szablonu, który rysuje płótno z bitmapami w taki sposób:

private void doDraw(Canvas canvas) {
    for (int i=0;i<8;i++)
        for (int j=0;j<9;j++)
            for (int k=0;k<7;k++)   {
    canvas.drawBitmap(mBits[allBits[i][j][k]], i*50 -k*7, j*50 -k*7, null); } }

(płótno jest zdefiniowane w" run () " / SurfaceView żyje w grze.)

Moje pierwsze pytanie brzmi: jak wyczyścić (lub przerysować) całe płótno dla nowego layoutu?
Po drugie, jak mogę zaktualizować tylko część ekranu?

// This is the routine that calls "doDraw":
public void run() {
    while (mRun) {
        Canvas c = null;
        try {
            c = mSurfaceHolder.lockCanvas(null);
            synchronized (mSurfaceHolder) {
                if (mMode == STATE_RUNNING) 
                    updateGame();
                doDraw(c);          }
        } finally {
            if (c != null) {
                mSurfaceHolder.unlockCanvasAndPost(c);  }   }   }       }
Author: PaulrBear, 2011-04-20

14 answers

Jak wyczyścić (lub przerysować) całe płótno dla nowego układu (=spróbuj w grze)?

Po Prostu zadzwoń Canvas.drawColor(Color.BLACK), lub jaki kolor chcesz wyczyścić Canvas.

I: jak zaktualizować tylko część ekranu ?

Nie ma takiej metody, która po prostu aktualizuje "część ekranu", ponieważ system operacyjny Android przerysowuje każdy piksel podczas aktualizacji ekranu. Ale kiedy nie czyścisz starych rysunków na swojej Canvas, Stare rysunki są nadal na powierzchni i jest to prawdopodobnie jeden ze sposobów na "aktualizację tylko części" ekranu.

Więc, jeśli chcesz "zaktualizować część ekranu", po prostu unikaj wywoływania metody Canvas.drawColor().

 67
Author: Wroclai,
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
2011-04-20 12:22:05

Narysuj przezroczysty kolor z trybem przezroczystym PorterDuff robi to, co chciałem.

Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
 252
Author: Sileria,
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-06-04 13:37:35

Znalazłem to w google groups i to działało dla mnie..

Paint clearPaint = new Paint();
clearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, width, height, clearPaint); 

To usuwa prostokąty rysunków itp. zachowując ustawioną bitmapę..

 25
Author: Rukmal Dias,
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-09-04 12:13:42

Próbowałem odpowiedzieć @mobistry:

canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);

Ale to nie działa na mnie. Dla mnie rozwiązaniem było:

canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);

Może ktoś ma ten sam problem.
 15
Author: Derzu,
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-05-21 04:47:21
mBitmap.eraseColor(Color.TRANSPARENT);

canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
 11
Author: heMac,
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-03-04 10:19:11

Użyj metody resetowania klasy Path

Path.reset();
 10
Author: Rakesh,
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
2013-11-06 12:22:27

Proszę wkleić poniższy kod do konstruktora klasy surfaceview extend.............

Kodowanie konstruktora

    SurfaceHolder holder = getHolder();
    holder.addCallback(this);

    SurfaceView sur = (SurfaceView)findViewById(R.id.surfaceview);
    sur.setZOrderOnTop(true);    // necessary
    holder = sur.getHolder();
    holder.setFormat(PixelFormat.TRANSPARENT);

Kodowanie Xml

    <com.welcome.panelview.PanelViewWelcomeScreen
        android:id="@+id/one"
        android:layout_width="600px"
        android:layout_height="312px"
        android:layout_gravity="center"
        android:layout_marginTop="10px"
        android:background="@drawable/welcome" />

Spróbuj powyższy kod...

 3
Author: Hemant Chand Dungriyal,
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-06-22 07:25:37

Dla mnie wywołanie {[1] } lub coś podobnego działa tylko po dotknięciu ekranu. Więc chciałbym wywołać powyższą linię kodu, ale ekran będzie jasne dopiero po dotknięciu ekranu. Zadziałało więc dla mnie wywołanie invalidate(), a następnie init(), które jest wywoływane w czasie tworzenia, aby zainicjować widok.

private void init() {
    setFocusable(true);
    setFocusableInTouchMode(true);
    setOnTouchListener(this);

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(Color.BLACK);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(6);

    mCanvas = new Canvas();
    mPaths = new LinkedList<>();

    addNewPath();
}
 3
Author: Jason Crosby,
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
2015-08-30 19:15:58

Oto kod minimalnego przykładu pokazującego, że zawsze musisz przerysować każdy piksel płótna w każdej klatce.

Ta czynność rysuje nową bitmapę co sekundę na widoku SurfaceView, bez wcześniejszego czyszczenia ekranu. Jeśli go przetestujesz, zobaczysz, że bitmapa nie zawsze jest zapisywana do tego samego bufora, a ekran będzie się zmieniać między tymi dwoma buforami.

Testowałem go na moim telefonie (Nexus S, Android 2.3.3) i na emulatorze (Android 2.2).

public class TestCanvas extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new TestView(this));
    }
}

class TestView extends SurfaceView implements SurfaceHolder.Callback {

    private TestThread mThread;
    private int mWidth;
    private int mHeight;
    private Bitmap mBitmap;
    private SurfaceHolder mSurfaceHolder;

    public TestView(Context context) {
        super(context);
        mThread = new TestThread();
        mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon);
        mSurfaceHolder = getHolder();
        mSurfaceHolder.addCallback(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        mWidth = width;
        mHeight = height;
        mThread.start();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {/* Do nothing */}

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mThread != null && mThread.isAlive())
            mThread.interrupt();
    }

    class TestThread extends Thread {
        @Override
        public void run() {
            while (!isInterrupted()) {
                Canvas c = null;
                try {
                    c = mSurfaceHolder.lockCanvas(null);
                    synchronized (mSurfaceHolder) {
                        c.drawBitmap(mBitmap, (int) (Math.random() * mWidth), (int) (Math.random() * mHeight), null);
                    }
                } finally {
                    if (c != null)
                        mSurfaceHolder.unlockCanvasAndPost(c);
                }

                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    interrupt();
                }
            }
        }   
    }
}
 2
Author: Guillaume Brunerie,
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
2011-04-20 13:41:12

Płótno.drawColor (Color.Przezroczysty, PorterDuff.Mode.CLEAR)

 2
Author: dileep krishnan,
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
2018-01-11 06:08:44
canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);
 1
Author: aliakbarian,
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
2017-03-05 07:39:05

Aby wyczyścić płótno (zablokować, narysować i odblokować), musiałem użyć osobnego przejścia do rysowania:

Canvas canvas = null;
try {
    canvas = holder.lockCanvas();
    if (canvas == null) {
        // exit drawing thread
        break;
    }
    canvas.drawColor(colorToClearFromCanvas, PorterDuff.Mode.CLEAR);
} finally {
    if (canvas != null) {
        holder.unlockCanvasAndPost(canvas);
    }
}
 0
Author: Farid Z,
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
2018-08-12 18:51:53

Twoje pierwsze Wymaganie, jak wyczyścić lub przerysować całe płótno-Odpowiedz-użyj płótna.drawColor (color.Czarny) metoda czyszczenia ekranu z kolorem czarnym lub cokolwiek określisz .

Twoje drugie Wymaganie, jak zaktualizować część odpowiedzi na ekranie - na przykład, jeśli chcesz zachować wszystkie inne rzeczy niezmienione na ekranie, ale na małym obszarze ekranu, aby pokazać liczbę całkowitą (powiedzmy licznik), która zwiększa się po pięciu sekundach. następnie użyj canvas.metoda drawrect aby to narysować mały obszar, określając lewy górny prawy dolny i paint. następnie Oblicz wartość licznika (używając postdalayed przez 5 sekund itp., llike Handler.postDelayed (Runnable_Object, 5000);), przekonwertuj go na ciąg tekstowy, Oblicz współrzędną x i y w tym małym rect i użyj widoku tekstowego, aby wyświetlić zmieniającą się wartość licznika.

 -1
Author: Chandu,
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
2013-04-08 01:28:11

Po Prostu zadzwoń

Płótno.drawColor (Color.Przezroczysty)

 -3
Author: reznic,
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
2011-11-29 09:20:20