본문 바로가기

Android/2D 그래픽스

[Android] Invalidate 화면을 갱신한다.

View에서 onDraw() 가 호출 된 이후, 화면은 더 이상 갱신되지 않은채로 남아있게 된다. 하지만 애니메이션등 기타 효과들을 구현하기 위해서는 이벤트에 따라 화면을 갱신 할 필요가 있다.

invalidate()
     Invalidate the whole view.

postInvalidate()

Cause an invalidate to happen on a subsequent cycle through the event loop.


위의 두 메소드가 View의 화면을 갱신하는데에 이용이된다. invalidate의 API설명을 읽어보면 "전체 뷰의 무효화"라고 되어있다. 즉 현재 View에 나타나 있는 모든 그림 및 이미지들을 무효화해서 화면에 나타나지 않게 한다는 것이다. 뷰를 무효화 한 후에는 다시 화면을 그리기 위해 onDraw를 호출하는 것이다.

아래의 postInvalidate도 invalidate와 동일한 역할을 수행하지만 약간의 차이점을 가지고 있다. invalidate는 thread내부에서는 작동을 할 수 없게 되어있다. 따라서 invalidate만 가지고서는 타이머를 이용한 애니메이션의 구현이 가능하지 않게 되는것이다.(단, Handler를 사용하면 invalidate를 이용하여 화면을 재구성 하는것이 가능하다.) 이 때 사용되는 것이 postInvalidate이다. 

다음에 나오는 예제 코드는 터치 이벤트를 감지하여 Touch UP이 되었을 때 화면을 재구성 하도록 구현된 코드이다. count값으로 draw를 제어하여, invalidate가 호출 될 때마다 화면은 초기화 된다는 것을 증명한다.


package com.cashyalla.graphics;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;

public class InvalidateTest extends View {

	/** onDraw에서 한번만 그리기를 제어하기 위한 변수 */
	int count = 0;
	
	Paint mPaint;
	
	public InvalidateTest(Context context) {
		super(context);
		
		mPaint = new Paint();
		// 계단 현상을 감소시킨다.
		mPaint.setAntiAlias(true);
		mPaint.setColor(Color.RED);
	}
	
	/**
	 * 
	 * onDraw가 호출이 되면 화면은 다시 아무것도 없는 상태로 초기화가 된다.
	 * 때문에 count의 값이 홀수가 되어버리면 원을 그리지 않아 View에는
	 * 아무것도 나타나지 않게 된다.
	 * 
*/ @Override protected void onDraw(Canvas canvas) { if (count % 2 == 0) { canvas.drawCircle(getWidth() / 2, getHeight() / 2, 100, mPaint); } count++; } @Override public boolean onTouchEvent(MotionEvent event) { // 터치 up이 되었을 때 화면을 갱신한다. switch (event.getAction()) { case MotionEvent.ACTION_UP : // invalidate()을 호출하면 화면을 갱신한다. invalidate(); break; } return true; } }

위에 예제를 실행시켜 화면 터치를 반복해보면 붉은 원이 나타났다 사라졌다를 반복하는 것을 알 수 있다.