Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] DragSelectionItemTouchListener #325

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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<RecyclerView.ViewHolder> 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) {

}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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<RecyclerView.ViewHolder> selection);
}