summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2016-12-13 19:37:10 -0800
committerSunny Goyal <sunnygoyal@google.com>2016-12-13 23:39:16 -0800
commit0f76b56865bd7b63bd21d53aaac47300396aa38f (patch)
tree1b5bd8b01b2860cc1597d6371056c288a199cb55
parent466c4131d88fc951c8eaef7f1f7ade5ac91221e4 (diff)
downloadandroid_packages_apps_Trebuchet-0f76b56865bd7b63bd21d53aaac47300396aa38f.tar.gz
android_packages_apps_Trebuchet-0f76b56865bd7b63bd21d53aaac47300396aa38f.tar.bz2
android_packages_apps_Trebuchet-0f76b56865bd7b63bd21d53aaac47300396aa38f.zip
Refactoring FlingToDelete
> Moving all fling related logic to FlingToDeleteHelper from DragController > Removing fling related methods from DragSource and DropTarget > Moving fling animation logic from DeleteDropTarget to FlingAnimation > Simplifying DropTargetBar to directly look for all valid drop targets. This makes it easier to add new DropTarget in xml. Change-Id: I7214d2d30c907ab93c80d92d9f9be6dda2d63354
-rw-r--r--src/com/android/launcher3/AnotherWindowDropTarget.java3
-rw-r--r--src/com/android/launcher3/ButtonDropTarget.java17
-rw-r--r--src/com/android/launcher3/DeleteDropTarget.java57
-rw-r--r--src/com/android/launcher3/DragSource.java12
-rw-r--r--src/com/android/launcher3/DropTarget.java11
-rw-r--r--src/com/android/launcher3/DropTargetBar.java37
-rw-r--r--src/com/android/launcher3/InfoDropTarget.java2
-rw-r--r--src/com/android/launcher3/Launcher.java2
-rw-r--r--src/com/android/launcher3/UninstallDropTarget.java2
-rw-r--r--src/com/android/launcher3/Workspace.java16
-rw-r--r--src/com/android/launcher3/allapps/AllAppsContainerView.java13
-rw-r--r--src/com/android/launcher3/dragndrop/AnotherWindowDragSource.java9
-rw-r--r--src/com/android/launcher3/dragndrop/DragController.java120
-rw-r--r--src/com/android/launcher3/dragndrop/DragDriver.java9
-rw-r--r--src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java109
-rw-r--r--src/com/android/launcher3/folder/Folder.java18
-rw-r--r--src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java10
-rw-r--r--src/com/android/launcher3/util/FlingAnimation.java89
-rw-r--r--src/com/android/launcher3/widget/WidgetsContainerView.java18
19 files changed, 227 insertions, 327 deletions
diff --git a/src/com/android/launcher3/AnotherWindowDropTarget.java b/src/com/android/launcher3/AnotherWindowDropTarget.java
index 7074f7838..052e5d09a 100644
--- a/src/com/android/launcher3/AnotherWindowDropTarget.java
+++ b/src/com/android/launcher3/AnotherWindowDropTarget.java
@@ -48,9 +48,6 @@ public class AnotherWindowDropTarget implements DropTarget {
public void onDragExit(DragObject dragObject) {}
@Override
- public void onFlingToDelete(DragObject dragObject, PointF vec) {}
-
- @Override
public boolean acceptDrop(DragObject dragObject) {
return dragObject.dragInfo instanceof ShortcutInfo;
}
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 60a2cc325..e613b3b2f 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -28,7 +28,6 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
@@ -119,9 +118,6 @@ public abstract class ButtonDropTarget extends TextView
}
@Override
- public void onFlingToDelete(DragObject d, PointF vec) { }
-
- @Override
public final void onDragEnter(DragObject d) {
d.dragView.setColor(mHoverColor);
if (Utilities.ATLEAST_LOLLIPOP) {
@@ -243,10 +239,7 @@ public abstract class ButtonDropTarget extends TextView
final Rect from = new Rect();
dragLayer.getViewRectRelativeToSelf(d.dragView, from);
- int width = mDrawable.getIntrinsicWidth();
- int height = mDrawable.getIntrinsicHeight();
- final Rect to = getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
- width, height);
+ final Rect to = getIconRect(d);
final float scale = (float) to.width() / from.width();
mDropTargetBar.deferOnDragEnd();
@@ -268,7 +261,7 @@ public abstract class ButtonDropTarget extends TextView
@Override
public void prepareAccessibilityDrop() { }
- @Thunk abstract void completeDrop(DragObject d);
+ public abstract void completeDrop(DragObject d);
@Override
public void getHitRectRelativeToDragLayer(android.graphics.Rect outRect) {
@@ -280,7 +273,11 @@ public abstract class ButtonDropTarget extends TextView
outRect.offsetTo(coords[0], coords[1]);
}
- protected Rect getIconRect(int viewWidth, int viewHeight, int drawableWidth, int drawableHeight) {
+ public Rect getIconRect(DragObject dragObject) {
+ int viewWidth = dragObject.dragView.getMeasuredWidth();
+ int viewHeight = dragObject.dragView.getMeasuredHeight();
+ int drawableWidth = mDrawable.getIntrinsicWidth();
+ int drawableHeight = mDrawable.getIntrinsicHeight();
DragLayer dragLayer = mLauncher.getDragLayer();
// Find the rect to animate to (the view is center aligned)
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 705f84101..9097ed23d 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -16,19 +16,13 @@
package com.android.launcher3;
-import android.animation.TimeInterpolator;
import android.content.Context;
-import android.graphics.PointF;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
-import android.view.animation.AnimationUtils;
-import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.folder.Folder;
-import com.android.launcher3.util.FlingAnimation;
-import com.android.launcher3.util.Thunk;
public class DeleteDropTarget extends ButtonDropTarget {
@@ -78,7 +72,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
}
@Override
- @Thunk void completeDrop(DragObject d) {
+ public void completeDrop(DragObject d) {
ItemInfo item = d.dragInfo;
if ((d.dragSource instanceof Workspace) || (d.dragSource instanceof Folder)) {
removeWorkspaceOrFolderItem(mLauncher, item, null);
@@ -96,53 +90,4 @@ public class DeleteDropTarget extends ButtonDropTarget {
launcher.getWorkspace().stripEmptyScreens();
launcher.getDragLayer().announceForAccessibility(launcher.getString(R.string.item_removed));
}
-
- @Override
- public void onFlingToDelete(final DragObject d, PointF vel) {
- // Don't highlight the icon as it's animating
- d.dragView.setColor(0);
-
- final DragLayer dragLayer = mLauncher.getDragLayer();
- FlingAnimation fling = new FlingAnimation(d, vel,
- getIconRect(d.dragView.getMeasuredWidth(), d.dragView.getMeasuredHeight(),
- mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()),
- dragLayer);
-
- final int duration = fling.getDuration();
- final long startTime = AnimationUtils.currentAnimationTimeMillis();
-
- // NOTE: Because it takes time for the first frame of animation to actually be
- // called and we expect the animation to be a continuation of the fling, we have
- // to account for the time that has elapsed since the fling finished. And since
- // we don't have a startDelay, we will always get call to update when we call
- // start() (which we want to ignore).
- final TimeInterpolator tInterpolator = new TimeInterpolator() {
- private int mCount = -1;
- private float mOffset = 0f;
-
- @Override
- public float getInterpolation(float t) {
- if (mCount < 0) {
- mCount++;
- } else if (mCount == 0) {
- mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() -
- startTime) / duration);
- mCount++;
- }
- return Math.min(1f, mOffset + t);
- }
- };
-
- Runnable onAnimationEndRunnable = new Runnable() {
- @Override
- public void run() {
- mLauncher.exitSpringLoadedDragMode();
- completeDrop(d);
- mLauncher.getDragController().onDeferredEndFling(d);
- }
- };
-
- dragLayer.animateView(d.dragView, fling, duration, tInterpolator, onAnimationEndRunnable,
- DragLayer.ANIMATION_END_DISAPPEAR, null);
- }
}
diff --git a/src/com/android/launcher3/DragSource.java b/src/com/android/launcher3/DragSource.java
index 2fb495fdd..dcd8f589a 100644
--- a/src/com/android/launcher3/DragSource.java
+++ b/src/com/android/launcher3/DragSource.java
@@ -27,11 +27,6 @@ import com.android.launcher3.logging.UserEventDispatcher.LogContainerProvider;
public interface DragSource extends LogContainerProvider {
/**
- * @return whether items dragged from this source supports
- */
- boolean supportsFlingToDelete();
-
- /**
* @return whether items dragged from this source supports 'App Info'
*/
boolean supportsAppInfoDropTarget();
@@ -48,13 +43,6 @@ public interface DragSource extends LogContainerProvider {
float getIntrinsicIconScaleFactor();
/**
- * A callback specifically made back to the source after an item from this source has been flung
- * to be deleted on a DropTarget. In such a situation, this method will be called after
- * onDropCompleted, and more importantly, after the fling animation has completed.
- */
- void onFlingToDeleteCompleted();
-
- /**
* A callback made back to the source after an item from this source has been dropped on a
* DropTarget.
*/
diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java
index e91fc15e0..7d047d748 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -16,12 +16,10 @@
package com.android.launcher3;
-import com.android.launcher3.dragndrop.DragView;
-
-import android.graphics.PointF;
import android.graphics.Rect;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
+import com.android.launcher3.dragndrop.DragView;
/**
* Interface defining an object that can receive a drag.
@@ -117,13 +115,6 @@ public interface DropTarget {
void onDragExit(DragObject dragObject);
/**
- * Handle an object being dropped as a result of flinging to delete and will be called in place
- * of onDrop(). (This is only called on objects that are set as the DragController's
- * fling-to-delete target.
- */
- void onFlingToDelete(DragObject dragObject, PointF vec);
-
- /**
* Check if a drop action can occur at, or near, the requested location.
* This will be called just before onDrop.
* @return True if the drop will be accepted, false otherwise.
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index 42bab4705..0840b7015 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -21,6 +21,7 @@ import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewDebug;
+import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
@@ -56,11 +57,6 @@ public class DropTargetBar extends LinearLayout implements DragController.DragLi
private ViewPropertyAnimator mCurrentAnimation;
- // Drop targets
- private ButtonDropTarget mDeleteDropTarget;
- private ButtonDropTarget mAppInfoDropTarget;
- private ButtonDropTarget mUninstallDropTarget;
-
public DropTargetBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -73,30 +69,27 @@ public class DropTargetBar extends LinearLayout implements DragController.DragLi
protected void onFinishInflate() {
super.onFinishInflate();
- // Get the individual components
- mDeleteDropTarget = (ButtonDropTarget) findViewById(R.id.delete_target_text);
- mAppInfoDropTarget = (ButtonDropTarget) findViewById(R.id.info_target_text);
- mUninstallDropTarget = (ButtonDropTarget) findViewById(R.id.uninstall_target_text);
-
- mDeleteDropTarget.setDropTargetBar(this);
- mAppInfoDropTarget.setDropTargetBar(this);
- mUninstallDropTarget.setDropTargetBar(this);
-
// Initialize with hidden state
setAlpha(0f);
}
public void setup(DragController dragController) {
dragController.addDragListener(this);
- dragController.setFlingToDeleteDropTarget(mDeleteDropTarget);
-
- dragController.addDragListener(mDeleteDropTarget);
- dragController.addDragListener(mAppInfoDropTarget);
- dragController.addDragListener(mUninstallDropTarget);
+ setupButtonDropTarget(this, dragController);
+ }
- dragController.addDropTarget(mDeleteDropTarget);
- dragController.addDropTarget(mAppInfoDropTarget);
- dragController.addDropTarget(mUninstallDropTarget);
+ private void setupButtonDropTarget(View view, DragController dragController) {
+ if (view instanceof ButtonDropTarget) {
+ ButtonDropTarget bdt = (ButtonDropTarget) view;
+ bdt.setDropTargetBar(this);
+ dragController.addDragListener(bdt);
+ dragController.addDropTarget(bdt);
+ } else if (view instanceof ViewGroup) {
+ ViewGroup vg = (ViewGroup) view;
+ for (int i = vg.getChildCount() - 1; i >= 0; i--) {
+ setupButtonDropTarget(vg.getChildAt(i), dragController);
+ }
+ }
}
private void animateToVisibility(boolean isVisible) {
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index 398c9d2a2..6a6d2859a 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -49,7 +49,7 @@ public class InfoDropTarget extends UninstallDropTarget {
}
@Override
- void completeDrop(DragObject d) {
+ public void completeDrop(DragObject d) {
DropTargetResultCallback callback = d.dragSource instanceof DropTargetResultCallback
? (DropTargetResultCallback) d.dragSource : null;
startDetailsActivityForInfo(d.dragInfo, mLauncher, callback);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index accc3cd61..7775a6bc5 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -3068,7 +3068,7 @@ public class Launcher extends Activity
|| mState == State.WIDGETS_SPRING_LOADED;
}
- void exitSpringLoadedDragMode() {
+ public void exitSpringLoadedDragMode() {
if (mState == State.APPS_SPRING_LOADED) {
showAppsView(true /* animated */,
false /* updatePredictedApps */, false /* focusSearchBar */);
diff --git a/src/com/android/launcher3/UninstallDropTarget.java b/src/com/android/launcher3/UninstallDropTarget.java
index 7ea9aca7c..00c613a88 100644
--- a/src/com/android/launcher3/UninstallDropTarget.java
+++ b/src/com/android/launcher3/UninstallDropTarget.java
@@ -95,7 +95,7 @@ public class UninstallDropTarget extends ButtonDropTarget {
}
@Override
- void completeDrop(final DragObject d) {
+ public void completeDrop(final DragObject d) {
DropTargetResultCallback callback = d.dragSource instanceof DropTargetResultCallback
? (DropTargetResultCallback) d.dragSource : null;
startUninstallActivity(mLauncher, d.dragInfo, callback);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 13bea2077..49e14e494 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -33,7 +33,6 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Point;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
@@ -3722,11 +3721,6 @@ public class Workspace extends PagedView
}
@Override
- public boolean supportsFlingToDelete() {
- return true;
- }
-
- @Override
public boolean supportsAppInfoDropTarget() {
return !FeatureFlags.LAUNCHER3_LEGACY_WORKSPACE_DND;
}
@@ -3736,16 +3730,6 @@ public class Workspace extends PagedView
return true;
}
- @Override
- public void onFlingToDelete(DragObject d, PointF vec) {
- // Do nothing
- }
-
- @Override
- public void onFlingToDeleteCompleted() {
- // Do nothing
- }
-
public boolean isDropEnabled() {
return true;
}
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index f98e0275f..6fae7b12d 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -402,11 +402,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
}
@Override
- public boolean supportsFlingToDelete() {
- return true;
- }
-
- @Override
public boolean supportsAppInfoDropTarget() {
return true;
}
@@ -423,14 +418,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
}
@Override
- public void onFlingToDeleteCompleted() {
- // We just dismiss the drag when we fling, so cleanup here
- mLauncher.exitSpringLoadedDragModeDelayed(true,
- Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
- mLauncher.unlockScreenOrientation(false);
- }
-
- @Override
public void onDropCompleted(View target, DropTarget.DragObject d, boolean isFlingToDelete,
boolean success) {
if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
diff --git a/src/com/android/launcher3/dragndrop/AnotherWindowDragSource.java b/src/com/android/launcher3/dragndrop/AnotherWindowDragSource.java
index e968f36a7..162301069 100644
--- a/src/com/android/launcher3/dragndrop/AnotherWindowDragSource.java
+++ b/src/com/android/launcher3/dragndrop/AnotherWindowDragSource.java
@@ -37,11 +37,6 @@ public class AnotherWindowDragSource implements DragSource {
}
@Override
- public boolean supportsFlingToDelete() {
- return false;
- }
-
- @Override
public boolean supportsAppInfoDropTarget() {
return false;
}
@@ -57,10 +52,6 @@ public class AnotherWindowDragSource implements DragSource {
}
@Override
- public void onFlingToDeleteCompleted() {
- }
-
- @Override
public void onDropCompleted(View target, DragObject d,
boolean isFlingToDelete, boolean success) {
if (!success) {
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 67ef5fc3c..a5a54c1ec 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -17,11 +17,9 @@
package com.android.launcher3.dragndrop;
import android.content.ComponentName;
-import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
@@ -29,7 +27,6 @@ import android.view.DragEvent;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.MotionEvent;
-import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.inputmethod.InputMethodManager;
@@ -54,8 +51,6 @@ import java.util.ArrayList;
* Class for initiating a drag within a view or across multiple views.
*/
public class DragController implements DragDriver.EventListener, TouchController {
- private static final String TAG = "Launcher.DragController";
-
public static final int SCROLL_DELAY = 500;
public static final int RESCROLL_DELAY = PagedView.PAGE_SNAP_ANIMATION_DURATION + 150;
@@ -68,10 +63,9 @@ public class DragController implements DragDriver.EventListener, TouchController
public static final int SCROLL_LEFT = 0;
public static final int SCROLL_RIGHT = 1;
- private static final float MAX_FLING_DEGREES = 35f;
-
@Thunk Launcher mLauncher;
private Handler mHandler;
+ private FlingToDeleteHelper mFlingToDeleteHelper;
// temporaries to avoid gc thrash
private Rect mRectTemp = new Rect();
@@ -103,7 +97,6 @@ public class DragController implements DragDriver.EventListener, TouchController
/** Who can receive drop events */
private ArrayList<DropTarget> mDropTargets = new ArrayList<DropTarget>();
private ArrayList<DragListener> mListeners = new ArrayList<DragListener>();
- private DropTarget mFlingToDeleteDropTarget;
/** The window token used as the parent for the DragView. */
private IBinder mWindowToken;
@@ -119,8 +112,6 @@ public class DragController implements DragDriver.EventListener, TouchController
private DropTarget mLastDropTarget;
- private InputMethodManager mInputMethodManager;
-
@Thunk int mLastTouch[] = new int[2];
@Thunk long mLastTouchUpTime = -1;
@Thunk int mDistanceSinceScroll = 0;
@@ -128,9 +119,6 @@ public class DragController implements DragDriver.EventListener, TouchController
private int mTmpPoint[] = new int[2];
private Rect mDragLayerRect = new Rect();
- protected final int mFlingToDeleteThresholdVelocity;
- private VelocityTracker mVelocityTracker;
-
private boolean mIsInPreDrag;
/**
@@ -159,11 +147,8 @@ public class DragController implements DragDriver.EventListener, TouchController
mLauncher = launcher;
mHandler = new Handler();
mScrollZone = r.getDimensionPixelSize(R.dimen.scroll_zone);
- mVelocityTracker = VelocityTracker.obtain();
-
- mFlingToDeleteThresholdVelocity =
- r.getDimensionPixelSize(R.dimen.drag_flingToDeleteMinVelocity);
mIsRtl = Utilities.isRtl(r);
+ mFlingToDeleteHelper = new FlingToDeleteHelper(launcher);
}
/**
@@ -208,11 +193,8 @@ public class DragController implements DragDriver.EventListener, TouchController
}
// Hide soft keyboard, if visible
- if (mInputMethodManager == null) {
- mInputMethodManager = (InputMethodManager)
- mLauncher.getSystemService(Context.INPUT_METHOD_SERVICE);
- }
- mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0);
+ mLauncher.getSystemService(InputMethodManager.class)
+ .hideSoftInputFromWindow(mWindowToken, 0);
mOptions = options;
if (mOptions.systemDndStartPoint != null) {
@@ -369,7 +351,7 @@ public class DragController implements DragDriver.EventListener, TouchController
}
}
- releaseVelocityTracker();
+ mFlingToDeleteHelper.releaseVelocityTracker();
}
public void animateDragViewToOriginalPosition(final Runnable onComplete,
@@ -411,10 +393,6 @@ public class DragController implements DragDriver.EventListener, TouchController
}
}
- public void onDeferredEndFling(DropTarget.DragObject d) {
- d.dragSource.onFlingToDeleteCompleted();
- }
-
/**
* Clamps the position to the drag layer bounds.
*/
@@ -453,22 +431,16 @@ public class DragController implements DragDriver.EventListener, TouchController
}
@Override
- public void onDriverDragEnd(float x, float y, DropTarget dropTargetOverride) {
+ public void onDriverDragEnd(float x, float y) {
DropTarget dropTarget;
- PointF vec = null;
-
- if (dropTargetOverride != null) {
- dropTarget = dropTargetOverride;
+ Runnable flingAnimation = mFlingToDeleteHelper.getFlingAnimation(mDragObject);
+ if (flingAnimation != null) {
+ dropTarget = mFlingToDeleteHelper.getDropTarget();
} else {
- vec = isFlingingToDelete(mDragObject.dragSource);
- if (vec != null) {
- dropTarget = mFlingToDeleteDropTarget;
- } else {
- dropTarget = findDropTarget((int) x, (int) y, mCoordinatesTemp);
- }
+ dropTarget = findDropTarget((int) x, (int) y, mCoordinatesTemp);
}
- drop(dropTarget, x, y, vec);
+ drop(dropTarget, flingAnimation);
endDrag();
}
@@ -487,7 +459,7 @@ public class DragController implements DragDriver.EventListener, TouchController
}
// Update the velocity tracker
- acquireVelocityTrackerAndAddMovement(ev);
+ mFlingToDeleteHelper.recordMotionEvent(ev);
final int action = ev.getAction();
final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
@@ -635,7 +607,7 @@ public class DragController implements DragDriver.EventListener, TouchController
}
// Update the velocity tracker
- acquireVelocityTrackerAndAddMovement(ev);
+ mFlingToDeleteHelper.recordMotionEvent(ev);
final int action = ev.getAction();
final int[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
@@ -688,47 +660,12 @@ public class DragController implements DragDriver.EventListener, TouchController
dropTarget.prepareAccessibilityDrop();
// Perform the drop
- drop(dropTarget, location[0], location[1], null);
+ drop(dropTarget, null);
endDrag();
}
- /**
- * Determines whether the user flung the current item to delete it.
- *
- * @return the vector at which the item was flung, or null if no fling was detected.
- */
- private PointF isFlingingToDelete(DragSource source) {
- if (mFlingToDeleteDropTarget == null) return null;
- if (!source.supportsFlingToDelete()) return null;
-
- ViewConfiguration config = ViewConfiguration.get(mLauncher);
- mVelocityTracker.computeCurrentVelocity(1000, config.getScaledMaximumFlingVelocity());
- PointF vel = new PointF(mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
- float theta = MAX_FLING_DEGREES + 1;
- if (mVelocityTracker.getYVelocity() < mFlingToDeleteThresholdVelocity) {
- // Do a quick dot product test to ensure that we are flinging upwards
- PointF upVec = new PointF(0f, -1f);
- theta = getAngleBetweenVectors(vel, upVec);
- } else if (mLauncher.getDeviceProfile().isVerticalBarLayout() &&
- mVelocityTracker.getXVelocity() < mFlingToDeleteThresholdVelocity) {
- // Remove icon is on left side instead of top, so check if we are flinging to the left.
- PointF leftVec = new PointF(-1f, 0f);
- theta = getAngleBetweenVectors(vel, leftVec);
- }
- if (theta <= Math.toRadians(MAX_FLING_DEGREES)) {
- return vel;
- }
- return null;
- }
-
- private float getAngleBetweenVectors(PointF vec1, PointF vec2) {
- return (float) Math.acos(((vec1.x * vec2.x) + (vec1.y * vec2.y)) /
- (vec1.length() * vec2.length()));
- }
-
- private void drop(DropTarget dropTarget, float x, float y, PointF flingVel) {
+ private void drop(DropTarget dropTarget, Runnable flingAnimation) {
final int[] coordinates = mCoordinatesTemp;
-
mDragObject.x = coordinates[0];
mDragObject.y = coordinates[1];
@@ -750,8 +687,8 @@ public class DragController implements DragDriver.EventListener, TouchController
if (dropTarget != null) {
dropTarget.onDragExit(mDragObject);
if (dropTarget.acceptDrop(mDragObject)) {
- if (flingVel != null) {
- dropTarget.onFlingToDelete(mDragObject, flingVel);
+ if (flingAnimation != null) {
+ flingAnimation.run();
} else if (!mIsInPreDrag) {
dropTarget.onDrop(mDragObject);
}
@@ -762,7 +699,7 @@ public class DragController implements DragDriver.EventListener, TouchController
mLauncher.getUserEventDispatcher().logDragNDrop(mDragObject, dropTargetAsView);
if (!mIsInPreDrag) {
mDragObject.dragSource.onDropCompleted(
- dropTargetAsView, mDragObject, flingVel != null, accepted);
+ dropTargetAsView, mDragObject, flingAnimation != null, accepted);
}
}
@@ -829,27 +766,6 @@ public class DragController implements DragDriver.EventListener, TouchController
}
/**
- * Sets the current fling-to-delete drop target.
- */
- public void setFlingToDeleteDropTarget(DropTarget target) {
- mFlingToDeleteDropTarget = target;
- }
-
- private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
- }
-
- private void releaseVelocityTracker() {
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- }
-
- /**
* Set which view scrolls for touch events near the edge of the screen.
*/
public void setScrollView(View v) {
diff --git a/src/com/android/launcher3/dragndrop/DragDriver.java b/src/com/android/launcher3/dragndrop/DragDriver.java
index d0c8e1690..a90cfffdc 100644
--- a/src/com/android/launcher3/dragndrop/DragDriver.java
+++ b/src/com/android/launcher3/dragndrop/DragDriver.java
@@ -23,7 +23,6 @@ import android.content.Intent;
import android.view.DragEvent;
import android.view.MotionEvent;
-import com.android.launcher3.DropTarget;
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.ShortcutInfo;
@@ -40,7 +39,7 @@ public abstract class DragDriver {
public interface EventListener {
void onDriverDragMove(float x, float y);
void onDriverDragExitWindow();
- void onDriverDragEnd(float x, float y, DropTarget dropTargetOverride);
+ void onDriverDragEnd(float x, float y);
void onDriverDragCancel();
}
@@ -62,7 +61,7 @@ public abstract class DragDriver {
break;
case MotionEvent.ACTION_UP:
mEventListener.onDriverDragMove(ev.getX(), ev.getY());
- mEventListener.onDriverDragEnd(ev.getX(), ev.getY(), null);
+ mEventListener.onDriverDragEnd(ev.getX(), ev.getY());
break;
case MotionEvent.ACTION_CANCEL:
mEventListener.onDriverDragCancel();
@@ -80,7 +79,7 @@ public abstract class DragDriver {
switch (action) {
case MotionEvent.ACTION_UP:
- mEventListener.onDriverDragEnd(ev.getX(), ev.getY(), null);
+ mEventListener.onDriverDragEnd(ev.getX(), ev.getY());
break;
case MotionEvent.ACTION_CANCEL:
mEventListener.onDriverDragCancel();
@@ -160,7 +159,7 @@ class SystemDragDriver extends DragDriver {
case DragEvent.ACTION_DRAG_ENDED:
if (mReceivedDropEvent) {
- mEventListener.onDriverDragEnd(mLastX, mLastY, null);
+ mEventListener.onDriverDragEnd(mLastX, mLastY);
} else {
mEventListener.onDriverDragCancel();
}
diff --git a/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java b/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
new file mode 100644
index 000000000..a2aa27d17
--- /dev/null
+++ b/src/com/android/launcher3/dragndrop/FlingToDeleteHelper.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.dragndrop;
+
+import android.graphics.PointF;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.ViewConfiguration;
+
+import com.android.launcher3.ButtonDropTarget;
+import com.android.launcher3.DropTarget;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.util.FlingAnimation;
+
+/**
+ * Utility class to manage fling to delete action during drag and drop.
+ */
+public class FlingToDeleteHelper {
+
+ private static final float MAX_FLING_DEGREES = 35f;
+
+ private final Launcher mLauncher;
+ private final int mFlingToDeleteThresholdVelocity;
+
+ private ButtonDropTarget mDropTarget;
+ private VelocityTracker mVelocityTracker;
+
+ public FlingToDeleteHelper(Launcher launcher) {
+ mLauncher = launcher;
+ mFlingToDeleteThresholdVelocity = launcher.getResources()
+ .getDimensionPixelSize(R.dimen.drag_flingToDeleteMinVelocity);
+ }
+
+ public void recordMotionEvent(MotionEvent ev) {
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ mVelocityTracker.addMovement(ev);
+ }
+
+ public void releaseVelocityTracker() {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ }
+
+ public DropTarget getDropTarget() {
+ return mDropTarget;
+ }
+
+ public Runnable getFlingAnimation(DropTarget.DragObject dragObject) {
+ PointF vel = isFlingingToDelete();
+ if (vel == null) {
+ return null;
+ }
+ return new FlingAnimation(dragObject, vel, mDropTarget, mLauncher);
+ }
+
+ /**
+ * Determines whether the user flung the current item to delete it.
+ *
+ * @return the vector at which the item was flung, or null if no fling was detected.
+ */
+ private PointF isFlingingToDelete() {
+ if (mDropTarget == null) {
+ mDropTarget = (ButtonDropTarget) mLauncher.findViewById(R.id.delete_target_text);
+ }
+ if (mDropTarget == null || !mDropTarget.isDropEnabled()) return null;
+ ViewConfiguration config = ViewConfiguration.get(mLauncher);
+ mVelocityTracker.computeCurrentVelocity(1000, config.getScaledMaximumFlingVelocity());
+ PointF vel = new PointF(mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
+ float theta = MAX_FLING_DEGREES + 1;
+ if (mVelocityTracker.getYVelocity() < mFlingToDeleteThresholdVelocity) {
+ // Do a quick dot product test to ensure that we are flinging upwards
+ PointF upVec = new PointF(0f, -1f);
+ theta = getAngleBetweenVectors(vel, upVec);
+ } else if (mLauncher.getDeviceProfile().isVerticalBarLayout() &&
+ mVelocityTracker.getXVelocity() < mFlingToDeleteThresholdVelocity) {
+ // Remove icon is on left side instead of top, so check if we are flinging to the left.
+ PointF leftVec = new PointF(-1f, 0f);
+ theta = getAngleBetweenVectors(vel, leftVec);
+ }
+ if (theta <= Math.toRadians(MAX_FLING_DEGREES)) {
+ return vel;
+ }
+ return null;
+ }
+
+ private float getAngleBetweenVectors(PointF vec1, PointF vec2) {
+ return (float) Math.acos(((vec1.x * vec2.x) + (vec1.y * vec2.y)) /
+ (vec1.length() * vec2.length()));
+ }
+}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index a81b4caba..315f5118e 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -25,12 +25,10 @@ import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Build;
import android.text.InputType;
import android.text.Selection;
-import android.text.Spannable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ActionMode;
@@ -51,7 +49,6 @@ import android.widget.TextView;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Alarm;
import com.android.launcher3.AppInfo;
-import com.android.launcher3.BubbleTextView;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DragSource;
@@ -1010,11 +1007,6 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
}
@Override
- public boolean supportsFlingToDelete() {
- return true;
- }
-
- @Override
public boolean supportsAppInfoDropTarget() {
return !FeatureFlags.LAUNCHER3_LEGACY_WORKSPACE_DND;
}
@@ -1024,16 +1016,6 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
return true;
}
- @Override
- public void onFlingToDelete(DragObject d, PointF vec) {
- // Do nothing
- }
-
- @Override
- public void onFlingToDeleteCompleted() {
- // Do nothing
- }
-
private void updateItemLocationsInDatabaseBatch() {
ArrayList<View> list = getItemsInReadingOrder();
ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
index 314a8628b..a2534926f 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
@@ -475,11 +475,6 @@ public class DeepShortcutsContainer extends AbstractFloatingView
}
@Override
- public boolean supportsFlingToDelete() {
- return true;
- }
-
- @Override
public boolean supportsAppInfoDropTarget() {
return true;
}
@@ -495,11 +490,6 @@ public class DeepShortcutsContainer extends AbstractFloatingView
}
@Override
- public void onFlingToDeleteCompleted() {
- // Don't care; ignore.
- }
-
- @Override
public void onDropCompleted(View target, DropTarget.DragObject d, boolean isFlingToDelete,
boolean success) {
if (!success) {
diff --git a/src/com/android/launcher3/util/FlingAnimation.java b/src/com/android/launcher3/util/FlingAnimation.java
index da8bae712..d475ee9df 100644
--- a/src/com/android/launcher3/util/FlingAnimation.java
+++ b/src/com/android/launcher3/util/FlingAnimation.java
@@ -5,13 +5,16 @@ import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
+import com.android.launcher3.ButtonDropTarget;
import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.Launcher;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragView;
-public class FlingAnimation implements AnimatorUpdateListener {
+public class FlingAnimation implements AnimatorUpdateListener, Runnable {
/**
* Maximum acceleration in one dimension (pixels per milliseconds)
@@ -19,40 +22,86 @@ public class FlingAnimation implements AnimatorUpdateListener {
private static final float MAX_ACCELERATION = 0.5f;
private static final int DRAG_END_DELAY = 300;
+ private final ButtonDropTarget mDropTarget;
+ private final Launcher mLauncher;
+
protected final DragObject mDragObject;
- protected final Rect mIconRect;
protected final DragLayer mDragLayer;
- protected final Rect mFrom;
- protected final int mDuration;
- protected final float mUX, mUY;
- protected final float mAnimationTimeFraction;
protected final TimeInterpolator mAlphaInterpolator = new DecelerateInterpolator(0.75f);
+ protected final float mUX, mUY;
+
+ protected Rect mIconRect;
+ protected Rect mFrom;
+ protected int mDuration;
+ protected float mAnimationTimeFraction;
protected float mAX, mAY;
- /**
- * @param vel initial fling velocity in pixels per second.
- */
- public FlingAnimation(DragObject d, PointF vel, Rect iconRect, DragLayer dragLayer) {
+ public FlingAnimation(DragObject d, PointF vel, ButtonDropTarget dropTarget, Launcher launcher) {
+ mDropTarget = dropTarget;
+ mLauncher = launcher;
mDragObject = d;
mUX = vel.x / 1000;
mUY = vel.y / 1000;
- mIconRect = iconRect;
+ mDragLayer = mLauncher.getDragLayer();
+ }
- mDragLayer = dragLayer;
- mFrom = new Rect();
- dragLayer.getViewRectRelativeToSelf(d.dragView, mFrom);
+ @Override
+ public void run() {
+ mIconRect = mDropTarget.getIconRect(mDragObject);
- float scale = d.dragView.getScaleX();
- float xOffset = ((scale - 1f) * d.dragView.getMeasuredWidth()) / 2f;
- float yOffset = ((scale - 1f) * d.dragView.getMeasuredHeight()) / 2f;
+ // Initiate from
+ mFrom = new Rect();
+ mDragLayer.getViewRectRelativeToSelf(mDragObject.dragView, mFrom);
+ float scale = mDragObject.dragView.getScaleX();
+ float xOffset = ((scale - 1f) * mDragObject.dragView.getMeasuredWidth()) / 2f;
+ float yOffset = ((scale - 1f) * mDragObject.dragView.getMeasuredHeight()) / 2f;
mFrom.left += xOffset;
mFrom.right -= xOffset;
mFrom.top += yOffset;
mFrom.bottom -= yOffset;
+ mDuration = Math.abs(mUY) > Math.abs(mUX) ? initFlingUpDuration() : initFlingLeftDuration();
- mDuration = Math.abs(vel.y) > Math.abs(vel.x) ? initFlingUpDuration() : initFlingLeftDuration();
mAnimationTimeFraction = ((float) mDuration) / (mDuration + DRAG_END_DELAY);
+
+ // Don't highlight the icon as it's animating
+ mDragObject.dragView.setColor(0);
+
+ final int duration = mDuration + DRAG_END_DELAY;
+ final long startTime = AnimationUtils.currentAnimationTimeMillis();
+
+ // NOTE: Because it takes time for the first frame of animation to actually be
+ // called and we expect the animation to be a continuation of the fling, we have
+ // to account for the time that has elapsed since the fling finished. And since
+ // we don't have a startDelay, we will always get call to update when we call
+ // start() (which we want to ignore).
+ final TimeInterpolator tInterpolator = new TimeInterpolator() {
+ private int mCount = -1;
+ private float mOffset = 0f;
+
+ @Override
+ public float getInterpolation(float t) {
+ if (mCount < 0) {
+ mCount++;
+ } else if (mCount == 0) {
+ mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() -
+ startTime) / duration);
+ mCount++;
+ }
+ return Math.min(1f, mOffset + t);
+ }
+ };
+
+ Runnable onAnimationEndRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mLauncher.exitSpringLoadedDragMode();
+ mDropTarget.completeDrop(mDragObject);
+ }
+ };
+
+ mDragLayer.animateView(mDragObject.dragView, this, duration, tInterpolator,
+ onAnimationEndRunnable, DragLayer.ANIMATION_END_DISAPPEAR, null);
}
/**
@@ -111,10 +160,6 @@ public class FlingAnimation implements AnimatorUpdateListener {
return (int) Math.round(t);
}
- public final int getDuration() {
- return mDuration + DRAG_END_DELAY;
- }
-
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float t = animation.getAnimatedFraction();
diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java
index 2e1294251..165d12ef8 100644
--- a/src/com/android/launcher3/widget/WidgetsContainerView.java
+++ b/src/com/android/launcher3/widget/WidgetsContainerView.java
@@ -31,8 +31,6 @@ import com.android.launcher3.BaseContainerView;
import com.android.launcher3.DeleteDropTarget;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.dragndrop.DragOptions;
-import com.android.launcher3.folder.Folder;
import com.android.launcher3.IconCache;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
@@ -42,10 +40,11 @@ import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.WidgetPreviewLoader;
import com.android.launcher3.dragndrop.DragController;
+import com.android.launcher3.dragndrop.DragOptions;
+import com.android.launcher3.folder.Folder;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.model.PackageItemInfo;
import com.android.launcher3.model.WidgetItem;
-import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.MultiHashMap;
@@ -246,11 +245,6 @@ public class WidgetsContainerView extends BaseContainerView
//
@Override
- public boolean supportsFlingToDelete() {
- return true;
- }
-
- @Override
public boolean supportsAppInfoDropTarget() {
return true;
}
@@ -270,14 +264,6 @@ public class WidgetsContainerView extends BaseContainerView
}
@Override
- public void onFlingToDeleteCompleted() {
- // We just dismiss the drag when we fling, so cleanup here
- mLauncher.exitSpringLoadedDragModeDelayed(true,
- Launcher.EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT, null);
- mLauncher.unlockScreenOrientation(false);
- }
-
- @Override
public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete,
boolean success) {
if (LOGD) {