From d9378317910fefa8c62cc7a5b1b187c9a38af5df Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Sat, 5 Feb 2022 07:06:41 +0000 Subject: [PATCH] Add basic return animation when drag is canceled Bug: 179390870 Test: Drag, but don't drop to split an app from the taskbar and check that Launcher animates the surface back into place Change-Id: I726855ff5bdffd1fc58d2839b3cc44b3fdb131e9 --- .../taskbar/TaskbarDragController.java | 121 +++++++++++++++++- .../launcher3/taskbar/TaskbarView.java | 16 ++- .../taskbar/TaskbarViewController.java | 8 +- 3 files changed, 137 insertions(+), 8 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java index e152915038..435eae47ee 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java @@ -15,6 +15,11 @@ */ package com.android.launcher3.taskbar; +import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; import android.content.ClipData; import android.content.ClipDescription; import android.content.Intent; @@ -27,7 +32,9 @@ import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.view.DragEvent; import android.view.MotionEvent; +import android.view.SurfaceControl; import android.view.View; +import android.view.ViewRootImpl; import androidx.annotation.Nullable; @@ -39,20 +46,25 @@ import com.android.launcher3.DragSource; import com.android.launcher3.DropTarget; import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; +import com.android.launcher3.Utilities; import com.android.launcher3.accessibility.DragViewStateAnnouncer; +import com.android.launcher3.anim.Interpolators; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragController; import com.android.launcher3.dragndrop.DragDriver; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.dragndrop.DraggableView; +import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.graphics.DragPreviewProvider; import com.android.launcher3.logging.StatsLogManager; +import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.popup.PopupContainerWithArrow; import com.android.launcher3.shortcuts.DeepShortcutView; import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider; +import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.ClipDescriptionCompat; import com.android.systemui.shared.system.LauncherAppsCompat; @@ -66,6 +78,8 @@ import java.util.Arrays; public class TaskbarDragController extends DragController implements TaskbarControllers.LoggableTaskbarController { + private static boolean DEBUG_DRAG_SHADOW_SURFACE = false; + private final int mDragIconSize; private final int[] mTempXY = new int[2]; @@ -78,6 +92,9 @@ public class TaskbarDragController extends DragController { switch (dragEvent.getAction()) { @@ -356,7 +377,12 @@ public class TaskbarDragController extends DragController= 0) { + // Since folders close when the drag starts, target the folder icon instead + LauncherBindableItemsContainer.ItemOperator op = (info, v) -> { + if (info instanceof FolderInfo && v instanceof FolderIcon) { + FolderInfo fi = (FolderInfo) info; + for (WorkspaceItemInfo si : fi.contents) { + if (si.id == item.id) { + // Found the parent + return true; + } + } + } + return false; + }; + target = taskbarViewController.mapOverItems(op); + } + } + + // Finish any pending return animation before starting a new drag + if (mReturnAnimator != null) { + mReturnAnimator.end(); + } + + float fromX = dragEvent.getX() - dragEvent.getOffsetX(); + float fromY = dragEvent.getY() - dragEvent.getOffsetY(); + int[] toPosition = target.getLocationOnScreen(); + float toScale = (float) target.getWidth() / mDragIconSize; + float toAlpha = (target == btv) ? 1f : 0f; + final ViewRootImpl viewRoot = target.getViewRootImpl(); + SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); + mReturnAnimator = ValueAnimator.ofFloat(0f, 1f); + mReturnAnimator.setDuration(300); + mReturnAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); + mReturnAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float t = animation.getAnimatedFraction(); + float accelT = Interpolators.ACCEL_2.getInterpolation(t); + float scale = 1f - t * (1f - toScale); + float alpha = 1f - accelT * (1f - toAlpha); + tx.setPosition(dragSurface, Utilities.mapRange(t, fromX, toPosition[0]), + Utilities.mapRange(t, fromY, toPosition[1])); + tx.setScale(dragSurface, scale, scale); + tx.setAlpha(dragSurface, alpha); + tx.apply(); + } + }); + mReturnAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationCancel(Animator animation) { + cleanUpSurface(); + } + + @Override + public void onAnimationEnd(Animator animation) { + cleanUpSurface(); + } + + private void cleanUpSurface() { + maybeOnDragEnd(); + // Synchronize removing the drag surface with the next draw after calling + // maybeOnDragEnd() + viewRoot.consumeNextDraw((transaction) -> { + transaction.remove(dragSurface); + transaction.apply(); + tx.close(); + }); + viewRoot.getView().invalidate(); + mReturnAnimator = null; + } + }); + mReturnAnimator.start(); + } + @Override protected float getX(MotionEvent ev) { // We will resize to fill the screen while dragging, so use screen coordinates. This ensures diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index fddd1ed6fb..cfdacacfe7 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -316,6 +316,13 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar return icons; } + /** + * Returns the all apps button in the taskbar. + */ + public View getAllAppsButtonView() { + return mAllAppsButton; + } + // FolderIconParent implemented methods. @Override @@ -357,13 +364,18 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar return getVisibility() == VISIBLE; } - protected void mapOverItems(LauncherBindableItemsContainer.ItemOperator op) { + /** + * Maps {@code op} over all the child views, returning the view that {@code op} evaluates + * {@code true} for, or {@code null} if none satisfy {@code op}. + */ + protected View mapOverItems(LauncherBindableItemsContainer.ItemOperator op) { // map over all the shortcuts on the taskbar for (int i = 0; i < getChildCount(); i++) { View item = getChildAt(i); if (op.evaluate((ItemInfo) item.getTag(), item)) { - return; + return item; } } + return null; } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 778040dbc1..730f7a85a8 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -164,6 +164,10 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar return mTaskbarView.getIconViews(); } + public View getAllAppsButtonView() { + return mTaskbarView.getAllAppsButtonView(); + } + public AnimatedFloat getTaskbarIconScaleForStash() { return mTaskbarIconScaleForStash; } @@ -268,8 +272,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar mTaskbarNavButtonTranslationY.updateValue(-deviceProfile.getTaskbarOffsetY()); } - public void mapOverItems(LauncherBindableItemsContainer.ItemOperator op) { - mTaskbarView.mapOverItems(op); + public View mapOverItems(LauncherBindableItemsContainer.ItemOperator op) { + return mTaskbarView.mapOverItems(op); } /**