package com.yokmama.learn10.chapter07.lesson33; import android.content.Context; import android.os.Build; import android.support.v4.view.GestureDetectorCompat; import android.support.v4.view.MotionEventCompat; import android.support.v7.widget.RecyclerView; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; /** * RecyclerViewのアイテムのクリックを取得するイベントリスナー * * Created by yokmama on 15/05/07. */ public abstract class ItemClickListener implements RecyclerView.OnItemTouchListener{ private final GestureDetectorCompat mGestureDetector; public ItemClickListener(RecyclerView recyclerView){ //RecyclerViewに対するジェスチャーを検出するためGestureDetectorを生成 mGestureDetector = new ItemClickGestureDetector(recyclerView.getContext(), new ItemClickGestureListener(recyclerView)); } @Override public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { if (!isAttachedToWindow(rv) || !hasAdapter(rv)) { return false; } //RecyclerViewに対するタッチイベントをGestureDetectorにて処理する mGestureDetector.onTouchEvent(e); return false; } @Override public void onTouchEvent(RecyclerView rv, MotionEvent e) { } @Override public void onRequestDisallowInterceptTouchEvent(boolean b) { //子のViewのうち、OnTouchをインターセプトする必要が発生した場合に呼ばれる。 } /*** * クリック時に呼ばれる * * @param parent * @param view * @param position * @param id * @return */ abstract boolean performItemClick(RecyclerView parent, View view, int position, long id); /*** * ロングクリック時に呼ばれる * * @param parent * @param view * @param position * @param id * @return */ abstract boolean performItemLongClick(RecyclerView parent, View view, int position, long id); /*** * RecyclerViewが画面にアタッチされているかどうか判断 * * @param hostView * @return */ private boolean isAttachedToWindow(RecyclerView hostView) { if (Build.VERSION.SDK_INT >= 19) { return hostView.isAttachedToWindow(); } else { return (hostView.getHandler() != null); } } /*** * RecyclerViewにAdapterが設定されているかどうか判断 * * @param hostView * @return */ private boolean hasAdapter(RecyclerView hostView) { return (hostView.getAdapter() != null); } /*** * クリック処理のみ検出するGestureDetector * */ private class ItemClickGestureDetector extends GestureDetectorCompat { private final ItemClickGestureListener mGestureListener; public ItemClickGestureDetector(Context context, ItemClickGestureListener listener) { super(context, listener); mGestureListener = listener; } @Override public boolean onTouchEvent(MotionEvent event) { final boolean handled = super.onTouchEvent(event); final int action = event.getAction() & MotionEventCompat.ACTION_MASK; if (action == MotionEvent.ACTION_UP) { mGestureListener.dispatchSingleTapUpIfNeeded(event); } return handled; } } /*** * クリック処理に応じて、シングルクリックかロングクリックか判定し、 * それぞれ設定されたリスナーメソッドをコールする * */ private class ItemClickGestureListener extends GestureDetector.SimpleOnGestureListener { private final RecyclerView mRecyclerView; private View mTargetChild; public ItemClickGestureListener(RecyclerView recyclerView) { mRecyclerView = recyclerView; } public void dispatchSingleTapUpIfNeeded(MotionEvent event) { if (mTargetChild != null) { onSingleTapUp(event); } } @Override public boolean onDown(MotionEvent event) { final int x = (int) event.getX(); final int y = (int) event.getY(); mTargetChild = mRecyclerView.findChildViewUnder(x, y); return (mTargetChild != null); } @Override public void onShowPress(MotionEvent event) { if (mTargetChild != null) { mTargetChild.setPressed(true); } } @Override public boolean onSingleTapUp(MotionEvent event) { boolean handled = false; if (mTargetChild != null) { mTargetChild.setPressed(false); final int position = mRecyclerView.getChildPosition(mTargetChild); final long id = mRecyclerView.getAdapter().getItemId(position); handled = performItemClick(mRecyclerView, mTargetChild, position, id); mTargetChild = null; } return handled; } @Override public boolean onScroll(MotionEvent event, MotionEvent event2, float v, float v2) { if (mTargetChild != null) { mTargetChild.setPressed(false); mTargetChild = null; return true; } return false; } @Override public void onLongPress(MotionEvent event) { if (mTargetChild == null) { return; } final int position = mRecyclerView.getChildPosition(mTargetChild); final long id = mRecyclerView.getAdapter().getItemId(position); final boolean handled = performItemLongClick(mRecyclerView, mTargetChild, position, id); if (handled) { mTargetChild.setPressed(false); mTargetChild = null; } } } }