티스토리 뷰



이 자료들은 팁스소프트에서 제공하는 [ 알짜배기 ] 프로그램을 이용하면 더 편리하게 볼수 있습니다.
* 알짜배기 프로그램 받기 - http://www.tipssoft.com/bulletin/tb.php/QnA/8406
* 안드로이드 강좌 목록 - http://www.tipssoft.com/bulletin/tb.php/old_bbs/501
이번 자료에서는 사용자 정의 뷰를 생성하여 해당 뷰에 터치 행위가 발생하였을 때 텍스트뷰에 좌표를
출력하고, 사용자 정의 뷰에는 해당 위치에 빨간 원을 그리는 예제를 다루도록 하겠습니다.
이 예제를 정확하고 쉽게 이해하기 위해서는 사용자 정의 뷰를 생성하고 배치하는 방법과 그림그리기의
기초적인 지식 그리고 터치 이벤트 핸들러에 대한 지식이 필요하므로 아래의 자료를 먼저 보시는 것이
좋습니다.
사용자정의 뷰 생성 및 배치1 - http://www.tipssoft.com/bulletin/tb.php/FAQ/964
그림그리기의 기초와 구조 - http://www.tipssoft.com/bulletin/tb.php/FAQ/971
사용자조작(터치) 처리하기 - http://www.tipssoft.com/bulletin/tb.php/FAQ/973
1. 실행 화면
이 예제에는 하나의 액티비티에 텍스트뷰와 사용자 정의 뷰가 배치되어 있으며 매우 간단한 사용자
조작 화면을 가지고 있습니다. 아래의 그림은 예제의 실행 화면이며 하얀색 뷰에 터치가 발생하면
빨강색 원이 그려지고, 상단의 텍스트뷰에는 현재 터치된 뷰의 좌표가 출력됩니다.
2. 주요 소스 코드
이 예제는 텍스트뷰와 사용자 정의 뷰를 관리하는 TipsDrawableActivity 클래스와 터치가 발생했을 때
해당 좌표에 원 그리기 행위를 하는 TipsView 클래스로 구성되어 있습니다.
TipsView 클래스에서 터치 이벤트가 발생하면 좌표 정보를 얻어서 텍스트뷰에 전달해야 하는데
이 정보를 TipsView 클래스 내에서 직접 얻으면 텍스트뷰에게 전달하기가 번거로워지므로
액티비티가 터치 이벤트를 처리할 수 있도록 액티비티에 터치 이벤트 리스너를 구현하여 리스너에서
좌표 정보를 얻습니다. 이 때 TipsView 클래스에서는 좌표 정보를 이용하여 그림 그리기를 수행해야
하기 때문에 터치 콜백 메소드로 다시 터치 이벤트를 처리할 수 있도록 리스너의 반환값은 false 로
명시해야 합니다.
2.1 TipsDrawableActivity
액티비티 클래스에서는 좌표 정보를 얻어서 텍스트뷰에 출력하는 역할을 수행합니다.

// Activity 클래스를 상속받은 사용자 정의 액티비티에 OnTouchListener 를 구현한다.
public class TipsDrawableActivity extends Activity implements OnTouchListener
{
// 좌표를 출력할 텍스트뷰
private TextView m_text_view = null;
// 터치 위치에 원이 그려지는 사용자 정의 뷰
private TipsView m_tips_view = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// XML 파일에 정의한대로 레이아웃을 설정한다.
setContentView(R.layout.main);
// 리소스 파일에 정의된 is_tv 라는 ID의 텍스트뷰를 얻어온다.
m_text_view = (TextView) findViewById(R.id.id_tv);
// 텍스트뷰에 문자열을 출력한다.
m_text_view.setText("Touch Touch!!");

// 리소스 파일에 정의된 id_view 라는 ID 의 사용자정의뷰를 얻어온다.
m_tips_view = (TipsView) findViewById(R.id.id_view);
// 사용자정의 뷰에 이 클래스에서 구현한 리스너를 등록한다.
m_tips_view.setOnTouchListener(this);
}
// 터치 리스너를 구현하는 onTouch 메소드
public boolean onTouch(View v, MotionEvent event)
{
// 어떤 이벤트가 발생하였는지에 따라 처리가 달라진다.
switch (event.getAction()) {
// DOWN 이나 MOVE 가 발생한 경우
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
// 터치가 발생한 X, Y 의 각 좌표를 얻는다.
float x = event.getX();
float y = event.getY();
String str;
// 좌표값을 이용하여 문자열을 구성한다.
str = "Coordinate : ( " + (int)x + ", " + (int)y + " )";
// 구성한 문자열을 텍스트뷰에 출력한다.
m_text_view.setText(str);
break;
case MotionEvent.ACTION_UP:
// UP 이 발생한 경우 문자를 출력한다.
m_text_view.setText("Touch Touch!!");
break;
}
// false 를 반환하여 뷰 내에 재정의한 onTouchEvent 메소드로 이벤트를 전달한다.
return false;
}
}
2.2 TipsView
TipsView 클래스에서는 좌표 정보를 얻어서 해당 좌표에 그리기 작업을 수행합니다.

// View 클래스를 상속받은 사용자 정의 뷰
public class TipsView extends View
{
// 원을 그릴 때 사용할 속성 paint
private Paint m_paint = null;
// 원을 그릴 좌표를 저장할 변수
private float m_x = -1, m_y = -1;

// 소스코드로 뷰가 생성되면 호출되는 생성자
public TipsView(Context c)
{
super(c);

// 빨강색 속성을 가진 Paint 객체 생성
m_paint = new Paint();
m_paint.setAntiAlias(true);
m_paint.setColor(Color.RED);
}

// XML 리소스 파일로 뷰가 생성되면 호출되는 생성자
public TipsView(Context c, AttributeSet attrs)
{
super(c, attrs);
// 빨강색 속성을 가진 Paint 객체 생성
m_paint = new Paint();
m_paint.setAntiAlias(true);
m_paint.setColor(Color.RED);
}

// 뷰에 그림그리는 행위를 담당하는 메소드
protected void onDraw(Canvas canvas)
{
// 뷰의 배경색을 흰색으로 칠한다.
canvas.drawColor(Color.WHITE);

// 터치 행위가 발생한 경우 해당 위치에 원을 그린다.
if(m_x > 0 && m_y > 0) {
// (x - 5, y - 5) 를 시작으로 지름이 10인 원을 그린다.
canvas.drawCircle(m_x - 5, m_y - 5, 10, m_paint);
}
}

// 터치 이벤트를 처리하는 콜백 메소드
public boolean onTouchEvent(MotionEvent event) {
// 상위 클래스인 View 클래스에 발생한 이벤트를 전달한다.
super.onTouchEvent(event);

// 어떤 이벤트가 발생하였는지에 따라 처리가 달라진다.
switch (event.getAction()) {
// DOWN 이나 MOVE 가 발생한 경우
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
// 터치가 발생한 X, Y 의 각 좌표를 얻는다.
m_x = event.getX();
m_y = event.getY();

// 뷰를 갱신한다.
invalidate();
break;
case MotionEvent.ACTION_UP:
// UP 이 발생한 경우 그리기 좌표에 -1 을 저장하고 뷰를 갱신한다.
m_y = m_x = -1;
invalidate();
break;
}
// true 를 반환하여 더이상의 이벤트 처리가 이루어지지 않도록 이벤트 처리가 완료한다.
return true;
}
}


댓글