Android SurfaceView Drawing example
안드로이드에서 SurfaceView를 이용하여 터치 이벤트로 화면에 그리는 예
SurfaceView에서는 onDraw()와 같이 자동으로 호출되는 그리기용 메소드가 없기 때문에 직접 호출해야 한다.
MainActivity.java
package com.example.androidapp; import android.app.Activity; import android.graphics.Point; import android.os.Bundle; import android.util.Log; import android.view.MotionEvent; import android.widget.TextView; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new DrawingSurface(this)); } }
DrawingSurface.java
package com.example.androidapp; 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.Matrix; import android.graphics.Paint; import android.graphics.Paint.Cap; import android.graphics.Rect; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.Toast; public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback { Canvas cacheCanvas; Bitmap backBuffer; int width, height, clientHeight; Paint paint; Context context; SurfaceHolder mHolder; public DrawingSurface(Context context) { super(context); this.context = context; init(); } public DrawingSurface(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; init(); } private void init() { mHolder = getHolder(); mHolder.addCallback(this); } int lastX, lastY, currX, currY; boolean isDeleting; @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); int action = event.getAction(); switch(action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: lastX = (int) event.getX(); lastY = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: if(isDeleting) break; currX = (int) event.getX(); currY = (int) event.getY(); cacheCanvas.drawLine(lastX, lastY, currX, currY, paint); lastX = currX; lastY = currY; break; case MotionEvent.ACTION_UP: if(isDeleting) isDeleting = false; break; case MotionEvent.ACTION_POINTER_DOWN: cacheCanvas.drawColor(Color.WHITE); isDeleting = true; break; case MotionEvent.ACTION_POINTER_UP: break; } draw(); // SurfaceView에 그리는 기능을 직접 호출해야 한다 return true; } protected void draw() { if(clientHeight==0) { clientHeight = getClientHeight(); height = clientHeight; backBuffer = Bitmap.createBitmap( width, height, Bitmap.Config.ARGB_8888); cacheCanvas.setBitmap(backBuffer); cacheCanvas.drawColor(Color.WHITE); } Canvas canvas = null; try{ canvas = mHolder.lockCanvas(null); //back buffer에 그려진 비트맵을 스크린 버퍼에 그린다 canvas.drawBitmap(backBuffer, 0,0, paint); }catch(Exception ex){ ex.printStackTrace(); }finally{ if(mHolder!=null) mHolder.unlockCanvasAndPost(canvas); } } /* 상태바, 타이틀바를 제외한 클라이언트 영역의 높이를 구한다 */ private int getClientHeight() { Rect rect= new Rect(); Window window = ((Activity)context).getWindow(); window.getDecorView().getWindowVisibleDisplayFrame(rect); int statusBarHeight= rect.top; int contentViewTop= window.findViewById(Window.ID_ANDROID_CONTENT).getTop(); int titleBarHeight= contentViewTop - statusBarHeight; return ((Activity)context).getWindowManager().getDefaultDisplay(). getHeight() - statusBarHeight - titleBarHeight; } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } public void surfaceCreated(SurfaceHolder holder) { width = getWidth(); height = getHeight(); cacheCanvas = new Canvas(); backBuffer = Bitmap.createBitmap( width, height, Bitmap.Config.ARGB_8888); // back buffer cacheCanvas.setBitmap(backBuffer); cacheCanvas.drawColor(Color.WHITE); paint = new Paint(); paint.setColor(Color.BLUE); paint.setStrokeWidth(10); paint.setStrokeCap(Paint.Cap.ROUND); paint.setStrokeJoin(Paint.Join.ROUND); draw(); } public void surfaceDestroyed(SurfaceHolder holder) { } }