diff --git a/library-extensions/src/main/java/com/mikepenz/fastadapter_extensions/drag/DragSelectionItemTouchListener.java b/library-extensions/src/main/java/com/mikepenz/fastadapter_extensions/drag/DragSelectionItemTouchListener.java new file mode 100644 index 000000000..245270b75 --- /dev/null +++ b/library-extensions/src/main/java/com/mikepenz/fastadapter_extensions/drag/DragSelectionItemTouchListener.java @@ -0,0 +1,117 @@ +package com.mikepenz.fastadapter_extensions.drag; + +import android.content.Context; +import android.graphics.Rect; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.MotionEvent; +import android.view.View; + +import java.util.ArrayList; +import java.util.List; + +public class DragSelectionItemTouchListener extends LongPressItemTouchListener implements RecyclerView.OnItemTouchListener { + private RecyclerView.ViewHolder mPreviousViewHolder; + private Rect mHitRect = new Rect(); + private List mRangeSelection = new ArrayList<>(); + + + public DragSelectionItemTouchListener(Context context, OnItemInteractionListener listener) { + super(context, listener); + } + + @Override + public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { + if (e.getAction() == MotionEvent.ACTION_UP || e.getAction() == MotionEvent.ACTION_POINTER_UP) { + cancelPreviousSelection(); + return false; + } else { + onLongPressedEvent(rv, e); + } + return mViewHolderLongPressed != null; + } + + private void cancelPreviousSelection() { + mViewHolderLongPressed = null; + mViewHolderInFocus = null; + mPreviousViewHolder = null; + mRangeSelection.clear(); + } + + private boolean onActionMove(RecyclerView rv, MotionEvent e) { + if (isMotionEventInCurrentViewHolder(e) || mViewHolderLongPressed == null) { + return false; + } + if (mViewHolderLongPressed != null && mPreviousViewHolder == null) { + mPreviousViewHolder = mViewHolderLongPressed; + } + View childViewUnder = rv.findChildViewUnder(e.getX(), e.getY()); + if (childViewUnder == null) return false; + RecyclerView.ViewHolder viewHolder = rv.getChildViewHolder(childViewUnder); + if (mPreviousViewHolder == null && viewHolder != null && mViewHolderLongPressed != null && viewHolder.getAdapterPosition() != mViewHolderLongPressed.getAdapterPosition()) { + dispatchOnViewHolderHovered(rv, viewHolder); + return true; + } else if (mPreviousViewHolder != null && viewHolder != null && viewHolder.getAdapterPosition() != mPreviousViewHolder.getAdapterPosition()) { + dispatchOnViewHolderHovered(rv, viewHolder); + return true; + } + return false; + } + + + private boolean isMotionEventInCurrentViewHolder(MotionEvent e) { + if (mPreviousViewHolder != null) { + mPreviousViewHolder.itemView.getHitRect(mHitRect); + return mHitRect.contains((int) e.getX(), (int) e.getY()); + } + return false; + } + + private void dispatchOnViewHolderHovered(RecyclerView rv, RecyclerView.ViewHolder viewHolder) { + if (!checkForSpanSelection(rv, viewHolder)) { + if (mListener != null) { + mListener.onViewHolderHovered(rv, viewHolder); + } + } + mPreviousViewHolder = viewHolder; + } + + private boolean checkForSpanSelection(RecyclerView rv, RecyclerView.ViewHolder viewHolder) { + if (rv.getLayoutManager() instanceof GridLayoutManager) { + GridLayoutManager.LayoutParams endSelectionParams = (GridLayoutManager.LayoutParams) viewHolder.itemView.getLayoutParams(); + GridLayoutManager.LayoutParams startSelectionParams = (GridLayoutManager.LayoutParams) mPreviousViewHolder.itemView.getLayoutParams(); + if (endSelectionParams.getSpanIndex() != startSelectionParams.getSpanIndex()) { + dispatchRangeSelection(rv, viewHolder); + return true; + } + } + return false; + } + + private void dispatchRangeSelection(RecyclerView rv, RecyclerView.ViewHolder viewHolder) { + if (mListener != null) { + mRangeSelection.clear(); + int start = Math.min(mPreviousViewHolder.getAdapterPosition() + 1, viewHolder.getAdapterPosition()); + int end = Math.max(mPreviousViewHolder.getAdapterPosition() + 1, viewHolder.getAdapterPosition()); + for (int i = start; i <= end; i++) { + mRangeSelection.add(rv.findViewHolderForAdapterPosition(i)); + } + mListener.onMultipleViewHoldersSelected(rv, mRangeSelection); + } + } + + + @Override + public void onTouchEvent(RecyclerView rv, MotionEvent e) { + if (e.getAction() == MotionEvent.ACTION_UP || e.getAction() == MotionEvent.ACTION_POINTER_UP) { + cancelPreviousSelection(); + } else if (mViewHolderLongPressed != null) { + onActionMove(rv, e); + } + } + + @Override + public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { + + } +} diff --git a/library-extensions/src/main/java/com/mikepenz/fastadapter_extensions/drag/LongPressItemTouchListener.java b/library-extensions/src/main/java/com/mikepenz/fastadapter_extensions/drag/LongPressItemTouchListener.java new file mode 100644 index 000000000..bc5357483 --- /dev/null +++ b/library-extensions/src/main/java/com/mikepenz/fastadapter_extensions/drag/LongPressItemTouchListener.java @@ -0,0 +1,60 @@ +package com.mikepenz.fastadapter_extensions.drag; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; + +public abstract class LongPressItemTouchListener extends RecyclerView.SimpleOnItemTouchListener { + + private final GestureDetector mGestureDetector; + protected final OnItemInteractionListener mListener; + protected RecyclerView.ViewHolder mViewHolderLongPressed; + public RecyclerView.ViewHolder mViewHolderInFocus; + + public LongPressItemTouchListener(Context context, OnItemInteractionListener listener) { + mGestureDetector = new GestureDetector(context, new LongPressGestureListener()); + mGestureDetector.setIsLongpressEnabled(true); + mListener = listener; + } + + + public boolean onLongPressedEvent(RecyclerView rv, MotionEvent e) { + + if (mViewHolderLongPressed != null) { + return false; + // long pressed happened, my job here is done. + } + View childViewUnder = rv.findChildViewUnder(e.getX(), e.getY()); + if (childViewUnder != null) { + mViewHolderInFocus = rv.findContainingViewHolder(childViewUnder); + if (mGestureDetector.onTouchEvent(e) && mListener != null) { + mListener.onItemClicked(rv, mViewHolderInFocus, rv.getChildAdapterPosition(childViewUnder)); + } + return mViewHolderLongPressed != null; + } + return false; + } + + class LongPressGestureListener extends GestureDetector.SimpleOnGestureListener { + @Override + public boolean onSingleTapUp(MotionEvent e) { + return true; + } + + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + return true; + } + + @Override + public void onLongPress(MotionEvent e) { + if (mViewHolderInFocus != null && mListener != null) { + RecyclerView recyclerView = (RecyclerView) mViewHolderInFocus.itemView.getParent(); + mListener.onLongItemClicked(recyclerView, mViewHolderInFocus, mViewHolderInFocus.getAdapterPosition()); + mViewHolderLongPressed = mViewHolderInFocus; + } + } + } +} diff --git a/library-extensions/src/main/java/com/mikepenz/fastadapter_extensions/drag/OnItemInteractionListener.java b/library-extensions/src/main/java/com/mikepenz/fastadapter_extensions/drag/OnItemInteractionListener.java new file mode 100644 index 000000000..165af145a --- /dev/null +++ b/library-extensions/src/main/java/com/mikepenz/fastadapter_extensions/drag/OnItemInteractionListener.java @@ -0,0 +1,15 @@ +package com.mikepenz.fastadapter_extensions.drag; + +import android.support.v7.widget.RecyclerView; + +import java.util.List; + +public interface OnItemInteractionListener { + void onLongItemClicked(RecyclerView recyclerView, RecyclerView.ViewHolder mViewHolderTouched, int position); + + void onItemClicked(RecyclerView recyclerView, RecyclerView.ViewHolder mViewHolderTouched, int position); + + void onViewHolderHovered(RecyclerView rv, RecyclerView.ViewHolder viewHolder); + + void onMultipleViewHoldersSelected(RecyclerView rv, List selection); +}