8. 그래픽 – 2. onTouchEvent에 따른 원과 선 그리기
이번에는 화면에 생성한 뷰를 터치하였을 때 처리를 위한 onTouchEvent 메서드를 재정의하여 원이나 선을 그리는 간단한 앱을 만들어 보아요.

LINE을 1, CIRCLE을 2로 정의하고 현재 어떠한 도형을 선택하였는지 기억하는 정적 멤버 필드 dflag를 선언하고 LINE으로 초기 설정합시다.
final static int LINE=1, CIRCLE=2;
static int dflag = LINE;
onCreateOptionMenu를 재정의하여 LINE과 CIRCLE 메뉴를 추가합니다. 앞에서는 xml 파일에서 메뉴 아이템을 설정하는 방법을 살펴보았는데 여기에서는 java 소스 코드에서 설정하는 방법입니다.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0,LINE,0,"LINE");
menu.add(0,CIRCLE,0,"CIRCLE");
return true;
}
onOptionsItemSelected 메서드를 재정의하여 선택한 아이템 아이드로 그릴 도형을 기억할 dflag 멤버 값을 설정합니다.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
dflag = item.getItemId();
return super.onOptionsItemSelected(item);
}
View를 기반 클래스로 하여 파생한 MyGraphicView 정적 클래스를 내부에 정의합니다.
private static class MyGrphicView extends View {
}
MyGraphicView 클래스에 멤버 필드로 시작 점의 좌표와 끝 점의 좌료를 기억할 멤버 필드를 선언하고 화면 좌표 외부의 값인 -1로 설정하세요.
int sx=-1;
int sy = -1;
int ex = -1;
int ey = -1;
onTouchEvent 메서드를 재정의합니다. 여기에서는 event의 Action값을 얻어와 ACTION_DOWN일 때는 시작 좌표를 설정하고 ACTION_MOVE 혹은 ACTION_UP일 때는 끝 좌표를 설정합니다.
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN: ChangeStartPoint(event); break;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP: ChangeEndPoint(event); break;
}
return true;
}
시작 좌표를 변경하는 메서드에서는 event의 getX 메서드와 getY 메서드를 호출하여 얻은 값으로 시작 좌표를 설정합니다.
private void ChangeStartPoint(MotionEvent event) {
sx = (int)event.getX();
sy = (int)event.getY();
}
끝 좌표를 설정하는 메서드에서도 event의 getX 메서드와 getY 메서드를 호출하여 얻읕 값으로 끝 좌표를 설정합니다. 그리고 무효화 영역을 발생하는 invalidate 메서드를 호출하여 다시 그리게 합니다.
private void ChangeEndPoint(MotionEvent event) {
ex = (int)event.getX();
ey = (int)event.getY();
this.invalidate();
}
이제 onDraw 메서드를 재정의하여 그릴 도형에 따라 선 혹은 원을 그립니다.
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.RED);
int radius = (int)Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ey-sy,2));
switch (dflag){
case LINE: canvas.drawLine(sx,sy,ex,ey,paint);break;
case CIRCLE: canvas.drawCircle(sx,sy,radius,paint); break;
}
}
다음은 MainActivity.java 파일의 소스 코드입니다.
package com.example.ehclub.ex_graphic2;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
public class MainActivity extends AppCompatActivity {
final static int LINE=1, CIRCLE=2;
static int dflag = LINE;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyGrphicView(this));
setTitle("Tiny Paint");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
menu.add(0,LINE,0,"LINE");
menu.add(0,CIRCLE,0,"CIRCLE");
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
dflag = item.getItemId();
return super.onOptionsItemSelected(item);
}
private static class MyGrphicView extends View {
int sx=-1;
int sy = -1;
int ex = -1;
int ey = -1;
public MyGrphicView(Context context){
super(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN: ChangeStartPoint(event); break;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP: ChangeEndPoint(event); break;
}
return true;
}
private void ChangeEndPoint(MotionEvent event) {
ex = (int)event.getX();
ey = (int)event.getY();
this.invalidate();
}
private void ChangeStartPoint(MotionEvent event) {
sx = (int)event.getX();
sy = (int)event.getY();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(3);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.RED);
int radius = (int)Math.sqrt(Math.pow(ex-sx,2)+Math.pow(ey-sy,2));
switch (dflag){
case LINE: canvas.drawLine(sx,sy,ex,ey,paint);break;
case CIRCLE: canvas.drawCircle(sx,sy,radius,paint); break;
}
}
}
}