서피스뷰

서피스뷰

서피스 뷰

∙ 서피스뷰 ∙화면에 그림을 넣어 자유자재로 움직이게 할 수 있다.

MySurfaceView.java

package com.justice.pingpong; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Point; import android.view.Display; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.WindowManager; class Ball { Context mContext; int x, y; //공의 위치 int dx, dy; //공이 한 번에 움직일 거리 int rad; //공의 반지름 static int max_width; //디바이스 화면의 폭을 저장할 변수 static int max_height; // 디바이스 화면의 높이를 저장할 변수 public Ball(Context context, int rad) { //공 객체를 생성할 때 반지름을 파라미터로 전달해준다. mContext = context; init(rad); //초기화 } public void init(int rad){ //휴대폰 단말의 스크린 폭, 높이 가져와서max_width, max_height에 대입 WindowManager manager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); Display display = manager.getDefaultDisplay(); Point sizePoint = new Point(); display.getSize(sizePoint); max_width = sizePoint.x; max_height = sizePoint.y; this.rad = rad; //반지름 초기화 /* 난수 생성메소드를 사용해서 위치값 및 위치변화량 값 랜덤으로 생성*/ x = (int) (Math.random() * (max_width - rad) + 3); y = (int) (Math.random() * (max_height - rad) + 3); dx = (int)(Math.random()*30 + 1); dy = (int)(Math.random()*30 + 1); } //파라미터로 전달받은 캔버스에 공 그리기 public void drawBall(Canvas canvas){ //왼쪽, 오른쪽 벽에 닿았을 때 if(x < rad || x > max_width - rad){ dx *= -1; //x방향 변경 } //위, 아래 벽에 닿았을 때 if(y < rad || y > max_height - rad){ dy *= -1; //y방향 변경 } //공 위치 이동 x += dx; y += dy; //빨간색 페인트로 공 그리기 Paint paint = new Paint(); paint.setColor(Color.RED); canvas.drawCircle(x, y, rad, paint); } } public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback { SurfaceHolder holder; Thread mThread; Ball balls[]; //공10개를 저장할 배열 생성 Context mContext; public MySurfaceView(Context context) { super(context); init(context); } private void init(Context context){ mContext = context; holder = getHolder(); //서피스뷰 객체 참조 holder.addCallback(this); //콜백 인터페이스 설정 //공 배열에 공 객체 생성 및 저장 balls = new Ball[10]; for(int i=0; i<10; i++){ balls[i] = new Ball(mContext, (int)(Math.random()*50 + 50)); } } @Override /* 서피스뷰 객체 생성시 호출*/ public void surfaceCreated(SurfaceHolder holder) { mThread = new MyThread(holder); //새로운 스레드 생성; ((MyThread) mThread).setThreadRun(true); mThread.start(); //스레드 실행 } @Override /* 서피스뷰 객체 변경시 호출*/ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override /* 서피스뷰 객체 해제 시 호출*/ public void surfaceDestroyed(SurfaceHolder holder) { ((MyThread) mThread).setThreadRun(false); boolean retry = true; /* 스레드 메인스레드에 다시 합치기*/ while(retry){ try{ mThread.join(); //메인 스레드에 합치기 retry = false; }catch(InterruptedException e){ e.printStackTrace(); } } } //내부 클래스로 스레드 정의 public class MyThread extends Thread{ SurfaceHolder surHolder; private boolean threadRun = true; public MyThread(SurfaceHolder holder){ surHolder = holder; } @Override public void run() { while(threadRun){ Canvas canvas = null; try{ canvas = surHolder.lockCanvas(null); //서피스홀더의 캔버스 객체 참조 canvas.drawColor(Color.BLUE); // 캔버스 배경 파란색으로 설정 synchronized (surHolder){ for(Ball ball : balls){ ball.drawBall(canvas);//캔버스에 공 그리기 } } }finally{ if(canvas != null){ surHolder.unlockCanvasAndPost(canvas); // 화면에 그려진 뷰 표시하기 } } } } public void setThreadRun(boolean threadRun) { this.threadRun = threadRun; } } }

MainActivity.java

package com.justice.pingpong; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity { MySurfaceView view; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(saavedInstanceState); view = new MySurfaceView(this); setContentView(view); } @Override protected void onPause() { super.onPause(); } protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); } }

실행결과

from http://kimm6094.tistory.com/43 by ccl(A) rewrite - 2021-09-09 11:01:33