본문 바로가기

Android/SurfaceView Ani example

SurfaceView Animation example

Android에서 제공하는 SurfaceView는 Double Buffering을 지원하는 API 클래스이다. Double Buffering은 여기를 참조하세요
SurfaceView에는 SurfaceHolder를 전달해주는 라이프사이클 메소드가 있으므로 SurfaceHolder.lockCanvas(null)을 이용하면 Canvas이 참조를 얻을 수 있는데, 이 Canvas를 SurfaceView의 onDraw()에 아규먼트로 전달하여 호출하면 Back Buffer에 그래픽 데이터를 기록할 수 있다.

참고로 Back Buffer에 해당하는 Canvas를 얻고 SurfaceView의 onDraw()에 전달하는 기능은 Thread클래스에서 할 것을 구글에서 권하고 있다.

canvas = SurfaceHolder.lockCanvas(null);
SurfaceView.onDraw(canvas); // Double Buffering시스템의 Back Buffer에 그래픽 데이터를 그린다
SurfaceHolder.unlockCanvasAndPost(canvas);

SurfaceViewAnimation.java
package com.ojtit.android.surfaceview.test;
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.graphics.Paint;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
import android.widget.LinearLayout;
 
public class SurfaceViewAnimation extends Activity {
       
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                LinearLayout lLayout = new LinearLayout(getApplicationContext());
                MyDraw mydraw = new MyDraw(getApplicationContext());
                lLayout.addView(mydraw);
                setContentView(lLayout);
        }
        class MyDraw extends SurfaceView implements Callback {
               
                private MyThread myThread;
                private Bitmap bmp;
                private SurfaceHolder holder;
                private Paint paint;
                private int x = 50;
                private int y = 50;            
                int newX = 50;
                int newY = 50;
                int diffX = newX - x;
                int diffY = newY - y;
                int incrX = -1;
                int incrY = -1;
                public MyDraw(Context context) {
                        super(context);
                        holder = getHolder();
                        holder.addCallback(this);
                        paint = new Paint();           
                        bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
                }
 
                public void surfaceChanged(SurfaceHolder holder, int format, int width,
                                int height) {
                       
                }
               
                public void surfaceCreated(SurfaceHolder holder) {
                        myThread = new MyThread(holder, this);
                        myThread.setFlag(true);
                        myThread.start();
                }
 
                public void surfaceDestroyed(SurfaceHolder holder) {
                       
                }
       
                @Override
                public boolean onTouchEvent(MotionEvent event) {
                        if(event.getAction() == MotionEvent.ACTION_DOWN) {
                                newX = (int) event.getX();
                                newY = (int) event.getY();
                                diffX = newX - x;
                                diffY = newY - y;
                        }
                        return true;
                }
                @Override
                protected void onDraw(Canvas canvas) {
                        canvas.drawColor(Color.BLACK);
                       
                        super.onDraw(canvas);                  
                        diffX = newX - x;
                        diffY = newY - y;
                       
                        if(diffX < 0){
                                incrX = 1;
                        }
                        else if(diffX > 0) {
                                incrX = 0;
                        }
                        else {
                                incrX = -1;
                        }
                       
                        if(diffY < 0){
                                incrY = 1;
                        }
                        else if(diffY > 0){
                                incrY = 0;
                        }
                        else {
                                incrY = -1;
                        }
                       
                        if(diffX != 0){
                                if(incrX == 0){
                                        x++;
                                }
                                else if(incrX == 1){
                                        x--;
                                }
                        }
                        if(diffY != 0){
                                if(incrY == 0){
                                        y++;
                                }
                                else if(incrY == 1){
                                        y--;
                                }
                        }
                        canvas.drawBitmap(bmp, x, y, paint);
                       
                }
        }
       
        class MyThread extends Thread {        
                boolean flag ;
                SurfaceHolder myHolder;
                MyDraw myDraw;
                public MyThread(SurfaceHolder holder , MyDraw drawMain) {
                        myHolder = holder;
                        myDraw = drawMain;
                }
               
                public void setFlag (boolean myFlag) {
                        flag = myFlag;
                }
                public void run(){
                        Canvas canvas = null;
                        while(flag) {
                                try {
                                        canvas = myHolder.lockCanvas(null);
                                        myDraw.onDraw(canvas);
                                }
                                finally{
                                        if(canvas != null){
                                                myHolder.unlockCanvasAndPost(canvas);
                                        }
                                }
                        }
                }
        }
}