안드로이드(Android) SurfaceView 와 Thread 를 이용해여 사각형자동그리기 |
환경 :Eclipse Mars, Android 4.2.2 |
이번예제는 SurfaceView 와 Thread 를 이용해서 사각형이 이동하는 것 같은 그림을 그리게 할 것입니다. Thread 를 이용해 연속적으로 그림을 계속해서 그리게 되는 것이죠. 그림을 그리고 지우는 것이 아니라 배경색을 바꿔서 이전 사각형을 덮어버리기 때문에 이동하는 것 처럼 보이게 되는 것입니다.
▼ 이전 SurfaceView 와 Thread 를 이용해 터치이벤트를 구현한 예제에서 사용한 소스를 조금 손 보았습니다. 먼저 메인 activity 에서 화면의 가로,세로 길이 값을 가져옵니다. 이 두 값의 용도는 사각형이 화면을 벗어나면 다시 처음시작위치에서 그리기 위함입니다.
DisplayMetrics disp = getApplicationContext().getResources().getDisplayMetrics(); deviceWidth = disp.widthPixels; deviceHeight = disp.heightPixels;
▼ 다음은 SurfaceHolder.Callback,SurfaceView 를 상속받은 사용자 정의 클래스에 대한 것입니다. SurfaceHolder.Callback 상속받았기 때문에 3가지 함수는 필히 구현을 해야 합니다. 생성함수에는 스레드 클래스를 시작하는 코드가 있으며 종료함수에는 스레드를 끝내는 코드가 있습니다.
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { } public void surfaceCreated(SurfaceHolder holder) { thread.setRunning(true); thread.start(); } public void surfaceDestroyed(SurfaceHolder holder) { boolean retry = true; thread.setRunning(false); while (retry) { try { thread.join(); retry = false; } catch (InterruptedException e) { } } }
▼ 마지막으로 스레드 클래스에서 run() 함수입니다. 스레드 객체에서 start() 호출하게 되면 run() 이 실행된다는 것은 아실거라 생각합니다. 이곳에 Canvas 사각형을 그리는 기능이 있습니다. 화면을 벗어났는지 체크해서 벗어났으면 Left, Top 위치를 초기화 하는 것이죠.
@Override public void run() { while (myThreadRun) { Canvas c = null; try { c = mThreadSurfaceHolder.lockCanvas(null); synchronized (mThreadSurfaceHolder) { Paint mPaint = new Paint(); mPaint.setColor(Color.WHITE); c.drawRect(0, 0, deviceWidth, deviceHeight, mPaint); mPaint.setColor(Color.RED); c.drawRect(x, x, x - quadWidth, x - quadHeight, mPaint); x += 5; if (x - quadWidth >= deviceWidth) { x = 0; } } } finally { if (c != null) { mThreadSurfaceHolder.unlockCanvasAndPost(c); } } } }
▼ 아래는 메인 activity 의 전체 내용입니다. 메인 activity 에 SurfaceView, Thread 클래스가 모두 들어가 있습니다.
import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Bundle; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.view.SurfaceHolder; import android.view.SurfaceView; public class SurfaceViewRectDrawActivity extends Activity { private static int deviceWidth, deviceHeight; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // setContentView(R.layout.activity_surface_view_draw); EventSufaceView mySurfaceView = new EventSufaceView(this); setContentView(mySurfaceView); DisplayMetrics disp = getApplicationContext().getResources().getDisplayMetrics(); deviceWidth = disp.widthPixels; deviceHeight = disp.heightPixels; } public class EventSufaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceThread thread; @Override public boolean performClick() { return super.performClick(); } public EventSufaceView(Context context) { super(context); init(); } public EventSufaceView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public EventSufaceView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { getHolder().addCallback(this); thread = new SurfaceThread(getHolder(), this); setFocusable(true); // make sure we get key events } public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { } public void surfaceCreated(SurfaceHolder holder) { thread.setRunning(true); thread.start(); } public void surfaceDestroyed(SurfaceHolder holder) { boolean retry = true; thread.setRunning(false); while (retry) { try { thread.join(); retry = false; } catch (InterruptedException e) { } } } } public class SurfaceThread extends Thread { private SurfaceHolder mThreadSurfaceHolder; private EventSufaceView mThreadSurfaceView; private boolean myThreadRun = false; private int x = 0; private int quadWidth = 100; private int quadHeight = 100; public SurfaceThread(SurfaceHolder surfaceHolder, EventSufaceView surfaceView) { mThreadSurfaceHolder = surfaceHolder; mThreadSurfaceView = surfaceView; } public void setRunning(boolean b) { myThreadRun = b; } @Override public void run() { while (myThreadRun) { Canvas c = null; try { c = mThreadSurfaceHolder.lockCanvas(null); synchronized (mThreadSurfaceHolder) { Paint mPaint = new Paint(); mPaint.setColor(Color.WHITE); c.drawRect(0, 0, deviceWidth, deviceHeight, mPaint); mPaint.setColor(Color.RED); c.drawRect(x, x, x - quadWidth, x - quadHeight, mPaint); x += 5; if (x - quadWidth >= deviceWidth) { x = 0; } } } finally { if (c != null) { mThreadSurfaceHolder.unlockCanvasAndPost(c); } } } } } }
'안드로이드 개발' 카테고리의 다른 글
안드로이드(Android) This Handler class should be static or leaks might occur 해결 (6) | 2014.12.21 |
---|---|
안드로이드(Android) Android.graphics.Color 에서 제공하는 컬러보기 샘플구현 (0) | 2014.12.17 |
안드로이드(Android) Activity 의 라이프사이클(LifeCycle) 알아보기위한 예제 (0) | 2014.12.16 |
안드로이드(Android) SurfaceView 와 Thread 이용해 화면에서 움직이는 공구현 (0) | 2014.12.12 |
안드로이드(Android) getWidth() from the type Display is deprecated 수정 (0) | 2014.12.02 |
안드로이드(Android) SurfaceView 와 Thread 를 이용해 화면에 도형표현 하기 (0) | 2014.12.01 |
안드로이드(Android) 두개의 사용자정의 View 를 FrameLayout 으로 표현하기 (0) | 2014.11.30 |
안드로이드(Android) onDraw() 를 이용해 스크린터치로 원그리기 (1) | 2014.11.29 |