관리 메뉴

moozi

그래픽 2D 3 - SurfaceView 활용 2 본문

안드로이드개발강좌

그래픽 2D 3 - SurfaceView 활용 2

moozi 2010. 3. 8. 22:06


이번 강좌는 지난 강좌  '[ 안드로이드 개발 2.0 ] 그래픽 2D 2 - SurfaceView 활용 1' 에서 이어 집니다.


1. CustomViewThread 클래스의 run() 메서드를 다음과 같이 작성합니다.

@Override
        public void run() {
            Canvas c;
            while (running) {
                c = null;
                try {
                    c = surfaceholder.lockCanvas(null);
                    synchronized (surfaceholder) {
                        customview.onDraw(c);
                    }
                } finally {
                   
                    if (c != null) {
                        surfaceholder.unlockCanvasAndPost(c);
                    }
                }
            }
        }

코드를 보면,

먼저 Canvas 오브젝트를 만든다음, running 멤버변수로 루프를 돌면서 Canvas객체를 이용해 그림을 그립니다.

여기서 그림을 그리는 순서를 요약해보면,

1. canvas를 잠금 -  lockCanvas
2. 그림을 그림 - customview.onDraw(c); 이 때 surfaceholder 를 동기화하여 처리
3. canvas의 잠금을 품 - unlockCanvasAndPost

와 같습니다.


2. CustomView 클래스의 생성자에서 CustomViewThread 객체를 생성하고,  surfaceCreated 메서드와 surfaceDestroyed 메서드에서 이 Thread객체를 사용하도록 다음과 같이 작성합니다.

class CustomView extends SurfaceView implements SurfaceHolder.Callback {
        private CustomViewThread CVThread;  // CustomViewThread 객체 선언
        public CustomView(Context context) {
            super(context);
            getHolder().addCallback(this);
            CVThread = new CustomViewThread(getHolder(), this); // CustomViewThread 객체 생성
        }
 
        @Override
        public void onDraw(Canvas canvas) {
         Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
            canvas.drawColor(Color.parseColor("#dedede"));
            canvas.drawBitmap(bm, 70, 70, null);
        }
 
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            // TODO Auto-generated method stub
 
        }
 
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            CVThread.setRunning(true);  // running 의 값을 true로 저장
          CVThread.start(); // thread 시작
        }
 
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
           
            boolean retry = true;
            CVThread.setRunning(false); //running 의 값을 false로 저장

            while (retry) {
                try {
                    CVThread.join(); // Thread 종료될 때까지 기다림
                    retry = false;
                } catch (InterruptedException e) {
                   
                }
            }
        }
    }

코드를 보면 생성자에서 CVThread 쓰레드 객체를 만들고, surfaceCreated 메서드에서 CVThread 쓰레드를 start하고, surfaceDestroyed 메서드에서 running 의 값을 false로 바꾸고 CVThread 쓰레드가 종료할 때까지 기다립니다.


3. 지금까지 작성된 코드의 완성된 모습은 다음과 같습니다.

package my.MyGraphics2D02;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;

public class MyGraphics2D02 extends Activity {
 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(new CustomView(this));
    }
 
    class CustomView extends SurfaceView implements SurfaceHolder.Callback {
        private CustomViewThread CVThread;
 
        public CustomView(Context context) {
            super(context);
            getHolder().addCallback(this);
            CVThread = new CustomViewThread(getHolder(), this);
        }
 
        @Override
        public void onDraw(Canvas canvas) {
         Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
            canvas.drawColor(Color.parseColor("#dedede"));
            canvas.drawBitmap(bm, 70, 70, null);
        }
 
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            // TODO Auto-generated method stub
 
        }
 
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            CVThread.setRunning(true);
            CVThread.start();
        }
 
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
           
            boolean retry = true;
            CVThread.setRunning(false);
            while (retry) {
                try {
                    CVThread.join();
                    retry = false;
                } catch (InterruptedException e) {
                   
                }
            }
        }
    }
 
    class CustomViewThread extends Thread {
        private SurfaceHolder surfaceholder;
        private CustomView customview;
        private boolean running = false;
 
        public CustomViewThread(SurfaceHolder surfaceHolder, CustomView CustomView) {
            surfaceholder = surfaceHolder;
            customview = CustomView;
        }
 
        public void setRunning(boolean run) {
            running = run;
        }
 
        @Override
        public void run() {
            Canvas c;
            while (running) {
                c = null;
                try {
                    c = surfaceholder.lockCanvas(null);
                    synchronized (surfaceholder) {
                        customview.onDraw(c);
                    }
                } finally {
                   
                    if (c != null) {
                        surfaceholder.unlockCanvasAndPost(c);
                    }
                }
            }
        }
    }
}


4.  Ctrl + F11 로 실행합니다.

[ 실행결과 ]

실행결과는  '[ 안드로이드 개발 2.0 ] 그래픽 2D 1 - 안드로이드 아이콘 띄우기, 커스텀뷰 활용' 과 같이 안드로이드 마스코트 아이콘이 화면에 출력됩니다.


( 참고 : http://www.droidnova.com/playing-with-graphics-in-android-part-ii,160.html )

Comments