Please Enable JavaScript!
Gon[ Enable JavaScript ]

화면의 Touch Event 정보와 Message 구현

안드로이드 개발

화면의 Touch Event 정보와 Message 구현 


이번 예제는 안드로이드 화면상에 Touch 이벤트가 발생했을 때 어떻게 정보를 캡쳐해서

사용하는지와 이벤트 발생시 안드로이드 Message 객체를 사용해서 화면을 재로딩하는

방법에 대해 알아본다.


소스는 다음과 같이 이루어져 있다.

MainTouch : 메인 Activity

MessageList : 공통 메시지

TouchView : 화면 View

TickHandler : 메시지 캡쳐를 위한 Handler

 

1. MainTouch

(1) onCreate

View 를 상속받은 TouchView 등록한다.

 

(2) Handler 해제와 생성

onResume() 함수를 override 해서 TickHandler 객체를 생성한다. onResume Activity

생성될 때 와 다른 Activity 로 전환되어 Pause 되었다가 다시 시작될 때 실행되는 부분이다.

onPause() 함수가 실행될 때 TickHandler 객체를 삭제한다. 이것은 위에서 설명했듯이 Activity

전환해서 Fouse를 잃었을 때 발생하는 함수이다.

 

(3) 화면무효화를 통한 View 화면 새로 그림

onTick() 함수에서 View 객체의 invalidate() 함수를 호출해 화면을 새로 그린다. 화면에 대한

정보는 이미 View 객체의 onDraw() 함수에서 실행된 상태이다. 이 함수의 실행은 TickHandler

수행된다. 실행하고 o.1 sleep 을 걸어준다.
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Window;

public class MainTouch extends Activity{
	private TouchView touchView; // 터치뷰
	private TickHandler tickHandler;// 정기처리핸들러

	@Override
	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		touchView = new TouchView(this);
		setContentView(touchView);
	}
	/**
	 * Handler 를 리턴한다
	 * @return
	 */
	public TickHandler getHandler(){
		return tickHandler;
	}
	/* Activity 가 재시작 되었을때 Handler 재등록
	 * @see android.app.Activity#onResume()
	 */
	@Override
	public void onResume() {
		super.onResume();
		tickHandler = new TickHandler();
		tickHandler.sleep(0);
	}
	/* Activity 가 멈추었을때  Handler 객체 삭제
	 * @see android.app.Activity#onPause()
	 */
	@Override
	public void onPause() {
		super.onPause();
		tickHandler = null;
	}

	/**
	 * 화면 무효화를 통해 새로 그린다. 그리고 핸들을 0.1 초 멈춘다.
	 */
	public void onTick() {
		Log.d("MainTouch", "==============Refersh=============");
		touchView.invalidate();
		if (tickHandler != null)
			tickHandler.sleep(100);
	}

	// 주기처리핸들러
	public class TickHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			Log.d("TickHandler", "Handler Message : " + msg.toString());
			switch (msg.what){
			case MessageList.MSG_REFRESH:
				onTick();
				break;
			default:
				super.handleMessage(msg);
				break;
			}
		}

		// 슬립
		public void sleep(long delayMills) {
			removeMessages(0);// 해당 ID 메시지를 삭제한다.
			sendMessageDelayed(obtainMessage(0), delayMills); // 파라미터로 넘긴 ID 에 해당하는 msg 재사용
		}
	}
}

2. MessageList.java

메시지에 대한 상수값을 변수로 정의하기 위해 따로 static 클래스를 하나 만들었다.

이것은 모든 클래스에서 공통으로 쓰기 위함이다.
public class MessageList {
	public static final int MSG_REFRESH = 1;
}

3. TickHandler.java

MainTouch 클래스에 포함되어있다 .

(1) Handler 클래스 상속

사용자 정의 메시지를 중간에 가로채서 기능을 수행한다.

 

(2) 함수 종류

- handleMessage() : 핸들러메세지큐에 있는 작업을 처리 ( 실제 처리 메소드)

- obtainMessage() : Message가 필요할때 Handler.obtainMessage() Message.obtain()

    사용해서 풀에 있는 안쓰는 Message를 가져와서 재사용

- post() : 핸들러 메세지 큐에 Runnable 형태로 보낸다.

- removeMessages() : 핸들러 메세지 큐에서 메시지를 제거한다.

- sendMessage() : 핸들러 메세지 큐에 메세지 형태로 보낸다.

- sendMessageDelayed() : 핸들러 메세지 큐에 delay후에 메세지를 보낸다

 

(3) 원하는 메시지 걸러내기

handleMessage() 함수의 파라미터로 넘어오는 Message 에서 what 변수값은 message id 가 된다

id 로 구분해서 원하는 기능을 수행하면된다.
// 주기처리핸들러
	public class TickHandler extends Handler {
		@Override
		public void handleMessage(Message msg) {
			Log.d("TickHandler", "Handler Message : " + msg.toString());
			switch (msg.what){
			case MessageList.MSG_REFRESH:
				onTick();
				break;
			default:
				super.handleMessage(msg);
				break;
			}
		}

		// 슬립
		public void sleep(long delayMills) {
			removeMessages(0);// 해당 ID 메시지를 삭제한다.
			sendMessageDelayed(obtainMessage(0), delayMills); // 파라미터로 넘긴 ID 에 해당하는 msg 재사용
		}
	}

4. TouchView.java

(1) onTouchEvent Override

