http://blog.naver.com/mbyn33/90116108888


안녕하세요.  


안드로이드의  콤포넌트들은  기본적으로  Long Click을  지원합니다. 


그래도, 가끔은  Long Click 자체를 만들어야 할 때가 있더군요. 


우선적으로  기본 View.OnLongClickListener 를  사용하시구요. 

http://developer.android.com/reference/android/view/View.OnLongClickListener.html


이것을 못 쓸 경우는 아래와 같이  만드시면 된답니다. 



우선 마우스 이벤트만을 이용해서 Long Click을  구현하는 방법은  간단합니다. 


*  마우스 down

    - 초기 위치와 시간 기억 


*  마우스 Move

    -  일정범위 벗어나면  취소


* 마우스 up

    -  일정시간(long click time) 이 초과했으면  ,  Long click 

    -  시간이 안 지났으면  ,  short click



이 방법의 문제점은  사용자가  클릭을 떼지 않으면  long click 이 발생하지 않는 다는 것입니다. 

예들 들어,  long click time을  600ms 로 주었다고 해도,  누른체로 3초를 누르고 있어도 떼지 않으면  long click 이벤트가 발생하지 않게 되지요. 



개선된 방법은  아래와 같습니다. 


아이디어는 간단한데요.  


*  마우스 down

    - 초기 위치 기억 

    - delayedMassage를  생성합니다. 


*  마우스 Move

    -  일정범위 벗어나면  취소


* 마우스 up

    -  long click을  처리 안 되었으면  message를 지우고,  Shot Click을 수행합니다.


* message 함수 

    -  Long Click을 처리합니다. 


위와 같이 수정합니다. 



    // 시작 위치를 저장을 위한 변수 

    private float mLastMotionX = 0;

    private float mLastMotionY = 0;

    //  마우스 move 로 일정범위 벗어나면 취소하기 위한  값

    private int mTouchSlop;

    

    // long click 을  위한  변수들 

    private boolean mHasPerformedLongPress;

    private CheckForLongPress mPendingCheckForLongPress;

우선,  마우스의 최소 이동 범위를 구해야 하는데요.  

안드로이드에서  drag 범위를  인식하는 기본값이 있답니다. 


mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();


위와 같이 구하면 되구요. 


Long Click을  처리하는 루틴을 만듭니다. 


  // Long Click을 처리할  Runnable 입니다. 

   class CheckForLongPress implements Runnable {


        public void run() {

            if (performLongClick()) {

                mHasPerformedLongPress = true;

            }

        }

    }

    

    // Long Click 처리 설정을 위한 함수 

    private void postCheckForLongClick(int delayOffset) {

        mHasPerformedLongPress = false;


        if (mPendingCheckForLongPress == null) {

            mPendingCheckForLongPress = new CheckForLongPress();

        }

        

        mHandler.postDelayed(mPendingCheckForLongPress,

                ViewConfiguration.getLongPressTimeout() - delayOffset);

// 여기서  시스템의  getLongPressTimeout() 후에 message 수행하게 합니다.  

// 추가 delay가 필요한 경우를 위해서  파라미터로 조절가능하게 합니다.

    }

    


     /**

     * Remove the longpress detection timer.

     * 중간에 취소하는 용도입니다.

     */

    private void removeLongPressCallback() {

        if (mPendingCheckForLongPress != null) {

         mHandler.removeCallbacks(mPendingCheckForLongPress);

        }

    }

    

    public boolean performLongClick() {

//  실제 Long Click 처리하는 부분을 여기 둡니다.

return true;

   }

위와 같이 코드를 만들어 두시구요. 


실제 사용할 부분은  onTouchEvent를   구현해 두면 된답니다. 





              public boolean onTouch(View v, MotionEvent event) {

int action = event.getAction();

switch (action) {

case MotionEvent.ACTION_DOWN:

mLastMotionX = event.getX();

mLastMotionY = event.getY();   // 시작 위치 저장


mHasPerformedLongPress = false;   

postCheckForLongClick(0);     //  Long click message 설정

                    

break;

case MotionEvent.ACTION_MOVE:

final float x = event.getX();

final float y = event.getY();

final int deltaX = Math.abs((int) (mLastMotionX - x));

final int deltaY = Math.abs((int) (mLastMotionY - y));

                                        // 일정 범위 벗어나면  취소함

if (deltaX >= mTouchSlop || deltaY >= mTouchSlop) {

if (!mHasPerformedLongPress) {

                                                    // This is a tap, so remove the longpress check

                                                removeLongPressCallback();

}

}


break;

case MotionEvent.ACTION_CANCEL:

if (!mHasPerformedLongPress) {

                                               // This is a tap, so remove the longpress check

                                               removeLongPressCallback();

}

break;

case MotionEvent.ACTION_UP:

                                    

if (!mHasPerformedLongPress) {

                                                //  Long Click을 처리되지 않았으면 제거함.

                                                removeLongPressCallback();

                        

                                               // Short Click 처리 루틴을 여기에 넣으면 됩니다. 


}

break;

}

return true; // false;

}


위와 같이 구현 하시면 되구요. 


Long Click 취소 루틴을  직접 테스트하면 적절한 곳에 추가해 주시면됩니다. 


감사합니다.