안녕하세요.


안드로이드의 콤포넌트들은 기본적으로 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 취소 루틴을 직접 테스트하면 적절한 곳에 추가해 주시면됩니다.


감사합니다. 






이상 원본 내용의 포스팅 이였구요. 포스팅을 바탕으로 직접 실행되는 예제를 만들어 봤습니다. 아래의 예제를 살펴 보겠습니다.