본문 바로가기
안드로이드

[안드로이드] 멀티터치 구현하기 (드래그, 핀치투줌)

by 호군 2011. 4. 8.
반응형
링크 : http://blog.naver.com/PostView.nhn?blogId=prosports0&logNo=80126529694

나중을 위해서 스크랩 해둡니다.


안드로이드 개발시 
멀티터치를 구현하는 방법을 설명한다..

http://stackoverflow.com/questions/4227451/android-imageview-setting-drag-and-pinch-zoom-parameters
위의 자료를 참조하였다.

기본 원리는 터치 이벤트를 받아서 좌표를 구하는 방식이다.
크게 두가지의 터치 방식을 생각해볼수 있다.

1. 손가락 하나로 터치하여 드래그하는 방식.
  - 처음 포인트의 위치와 드래그중의 위치의 거리를 비교하여 작업한다.
2. 두손가락을 동시에 드래그하는 핀치 투 줌(Pinch to zoom)방식이다.
  - 터치 순서에 따라 인덱스 0 ,1을 부여하는데 이를 이용해서 (ex event.getX(0), event.getX(1))
    두 포인트의 좌표를 가지고 두 포인트간의 거리를 측정한다.

주요 motion event로는 

MotionEvent.ACTION_DOWN : 터치 시작(첫번째 터치)
MotionEvent.ACTION_POINTER_DOWN : 터치 시작(두번째 터치)
MotionEvent.ACTION_UP : 터치 종료(첫번째 터치)
MotionEvent.ACTION_POINTER_UP : 터치 종료(첫번째 터치)
MotionEvent.ACTION_MOVE : 드래그 중
MotionEvent.ACTION_MASK : 터치 이벤트 액션을 구분짓기 위한 MASK
으로 구분할 수 있다.

/***************************************************************************

소스 구현 부

***************************************************************************/

// 드래그 모드인지 핀치줌 모드인지 구분

static final int NONE = 0;

static final int DRAG = 1;

static final int ZOOM = 2;

int mode = NONE;

    

// 드래그시 좌표 저장

int posX1=0, posX2=0, posY1=0, posY2=0;

    

// 핀치시 두좌표간의 거리 저장

float oldDist = 1f;

float newDist = 1f;

    

public boolean onTouchEvent(MotionEvent event) { 

    int act = event.getAction();

    String strMsg = "";

    switch(act & MotionEvent.ACTION_MASK) {

        case MotionEvent.ACTION_DOWN: //첫번째 손가락 터치(드래그 용도)

            posX1 = (int) event.getX();

            posY1 = (int) event.getY();

 

            Log.d("zoom", "mode=DRAG" );

            mode = DRAG;

            break;

        case MotionEvent.ACTION_MOVE

            if(mode == DRAG) { // 드래그 중

                posX2 = (int) event.getX();

                posY2 = (int) event.getY();

 

                if(Math.abs(posX2-posX1)>20 || Math.abs(posY2-posY1)>20) {

                    posX1 = posX2;

                    posY1 = posY2;

                    strMsg = "drag";

                    Toast toast = Toast.makeText(this, strMsg, Toast.LENGTH_SHORT);

                    toast.show();

                }

            } else if (mode == ZOOM) { // 핀치 중

                newDist = spacing(event);

                Log.d("zoom", "newDist=" + newDist);

                Log.d("zoom", "oldDist=" + oldDist);

                if (newDist - oldDist > 20) { // zoom in

                    oldDist = newDist;

                    strMsg = "zoom in";

                    Toast toast = Toast.makeText(this, strMsg, Toast.LENGTH_SHORT);

                    toast.show();

                } else if(oldDist - newDist > 20) { // zoom out

                    oldDist = newDist;

                    strMsg = "zoom out";

                    Toast toast = Toast.makeText(this, strMsg, Toast.LENGTH_SHORT);

                    toast.show();

                }

            }

            break;

        case MotionEvent.ACTION_UP: // 첫번째 손가락을 떼었을 경우

        case MotionEvent.ACTION_POINTER_UP: // 두번째 손가락을 떼었을 경우

            mode = NONE;

            break;

        case MotionEvent.ACTION_POINTER_DOWN:  

        //두번째 손가락 터치(손가락 2개를 인식하였기 때문에 핀치 줌으로 판별)

            mode = ZOOM;

 

            newDist = spacing(event);

            oldDist = spacing(event);


            Log.d("zoom", "newDist=" + newDist);

            Log.d("zoom", "oldDist=" + oldDist);

            Log.d("zoom", "mode=ZOOM");

            break;

        case MotionEvent.ACTION_CANCEL:

        default : 

            break;

    }

 

    return super.onTouchEvent(event);

}

private float spacing(MotionEvent event) {

    float x = event.getX(0) - event.getX(1);

    float y = event.getY(0) - event.getY(1);

    return FloatMath.sqrt(x * x + y * y);

}


 

 

반응형