안드로이드 화면의 레이아웃이나 뷰를 사용자가 터치했을 때 터치한 행동에 대한 이벤트가 발생한다. 터치 이벤트가 제공하는 정보는 다른 이벤트 리스너와 달리 터치한 상태에서 화면상의 이동을 감자하는 모션 이벤트를 제공하고 있다.
사용자가 뷰나 뷰그룹을 터치한 상태의 정보는 OnTouchListener 리스너와 onTouch() 콜백 메서드를 제공한다.
public abstract boolean onTouch(View v, MotionEvent event)
ontTouch() 콜백 메서드는 터치한 뷰와 모션 이벤트에 대한 이벤트 정보를 매개 변수로 제공한다. MotionEvent 클래스는 마우스, 스타일러스, 손 그리고 트랙볼의 움직음을 감지하여 필요한 정보를 제공한다.
사용자가 화면을 터치했을때 모션 이벤트로 제공하는 정보는 스타일러스와 같은 팬인 경우 터치의 위치를 주목하는 ACTION_POINT_DOWN 과 ACTION_POINT_UP 이벤트 그리고 손의 움직임을 주목하는 ACTION_DOWN, ACTION_UP, ACTION_MOVE 이벤트가 있다. 일반적으로 제스처는 포인터의 이벤트를 포함하기 때문에 주로 제스처를 중심으로 기술한다.
안드로이드는 모션 이벤트를 통해 다음과 같은 4종류의 이벤트 액션 정보를 getAction() 메서드(제스처에 대해서는 getActionMasked() 메서드 그리고 스타일러스는 getActionIndex() 메서드)로 제공된다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:id="@+id/container" >
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
</LinearLayout>
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class MotionTest extends Activity {
private View selected_item = null;
ViewGroup container;
ImageView img;
private int w, h;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.motion_ex_01);
// 화면의 픽셀수를 산출하여 이미지의 크기를 고려하여 여백을 만든다.
w = getWindowManager().getDefaultDisplay().getWidth() - 50;
h = getWindowManager().getDefaultDisplay().getHeight() - 100;
// 레이아웃에 대해 리스너를 설정한다.
container = (ViewGroup) findViewById(R.id.container);
//selected_item = findViewById(R.id.img);
img = (ImageView)findViewById(R.id.img);
img.setOnTouchListener(ViewListener);
container.setOnTouchListener(ViewGroupListener);
}
private final View.OnTouchListener ViewListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
selected_item = v;
}
return false;
}
};
private final View.OnTouchListener ViewGroupListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getActionMasked()) {
case MotionEvent.ACTION_MOVE:
if (selected_item == null)
break;
int x = (int) event.getX();
int y = (int) event.getY();
if (x > w)
x = w;
if (y > h)
y = h;
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
new ViewGroup.MarginLayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
lp.setMargins(x, y, 0, 0);
selected_item.setLayoutParams(lp);
break;
case MotionEvent.ACTION_UP:
selected_item = null;
break;
default:
break;
}
return true;
}
};
}
뷰의 OnTouchListener 인터페이스 내 onTouch() 콜백 메서드의 반환 값이 false로 한 이유는 화면상에서 보면 뷰가 레이아웃보다 앞에 나와 있기 때문에 뷰가 우선시 된다. 그러나 뷰의 위치는 어떤 면에서 보면 동시에 레이아웃의 위치이기도 하다. 현재 위치되어 있는 이미지뷰를 끌어서 다른 위치로 이동하고자 한다면 윈도우 매니저는 현재 위치를 이미지 뷰의 위치로 인식하고 있지만 새롭게 이동하는 위치는 정확하게 보면 레이아웃 영역 내 위치가 된다.
따라서 위의 프로그램에서 보면 화면을 구성하는 뷰와 레이아웃 모두 모션 이벤트를 받는 View.OnTouchListener 인터페이스를 구현하는 것으로 되어 있다. 뷰의 onTouch() 콜백 메서드 에서 true로 반환하면 안드로이드 입장에서 보면 터치와 관련 작업을 뷰의 onTouch() 콜백 메서드에서 수행했기 때문에 결과 적으로 레이아웃과 관련된 onTouch() 콜백 메서드를 호출하지 않게 된다.
이러한 이유에서 뷰의 메서드에서 false로 반한하고 레이아웃의 View.OnTouchListener 인터페이스 내 onTouch() 콜백 메서드에서 이미지 뷰의 궤적 작업을 처리하게 된다.
[결과]
[Android]자바 콜렉션 (0) | 2013.04.06 |
---|---|
[Android] 안드로이드 탭 (1) | 2013.04.06 |
[Android] 이벤트 핸들러 (0) | 2013.04.03 |
[Android]프로그레스바 이벤트 (0) | 2013.03.31 |
[Android]RatingBar 이벤트 (0) | 2013.03.31 |
댓글 영역