[Android] ListView에서 Single Tap, Double Tap 사용하기

Published on: 2013. 11. 14. 16:32 by louis.dev
리스트뷰에서 단순 탭과 더블탭을 구분하여 실행하는 방법을 찾던 중  github에서 괜찮은 코드를 발견했습니다. 그런데 이 코드에서 버그가 발견되어 버그를 수정하여 해당 소스를 공유하려고 합니다. 버그 내용은 싱글 탭을 하여 액티비티 전환이 일어난 후(선택된 아이템을 상세보기 하기 위해), 다시 뒤로 돌아와 동일한 아이템을 한번 더 누르면 더블 탭으로 인식하는 버그였습니다. 버그를 수정하기 위한 코드는 한줄이지만 전체 소스를 공유해 봅니다.
public class TabListView extends ListView {
	private Context mContext;

	// 더블텝을 사용하기 위한 변수들
	private boolean mFirstTabEvent;
	private Message mTapMessage;
	private final static int DOUBLE_TAP = 2;
	private final static int SINGLE_TAP = 1;
	private AdapterView<?> mParent;
	private View mView;
	private int mPosition;
	private long mId;
	private final static int DOUBLE_TAP_DELAY = ViewConfiguration.getDoubleTapTimeout();
	private int mPositionHolder = -1;

	private OnItemTapLister mItemTapListener;

	public TabListView(Context context, AttributeSet attrs,int defStyle) {
		super(context, attrs, defStyle);
		initConstructor(context);
	}

	public TabListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initConstructor(context);
	}

	public TabListView(Context context) {
		super(context);
		initConstructor(context);
	}

	private void initConstructor(Context context) {
		this.mContext = context;
		super.setOnItemClickListener(mItemClickListener);
	}

	/**
	 * 리스트뷰 더블텝 이벤트
	 * */
	public void setOnItemTapListener(OnItemTapLister l) {
		this.mItemTapListener = l;
	}

	OnItemClickListener mItemClickListener = new OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position,long id) {
			mParent = parent;
			mView = view;
			mPosition = position;
			mId = id;

			if (!mFirstTabEvent) {
				mPositionHolder = position;
				mFirstTabEvent = true;
				mTapMessage = mTapMessage == null ? new Message() : mHandler
						.obtainMessage();
				mHandler.removeMessages(SINGLE_TAP);
				mTapMessage.what = SINGLE_TAP;
				mHandler.sendMessageDelayed(mTapMessage, DOUBLE_TAP_DELAY);
			} else {
				if (mPositionHolder == position) {
					mHandler.removeMessages(SINGLE_TAP);
					mPosition = position;
					mTapMessage = mHandler.obtainMessage();
					mTapMessage.what = DOUBLE_TAP;
					mHandler.sendMessageAtFrontOfQueue(mTapMessage);
					mFirstTabEvent = false;
				} else {
					mTapMessage = mHandler.obtainMessage();
					mHandler.removeMessages(SINGLE_TAP);
					mFirstTabEvent = true;
					mTapMessage.what = SINGLE_TAP;
					mPositionHolder = position;
					mHandler.sendMessageDelayed(mTapMessage, DOUBLE_TAP_DELAY);
				}
			}
		}

	};

	private Handler mHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch (msg.what) {
			case SINGLE_TAP:
				mFirstTabEvent = false;//이 코드르 삽입함으로서 해당 버그 해결
				mItemTapListener.OnSingleTap(mParent, mView, mPosition, mId);
				break;
			case DOUBLE_TAP:
				mItemTapListener.OnDoubleTap(mParent, mView, mPosition, mId);
				break;
			}
		}

	};
	//Tab 이벤트 인터페이스
	public interface OnItemTapLister {
		public void OnDoubleTap(AdapterView<?> parent, View view, int position,long id);
		public void OnSingleTap(AdapterView<?> parent, View view, int position,long id);
	}

}
사용법은 다음처럼 하면 됩니다.
tabListView.setOnItemTapListener(new SingleColumnListView.OnItemTapLister() {
	@Override
	public void OnSingleTap(AdapterView<?> parent, View view, int position,long id) {
		//TODO 싱글 탭 시 작업
	}
	@Override
	public void OnDoubleTap(AdapterView<?> parent, View view, int position,long id) {
		/TODO 더블 탭 시 작업
	}
});
차~~암 쉽죠~?ㅎㅎ