Android, canvas: Как очистить (удалить содержимое) холст (= растровые изображения), живущий в surfaceView?



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



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

14 ответов:

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

просто позвони Canvas.drawColor(Color.BLACK), или любой цвет вы хотите очистить свой Canvas С.

и: как я могу обновить только часть экрана ?

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

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

нарисуйте прозрачный цвет с PorterDuff clear mode делает трюк для того, что я хотел.

Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)

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

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

Это удаляет рисунков, прямоугольников и т. д. при сохранении набора растрового изображения..

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

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

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

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

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

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

mBitmap.eraseColor(Color.TRANSPARENT);

canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

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

Path.reset();

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

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

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

попробовать выше код...

для меня вызов 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();
}

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

это действие рисует новое растровое изображение каждую секунду на 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();
                }
            }
        }   
    }
}

холст.drawColor(цвет.Прозрачная, Портер-Дафф.Режим.Ясно)

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

мне пришлось использовать отдельный чертеж прохода, чтобы очистить холст (блокировка и разблокировка):

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

ваше первое требование, как очистить или перерисовать весь холст-ответ - использовать холст.drawColor(цвет.Черный) метод для очистки экрана с цветом черного или все, что вы укажете .

ваше второе требование, как обновить часть экрана-ответ - например, если вы хотите сохранить все остальные вещи неизменными на экране, но в небольшой области экрана, чтобы показать целое число(скажем, счетчик), которое увеличивается через каждые пять секунд. затем используйте холст.drawrect метод для рисования это небольшая область, указав левую верхнюю правую нижнюю и краску. затем вычислите значение счетчика(используя postdalayed в течение 5 секунд и т. д. мне нравится Хендлер.postDelayed (Runnable_Object, 5000);) , преобразует его в текстовую строку, вычисляет координаты x и y в этом небольшом прямоугольнике и использует текстовое представление для отображения изменяющегося значения счетчика.

просто позвони

холст.drawColor(цвет.Прозрачный)

Comments

    Ничего не найдено.