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 취소 루틴을 직접 테스트하면 적절한 곳에 추가해 주시면됩니다. 감사합니다.
좋네요..ㅎㅎ
Move 까지 고려되어서 더 좋군요..