화면 터치이벤트가 일어났을 때 정보를 가져오기 위해 onTouchEvent 함수를 Override 한다.

여기에서 넘어온 파라미터로 화면좌표를 전역변수에 저장해주고 사용자 정의 메시지를 날려준다
android.os.Message msg = new android.os.Message();
msg.what = MessageList.MSG_REFRESH;
msg.obj = "REFRESH";
handler.sendMessage(msg);

(2) 화면 그리기

onDraw() 함수를 override 한 함수에서 화면을 그리기 위한 정보들을 셋팅한다.

전역번수에 저장해 두었던 좌표와 MotionEvent 정보로 Down, Up, Move, Cancel 정보를 구분해

화면를 그려주고 있다.
canvas.drawText(
     "[Touch DOWN] X=" + downX + ",Y=" + downY, 0, 20 * 1, paint);
canvas.drawText(
     "[Touch MOVE] X=" + moveX + ",Y=" + moveY, 0, 20 * 2, paint);
canvas.drawText(
     "[Touch UP] X=" + upX + ",Y=" + upY, 0, 20 * 3, paint);
canvas.drawText(
     "[Touch CANCEL] X=" + cancelX + ",Y=" + cancelY, 0, 20 * 4, paint);
전체소스는 다음과 같다
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;

import com.gon.touchevent.MainTouch.TickHandler;

public class TouchView extends View {
	private int touchX = 0; // 터치X좌표
	private int touchY = 0; // 터치Y좌표
	private int touchAction = -999;// 터치액션
	private int ballX = 0; // 볼X좌표
	private int ballY = 0; // 볼Y좌표
	private int ballAction = -999; // 볼액션
	
	private Context mContext = null;
	
	// 터치액션 그리기
	int downX = 0, downY = 0;
	int moveX = 0, moveY = 0;
	int upX = 0, upY = 0;
	int cancelX = 0, cancelY = 0;
	
	// 생성자
	public TouchView(Context context) {
		super(context);
		setBackgroundColor(Color.WHITE);
		// 포커스지정
		setFocusable(true);
		
		mContext = context;
	}

	// 그리기
	@Override
	protected void onDraw(Canvas canvas) {
		String str;

		// 페인트 객체생성
		Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setTextSize(16);
		
		str = "NONE";
		if (touchAction == MotionEvent.ACTION_DOWN){
			downX = touchX;
			downY = touchY;
		}
		if (touchAction == MotionEvent.ACTION_MOVE){
			moveX = touchX;
			moveY = touchY;
		}
		if (touchAction == MotionEvent.ACTION_UP){
			upX = touchX;
			upY = touchY;
		}
		if (touchAction == MotionEvent.ACTION_CANCEL){
			cancelX = touchX;
			cancelY = touchY;
		}
		// DOWN XY좌표 그리기
		canvas.drawText("[Touch DOWN] X=" + downX + ",Y=" + downY, 0, 20 * 1, paint);
		canvas.drawText("[Touch MOVE] X=" + moveX + ",Y=" + moveY, 0, 20 * 2, paint);
		canvas.drawText("[Touch UP] X=" + upX + ",Y=" + upY, 0, 20 * 3, paint);
		canvas.drawText("[Touch CANCEL] X=" + cancelX + ",Y=" + cancelY, 0, 20 * 4, paint);

		// 볼XY좌표 그리기
		canvas.drawText("[TrackballXY] X=" + ballX + ",Y=" + ballY, 0, 20 * 6, paint);

		// 볼 액션 그리기
		str = "NONE";
		if (ballAction == MotionEvent.ACTION_DOWN)
			str = "ACTION_DOWN";
		if (ballAction == MotionEvent.ACTION_MOVE)
			str = "ACTION_MOVE";
		if (ballAction == MotionEvent.ACTION_UP)
			str = "ACTION_UP";
		if (ballAction == MotionEvent.ACTION_CANCEL)
			str = "ACTION_CANCEL";
		canvas.drawText("[TrackballAction]" + str, 0, 20 * 7, paint);
	}

	// 터치이벤트 처리
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		touchX = (int) event.getX();
		touchY = (int) event.getY();
		touchAction = event.getAction();
		
		// 다시 그리기 위해 핸들러에 메시지를 전송한다
		MainTouch mainTouch = (MainTouch) mContext;
		TickHandler handler = mainTouch.getHandler();
		
		android.os.Message msg = new android.os.Message();
		msg.what = MessageList.MSG_REFRESH;
		msg.obj = "REFRESH";
		handler.sendMessage(msg);
		
		return true;
	}

	// 트랙볼 이벤트 처리
	@Override
	public boolean onTrackballEvent(MotionEvent event) {
		ballX = (int) (event.getX() * 100);
		ballY = (int) (event.getY() * 100);
		ballAction = event.getAction();
		return true;
	}
}

화면상에서 어떻게 나타나는지 그림을 통해 보자.

마우스를 클릭했을떄 Down 위치정보가 바뀌며 클릭한 상태에서 움직이게 되면 Move

위치정보가 바뀌는걸 볼수 있다.

Posted by 녹두장군

댓글을 달아 주세요

  1. Favicon of http://k77.go5.kr 하면 되더라 2010.11.03 16:52  댓글주소  수정/삭제  댓글쓰기

    꿈희망ⓜ 좋은 글 잘 보고갑니다. 좋은 꿈 꾸세요. 드디어 님의 꿈은 이루어 집니다.