티스토리 뷰


MotionEvent 객체는 터치에 대한 정보를 담고 있는 객체이다. 터치 된 점의 (x,y)좌표 터치 압력, 포인터의 개수등의 정보를 담고 있다. 만약에 하나의 액티비티가 여러개의 뷰로 겹겹이 쌓여있다고 해보자. 예를들어, 텍스트뷰가 리니어 레이아웃에 감싸져 있고 그 리니어 위에 또 리니어로 감싸져있고.. 뭐 이런 상황에서 화면이 터치되면 가장 최하위에 깔린 텍스트뷰가 제일 먼저 처리 권한을 갖게 된다. 그리고 만약에 텍스트뷰에 연결된 onTouchListener의 onTouch메소드에서 true를 반환하면 더이상 상위 뷰에 터치 이벤트가 전달되지 않지만 false를 리턴하는 경우에는 parent view에 터치 이벤트가 전달된다.


조상 -> 부모 -> 자식 순서대로 터치 이벤트가 전달되고 자식->부모->조상 순서대로 터치 이벤트를 처리할 권한을 갖게 되는데, 만약에 조상->부모->자식으로 터치 이벤트가 전달되는 과정중에서 중간에 부모가 그 터치이벤트를 처리하고 싶을때는

onInterceptTouchEvent() 메소드에서 true를 리턴하게끔 하면 된다. 그럼 자식까지 터치 이벤트가 전달되지 않고 중간에 부모가 그 터치 이벤트를 처리해버린다. 또한 부모 뷰의 모든 상위 뷰에게는 ACTION_CANCEL이벤트가 전달된다. 즉, 중간에 어떤 뷰가 이벤트를 처리했기 떄문에 자식뷰까지 터치 이벤트가 전달되지 않은것을 알리기 위한 용도이다.


Table 1. Touch Events
EventDescription

MotionEvent.ACTION_DOWN

New touch started

MotionEvent.ACTION_MOVE

Finger is moving

MotionEvent.ACTION_UP

Finger went up

MotionEvent.ACTION_CANCEL

Current event has been canceled, something else took control of the touch event

MotionEvent.ACTION_POINTER_DOWN

Pointer down (multi-touch)

MotionEvent.ACTION_POINTER_UP

Pointer up (multi-touch)

스크린에 손가락 2개를 올리려고 한다. 첫번째 손가락을 올렸을때는 ACTION_DOWN 이벤트가 발생하지만 두번째 손가락을 화면에 올렸을때는 ACTION_POINTER_DOWN 이벤트가 발생한다. 첫번째 손가락에 대해서는 ACTION_DOWN,UP이 사용되고 두번째 손가락부터는 ACTOIN_POINTER_DOWN,UP이 사용된다.






포인터 아이디

 터치가 발생했을 때 각각의 터치된 손가락들은 아이디 값을 가지게 됩니다. 그 터치된 순서에 따라 0부터 차례대로 아이디를 부여받으며 멀티터치에서 터치 좌표를 가져올 때 포인터 아이디가 사용됩니다. 

포인터 인덱스

 포인터 인덱스는 터치 이벤트가 발생했을 때 터치된 손가락 수 만큼 0에서부터 시작해 1씩 증가하게 된다. 만약 손가락 3개가 터치되었다면 각각의 손가락들은, 포인터 인덱스 0에서 2까지가 됩니다. 


둘이 비슷한 말 같은데 약간은 다르다. 위의 개념을 잘 잡아 놓아야 구현할때 에러가 나지 않을것이다.

화면에 손가락을 하나 올렸다. 이때 그 터치된 점에 대해서 포인터 아이디와 포인터 인덱스가 부여된다. 각각 0이 부여 될것이다.


이때, 다른 손가락으로 다른 화면을 동시에 터치한다고 해보자. 그럼, 그 점은 아이디 1 인덱스 1이 부여 될것이다.

이때, 처음 터치했던 손가락을 때면 두번째 터치된 부분의 아이디는 그대로1 인덱스는 0으로 변경될것이다.

