Android, холст: как очистить (удалить содержимое) холст (= растровые изображения), находящиеся в SurfaceView? - PullRequest
86 голосов
/ 20 апреля 2011

Чтобы сделать простую игру, я использовал шаблон, который рисует холст с растровыми изображениями, подобными этому:

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

(холст определен в «run ()» / SurfaceView живет вGameThread.)

Мой первый вопрос: как очистить (или перерисовать) целое полотно для нового макета?
Во-вторых, как мне обновить только часть экрана??

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

Ответы [ 13 ]

266 голосов
/ 04 июня 2012

Рисование прозрачного цвета с помощью режима очистки PorterDuff делает то, что я хотел.

Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
71 голосов
/ 20 апреля 2011

Как очистить (или перерисовать) ВЕСЬ холст для нового макета (= попробовать в игре)?

Просто позвоните Canvas.drawColor(Color.BLACK),или любым другим цветом, который вы хотите очистить Canvas.

И: как мне обновить только часть экрана?

Нет такого метода, которыйпросто обновите «часть экрана», так как ОС Android перерисовывает каждый пиксель при обновлении экрана.Но когда вы не очищаете старые рисунки на Canvas, старые рисунки все еще находятся на поверхности, и это, вероятно, один из способов «обновить только часть» экрана.

Итак, еслиВы хотите "обновить часть экрана", просто избегайте вызова метода Canvas.drawColor().

29 голосов
/ 04 сентября 2012

Нашел это в группах Google, и это сработало для меня ..

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

При этом удаляются прямоугольники с рисунками и т. Д. При сохранении установленного растрового изображения.

18 голосов
/ 21 мая 2014

Я попробовал ответ @mobistry:

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

Но у меня это не сработало.

Решение для меня было:

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

Возможно, у кого-то есть такая же проблема.

12 голосов
/ 06 ноября 2013

используйте метод сброса класса Path

Path.reset();
12 голосов
/ 02 ноября 2012
mBitmap.eraseColor(Color.TRANSPARENT);

canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
4 голосов
/ 22 июня 2012

, пожалуйста, вставьте код ниже в конструктор класса расширения поверхности .............

конструктор кодирования

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

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

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" />

попробуйте код выше ...

3 голосов
/ 30 августа 2015

Для меня вызов Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR) или что-то подобное будет работать только после того, как я коснусь экрана. Я бы назвал приведенную выше строку кода, но экран очистится только после того, как я коснусь экрана. Поэтому для меня сработало вызов invalidate() с последующим init(), который вызывается во время создания для инициализации представления.

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 голосов
/ 20 апреля 2011

Вот код минимального примера, показывающий, что вам всегда нужно перерисовывать каждый пиксель холста в каждом кадре.

Это действие рисует новый битовый рисунок каждую секунду в SurfaceView, не очищая экран перед этим.,Если вы протестируете его, вы увидите, что растровое изображение не всегда записывается в один и тот же буфер, и экран чередуется между двумя буферами.

Я тестировал его на своем телефоне (Nexus S, Android 2.3.3) и на эмуляторе (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 голосов
/ 05 марта 2017
canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);
...