Android, 캔버스 : 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); } } } }
새 레이아웃을 위해 전체 캔버스를 지우거나 다시 그리려면 어떻게합니까 (= 게임에서 시도)?
을 호출 Canvas.drawColor(Color.BLACK)
하거나 지우고 싶은 색상을 선택하세요 Canvas
.
그리고 : 화면의 일부만 업데이트하려면 어떻게해야합니까?
Android OS는 화면을 업데이트 할 때 모든 픽셀을 다시 그리기 때문에 "화면의 일부"만 업데이트하는 방법은 없습니다. 그러나에서 이전 그림을 지우지 않을 때 Canvas
이전 그림이 여전히 표면에 남아 있으며 이는 아마도 화면의 "일부만 업데이트"하는 한 가지 방법 일 것입니다.
따라서 "화면의 일부를 업데이트"하려면 Canvas.drawColor()
메서드 호출을 피하십시오 .
PorterDuff 클리어 모드로 투명한 색상을 그립니다.
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);
어쩌면 어떤 사람은 같은 문제를 가지고있을 것입니다.
경로 클래스의 재설정 방법 사용
Path.reset();
mBitmap.eraseColor(Color.TRANSPARENT);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
please paste below code on surfaceview extend class constructor.............
constructor coding
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 coding
<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" />
try above code...
Here is the code of a minimal example showing that you always have to redraw every pixel of the Canvas at each frame.
This activity draw a new Bitmap every second on the SurfaceView, without clearing the screen before. If you test it, you will see that the bitmap is not always written to the same buffer, and the screen will alternate between the two buffers.
I tested it on my phone (Nexus S, Android 2.3.3), and on the emulator (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();
}
}
}
}
}
For me calling Canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
or something similar would only work after I touch the screen. SO I would call the above line of code but the screen would only clear after I then touched the screen. So what worked for me was to call invalidate()
followed by init()
which is called at the time of creation to initialize the view.
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();
}
canvas.drawColor(Color.TRANSPARENT, Mode.MULTIPLY);
Don't forget to call invalidate();
canvas.drawColor(backgroundColor);
invalidate();
path.reset();
With the following approach, you can clear the whole canvas or just a part of it.
Please do not forget to disable Hardware acceleration since PorterDuff.Mode.CLEAR doesn’t work with hardware acceleration and finally call setWillNotDraw(false)
because we override the onDraw
method.
//view's constructor
setWillNotDraw(false);
setLayerType(LAYER_TYPE_HARDWARE, null);
//view's onDraw
Paint TransparentPaint = new Paint();
TransparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawRect(0, 0, width, height, TransparentPaint);
Your first requirement, how to clear or redraw whole canvas - Answer - use canvas.drawColor(color.Black) method for clearing the screen with a color of black or whatever you specify .
Your second requirement, how to update part of the screen - Answer - for example if you want to keep all other things unchanged on the screen but in a small area of screen to show an integer(say counter) which increases after every five seconds. then use canvas.drawrect method to draw that small area by specifying left top right bottom and paint. then compute your counter value(using postdalayed for 5 seconds etc., llike Handler.postDelayed(Runnable_Object, 5000);) , convert it to text string, compute the x and y coordinate in this small rect and use text view to display the changing counter value.
I had to use a separate drawing pass to clear the canvas (lock, draw and unlock):
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);
}
}
Just call
canvas.drawColor(Color.TRANSPARENT)
'IT story' 카테고리의 다른 글
EditText의 Drawable 권한에 대한 onClickListener 설정 (0) | 2020.09.12 |
---|---|
Java에서 사후 증가 (i ++) 및 사전 증가 (++ i) 연산자는 어떻게 작동합니까? (0) | 2020.09.12 |
UIButton의 이미지를 AspectFit으로 조정 하시겠습니까? (0) | 2020.09.12 |
코드 골프 : Collatz 추측 (0) | 2020.09.12 |
읽을 수있는 / 계층 적 형식으로 배열 표시 (0) | 2020.09.12 |