이때, 또 다른 화면을 터치할 경우 아이디는 0 인덱스는 1을 부여받을것이다.

왜냐면, 처음 화면을 터치했을때 부여받은 인덱스는 터치를 화면에서 때면서 남은 터치 점들의 인덱스가 0부터 새롭게 갱신되기 때문이다. 아이디는 갱신되지 않는다. 아이디는 한번 부여되면 그 터치점이 사라질때까지 유지된다.


화면에 두개의 손가락을 동시에 올려놓고 왼쪾에서 오른쪽으로 밀었다고 해보자.


그럼 가로로 2줄이 생겼을텐데, 그 2줄에는 많은 포인트들이 존재할것이다. 터치 이벤트가 발생한 점부터 차례대로 포인트 인덱스가 부여된다. 첫번째 줄에 있는 모든 포인트들은 같은 포인트 아이디를 가지고 두번째 줄에 있는 모든 포인트들은 같은 포인트 아이디를 가질것이다.


즉, 터치를 다운 -> 무브 -> 업 할때까지를 하나의 제스쳐라고 표현하는데, 이 때 발생되는 모든 터치점들은 같은 포인터 아이디를 갖는다.


포인터 인덱스는 그냥 그 점이 화면에서 몇번째로 만들어졌냐를 의미한다.


<싱글터치 MotionEvent 구현>

public float x, y;
@Override
public boolean onTouchEvent(MotionEvent event) {
    final int action = event.getAction();
    switch(action) {
        case MotionEvent.ACTION_DOWN:
            // 처음 터치가 눌러졌을 때
            x = event.getX();
            y = event.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            // 터치가 눌린 상태에서 움직일 때 
            x = event.getX();
            y = event.getY();
            break;
        case MotionEvent.ACTION_UP:
            // 터치가 떼어졌을 때
            x = event.getX();
            y = event.getY();
            break;
        default :
            break;
    }
    return true;
}
싱글 터치라는것은 그냥, 터치 스크린에서 한곳만 터치했다는것을 의미한다.
MotionEvent객체의 getX와 getY메소드는 말그대로 터치된 곳의 x,y좌표를 가져오는 함수이다. 매개변수를 전달 할 수 있는데, 매개변수로는 포인터 인덱스를 전달한다.

즉, 어떤 손가락 하나로 터치 스크린에서 선을 하나 그렸다고 해보자. 이때 만약에 첫번째 눌린 점의 x좌표를 얻고 싶다면 
event.getX(0);를 실행하면 된다. getX에 매개변수를 전달하지 않는 경우 포인터 인덱스가 0인 점의 x좌표를 넘긴다.
따라서, event.getX(0) == event.getX() 는 동일한 코드이다.

멀티 터치란 하나의 터치 스크린에서 여러개의 점을 동시에 터치하는것을 의미한다.
즉, 두개의 손가락으로 두개의 점을 터치 하는것.


MotionEvent.getPointerCount() 현재 터치된 손가락(아이디)의 갯수를 리턴하는 메소드

MotionEvent.getPointerId(index) 인덱스를 이용해 아이디를 리턴하는 메소드

MotionEvent.getPointerIndex(id) 아이디를 이용해 인데스를 리턴하는 메소드


@Override
public boolean onTouchEvent(MotionEvent event) {
    final int action = event.getAction();
    switch(action & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            // 처음 터치가 눌러졌을 때
            break;
        case MotionEvent.ACTION_MOVE:
            // 터치가 눌린 상태에서 움직일 때
            break;
        case MotionEvent.ACTION_UP:
            // 터치가 떼어졌을 때
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            // 터치가 두 개 이상일 때 눌러졌을 때
            break;
        case MotionEvent.ACTION_POINTER_UP:
            // 터치가 두 개 이상일 때 떼어졌을 때
            break;
        default :
            break;
    }
    return true;
}



출처

http://www.vogella.com/tutorials/AndroidTouch/article.html

https://developer.android.com/training/gestures/movement

https://hychome.blogspot.com/2015/10/blog-post.html

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함