Enable dragon drop for touch.
- Start a drag when the user long-presses on an already-selected item.
- Start a drag when the user mouse-drags on an already-selected item.
- Add highlighting of drop targets.
BUG=20556237
Change-Id: I450fd6768eeb08906304227385476942d641fd11
diff --git a/packages/DocumentsUI/Android.mk b/packages/DocumentsUI/Android.mk
index 1a4e3eb..e1650e1 100644
--- a/packages/DocumentsUI/Android.mk
+++ b/packages/DocumentsUI/Android.mk
@@ -8,6 +8,7 @@
LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
# The design lib requires that the client package use appcompat themes.
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-appcompat
+LOCAL_STATIC_JAVA_LIBRARIES += android-support-v13
# Supplies material design components, e.g. Snackbar.
LOCAL_STATIC_JAVA_LIBRARIES += android-support-design
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-recyclerview
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 7138c2d..f24fcc9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -52,6 +52,7 @@
import android.provider.DocumentsContract.Document;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
+import android.support.v13.view.DragStartHelper;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.GridLayoutManager.SpanSizeLookup;
import android.support.v7.widget.RecyclerView;
@@ -72,7 +73,6 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewParent;
import android.widget.ImageView;
import android.widget.TextView;
@@ -258,7 +258,8 @@
}
mRecView.setLayoutManager(mLayout);
- mGestureDetector = new ListeningGestureDetector(this.getContext(), new GestureListener());
+ mGestureDetector =
+ new ListeningGestureDetector(this.getContext(), mDragHelper, new GestureListener());
mRecView.addOnItemTouchListener(mGestureDetector);
@@ -1051,7 +1052,7 @@
view.setOnDragListener(mOnDragListener);
}
- view.setOnLongClickListener(mLongClickListener);
+ view.setOnLongClickListener(mDragHelper);
}
private View.OnDragListener mOnDragListener = new View.OnDragListener() {
@@ -1062,11 +1063,15 @@
// TODO: Check if the event contains droppable data.
return true;
- // TODO: Highlight potential drop target directory?
// TODO: Expand drop target directory on hover?
case DragEvent.ACTION_DRAG_ENTERED:
- case DragEvent.ACTION_DRAG_LOCATION:
+ highlightDropTarget(v, true);
+ return true;
case DragEvent.ACTION_DRAG_EXITED:
+ highlightDropTarget(v, false);
+ return true;
+
+ case DragEvent.ACTION_DRAG_LOCATION:
case DragEvent.ACTION_DRAG_ENDED:
return true;
@@ -1084,6 +1089,17 @@
}
return false;
}
+
+ private void highlightDropTarget(View v, boolean highlight) {
+ // Note: use exact comparison - this code is searching for views which are children of
+ // the RecyclerView instance in the UI.
+ if (v.getParent() == mRecView) {
+ RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(v);
+ if (vh instanceof DocumentHolder) {
+ ((DocumentHolder) vh).setHighlighted(highlight);
+ }
+ }
+ }
};
/**
@@ -1109,21 +1125,14 @@
* a document item view.
*/
private String getModelId(View view) {
- while (true) {
- if (view.getLayoutParams() instanceof RecyclerView.LayoutParams) {
- RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(view);
- if (vh instanceof DocumentHolder) {
- return ((DocumentHolder) vh).modelId;
- } else {
- return null;
- }
+ View itemView = mRecView.findContainingItemView(view);
+ if (itemView != null) {
+ RecyclerView.ViewHolder vh = mRecView.getChildViewHolder(itemView);
+ if (vh instanceof DocumentHolder) {
+ return ((DocumentHolder) vh).modelId;
}
- ViewParent parent = view.getParent();
- if (parent == null || !(parent instanceof View)) {
- return null;
- }
- view = (View) parent;
}
+ return null;
}
private List<DocumentInfo> getDraggableDocuments(View currentItemView) {
@@ -1299,10 +1308,10 @@
}
}
- private View.OnLongClickListener mLongClickListener = new View.OnLongClickListener() {
+ private DragStartHelper mDragHelper = new DragStartHelper(null) {
@Override
- public boolean onLongClick(View v) {
- if (mGestureDetector.mouseSpawnedLastEvent()) {
+ protected boolean onDragStart(View v) {
+ if (isSelected(getModelId(v))) {
List<DocumentInfo> docs = getDraggableDocuments(v);
if (docs.isEmpty()) {
return false;
@@ -1328,9 +1337,12 @@
implements OnItemTouchListener {
private int mLastTool = -1;
+ private DragStartHelper mDragHelper;
- public ListeningGestureDetector(Context context, GestureListener listener) {
+ public ListeningGestureDetector(
+ Context context, DragStartHelper dragHelper, GestureListener listener) {
super(context, listener);
+ mDragHelper = dragHelper;
setOnDoubleTapListener(listener);
}
@@ -1345,12 +1357,27 @@
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
mLastTool = e.getToolType(0);
- onTouchEvent(e); // bounce this forward to our detecty heart
+
+ // Detect drag events. When a drag is detected, intercept the rest of the gesture.
+ View itemView = rv.findChildViewUnder(e.getX(), e.getY());
+ if (itemView != null && mDragHelper.handleTouch(itemView, e)) {
+ return true;
+ }
+ // Forward unhandled events to the GestureDetector.
+ onTouchEvent(e);
+
return false;
}
@Override
- public void onTouchEvent(RecyclerView rv, MotionEvent e) {}
+ public void onTouchEvent(RecyclerView rv, MotionEvent e) {
+ View itemView = rv.findChildViewUnder(e.getX(), e.getY());
+ mDragHelper.handleTouch(itemView, e);
+ // Note: even though this event is being handled as part of a drag gesture, continue
+ // forwarding to the GestureDetector. The detector needs to see the entire cluster of
+ // events in order to properly interpret gestures.
+ onTouchEvent(e);
+ }
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
index 1bfc6e9..2967a90 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
@@ -75,11 +75,25 @@
*/
public abstract void bind(Cursor cursor, String modelId, State state);
+ /**
+ * Makes the associated item view appear selected. Note that this merely affects the appearance
+ * of the view, it doesn't actually select the item.
+ *
+ * @param selected
+ */
public void setSelected(boolean selected) {
itemView.setActivated(selected);
itemView.setBackgroundColor(selected ? mSelectedItemColor : mDefaultItemColor);
}
+ /**
+ * Highlights the associated item view.
+ * @param highlighted
+ */
+ public void setHighlighted(boolean highlighted) {
+ itemView.setBackgroundColor(highlighted ? mSelectedItemColor : mDefaultItemColor);
+ }
+
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// Event listener should always be set.