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 취소 루틴을 직접 테스트하면 적절한 곳에 추가해 주시면됩니다.
감사합니다.