게임과 같이 복잡하고 빠른 그래픽이 요구되는 애플리케이션에서는 캔버스에 직접 이미지를 그리는 것은 무리가 있기 때문에 그리기 전용의 화면을 제공하는 SurfaceView를 사용해야 한다. SurfaceView에는 다음 장의 화면을 미리 그려두고 그리기가 끝나면 바로 전환하는 더블 버퍼링이란 기능이 있어 처리속도를 빠르게 할 수 있다. 또한 직접적인 그리기 처리는 다른 스레드에서 수행한다. 스레드란 프로그램의 처리 흐름을 말하는데 다른 스레드를 추가함으로써 마치 2개 이상의 처리를 동시에 하는 것과 같은 효과를 줄 수 있다.
1. SurfaceView의 사용법에 대해서 알아본다.
1)SurfaceView를 상속받아서 새로운 클래스를 정의한다.
2)액티비티의 화면으로 SurfaceView를 설정한 후에 새로운 스레드에서 이SurfaceView에 그림을 그린다.
3)SurfaceHolder.Callback을 구현해서 Surface가 생성되고 소멸되는 시점을 알려준다.
cf) class SurfaceViewMyView extends SurfaceView implements SurfaceHolder.Callback{
public void SurfaceCreated(SurfaceHolder holder){
//Surface가 준비되었으므로 스레드를 시작한다.
.
.
.
}
public void SurfaceDestroyed(SurfaceHolder holder){
//Surface가 소멸되었으므로 스레드를 종료한다.
.
.
.
}
public void SurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
//Surface가 변경됨.
.
.
.
}
}
4)SurfaceView 객체는 우리가 직접 처리할 수 없고 반드시 SurfaceHolder를 통하여 처리해야 한다.
SurfaceView 객체가 초기화될 때 getholder()를 호출해서 SurfaceHolder를 얻으면 된다.
cf) SurfaceHolder holder = getHolder();
5)만약 SurfaceHolder의 콜백메서드를 받고 싶다면 addCallback()을 호출한다.
cf) holder.addCallback(this);
6)SurfaceView와 SurfaceHolder의 관계
SurfaceView의 상태제어는 SurfaceHolder의 상태제어를 콜백 메서드로 호출해서 사용하고
SurfaceView의 락제어는 SurfaceHolder의 락제어를 호출해서 사용한다.
7) onDraw() --> draw()
inValidate --> redraw()
※ SurfaceView는 안드로이드의 기본뷰 계층에 포함되지 않기때문에 onDraw()와 inValidate()을 사용할 수
없고 draw()와 redraw()로 대체해야 한다.
2. 애니메이션 프로그램 작성
이제 문자를 오른쪽에서 왼쪽으로 고속으로 스크롤하는 프로그램을 작성해 본다. 물론 위에서 설명한 SurfaceView를 이용한다.
ex)
private class SurfaceViewMyView extends SurfaceView
implements SurfaceHolder.Callback, Runnable{
private SurfaceHolder holder;
private Thread thread;
private int positionX = 0;
private Paint paint = new Paint();
public SurfaceViewMyView (Context context) {
super(context);
holder = getHolder(); // 위의 설명 4)를 참고한다.
holder.addCallback(this); // 5) 참고
}
public void surfaceCreated(Surface holder) { //서피스가 생성될 때 호출되는 메서드.
thread = new Thread(this);
thread.start(); //스레드를 시작한다.
}
public void surfaceDestroyed(SurfaceHolder holder) { //서피스가 소멸될 때 호출되는 메서드.
thread = null;
}
public void surfaceChanged(SurfaceHolder holder, //서피스가 갱신될 때 호출되는 메서드.
int format, int w, int h) {
}
public void run() { // 다른 스레드에서 실행되는 메서드이다.
paint.setTexSize(30);
while(thread != null) { // 루프의 조건을 준다. null이 될때까지 돈다.
Canvas canvas = holder.lockCanvas(); // 뒤 화면 그리기를 시작한다.
if (canvas == null)
break;
canvas.drawColor(Color.WHITE);
canvas.drawText("testTextAnimation", positionX, 100, paint); // 화면에 글자를 출력한다.
holder.unlockCanvasAndPost(canvas); // 뒤 화면 그리기를 종료하고 holder에 반영한다.
positionX -= 20; // 화면의 글자가 20픽셀씩 왼쪽으로 이동하여
if (positionX < 0) // 왼쪽 끝까지 오면
positionX = getwidth(); // 오른쪽 끝으로 돌아간다.
try{ // 예외처리를 둔다.
Thread.sleep(100); // 100밀리초(0.1초) 지연시간을 준다.
}catch (Exception e){ }
}
}
}
'SW 배움터 > 안드로이드' 카테고리의 다른 글
안드로이드 7: 메서드의 정의와 호출 (0) | 2017.06.13 |
---|---|
안드로이드 6: 클래스와 인스턴스화 (0) | 2017.06.12 |
안드로이드4: 스레드 II (0) | 2017.04.19 |
안드로이드3: 이벤트 처리 (0) | 2017.04.17 |
안드로이드2: Activity의 화면 설정 방법 (0) | 2017.04.11 |