Loading quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java +129 −49 Original line number Original line Diff line number Diff line Loading @@ -18,10 +18,12 @@ package com.android.launcher3.taskbar; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import android.animation.Animator; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.content.ClipData; import android.content.ClipData; import android.content.ClipDescription; import android.content.ClipDescription; import android.content.Intent; import android.content.Intent; Loading Loading @@ -49,7 +51,6 @@ import com.android.launcher3.DragSource; import com.android.launcher3.DropTarget; import com.android.launcher3.DropTarget; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.accessibility.DragViewStateAnnouncer; import com.android.launcher3.accessibility.DragViewStateAnnouncer; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.config.FeatureFlags; Loading @@ -70,6 +71,7 @@ import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.ItemInfoMatcher; import com.android.quickstep.util.LogUtils; import com.android.quickstep.util.LogUtils; import com.android.quickstep.util.MultiValueUpdateListener; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.Task; import java.io.PrintWriter; import java.io.PrintWriter; Loading @@ -83,7 +85,8 @@ import java.util.function.Predicate; public class TaskbarDragController extends DragController<BaseTaskbarContext> implements public class TaskbarDragController extends DragController<BaseTaskbarContext> implements TaskbarControllers.LoggableTaskbarController { TaskbarControllers.LoggableTaskbarController { private static boolean DEBUG_DRAG_SHADOW_SURFACE = false; private static final boolean DEBUG_DRAG_SHADOW_SURFACE = false; private static final int ANIM_DURATION_RETURN_ICON_TO_TASKBAR = 300; private final int mDragIconSize; private final int mDragIconSize; private final int[] mTempXY = new int[2]; private final int[] mTempXY = new int[2]; Loading @@ -99,6 +102,8 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im // Animation for the drag shadow back into position after an unsuccessful drag // Animation for the drag shadow back into position after an unsuccessful drag private ValueAnimator mReturnAnimator; private ValueAnimator mReturnAnimator; private boolean mDisallowGlobalDrag; private boolean mDisallowLongClick; public TaskbarDragController(BaseTaskbarContext activity) { public TaskbarDragController(BaseTaskbarContext activity) { super(activity); super(activity); Loading @@ -110,6 +115,14 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im mControllers = controllers; mControllers = controllers; } } public void setDisallowGlobalDrag(boolean disallowGlobalDrag) { mDisallowGlobalDrag = disallowGlobalDrag; } public void setDisallowLongClick(boolean disallowLongClick) { mDisallowLongClick = disallowLongClick; } /** /** * Attempts to start a system drag and drop operation for the given View, using its tag to * Attempts to start a system drag and drop operation for the given View, using its tag to * generate the ClipDescription and Intent. * generate the ClipDescription and Intent. Loading @@ -131,7 +144,7 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im View view, View view, @Nullable DragPreviewProvider dragPreviewProvider, @Nullable DragPreviewProvider dragPreviewProvider, @Nullable Point iconShift) { @Nullable Point iconShift) { if (!(view instanceof BubbleTextView)) { if (!(view instanceof BubbleTextView) || mDisallowLongClick) { return false; return false; } } TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onTaskbarItemLongClick"); TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onTaskbarItemLongClick"); Loading Loading @@ -293,6 +306,7 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im } } private void startSystemDrag(BubbleTextView btv) { private void startSystemDrag(BubbleTextView btv) { if (mDisallowGlobalDrag) return; View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(btv) { View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(btv) { @Override @Override Loading Loading @@ -421,6 +435,45 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im } } } } @Override protected void endDrag() { if (mDisallowGlobalDrag) { // We need to explicitly set deferDragViewCleanupPostAnimation to true here so the // super call doesn't remove it from the drag layer before the animation completes. // This variable gets set in to false in super.dispatchDropComplete() because it // (rightfully so, perhaps) thinks this drag operation has failed, and does its own // internal cleanup. // Another way to approach this would be to make all of overview a drop target and // accept the drop as successful and then run the setupReturnDragAnimator to simulate // drop failure to the user mDragObject.deferDragViewCleanupPostAnimation = true; float fromX = mDragObject.x - mDragObject.xOffset; float fromY = mDragObject.y - mDragObject.yOffset; DragView dragView = mDragObject.dragView; setupReturnDragAnimator(fromX, fromY, (View) mDragObject.originalView, (x, y, scale, alpha) -> { dragView.setTranslationX(x); dragView.setTranslationY(y); dragView.setScaleX(scale); dragView.setScaleY(scale); dragView.setAlpha(alpha); }); mReturnAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { callOnDragEnd(); dragView.remove(); dragView.clearAnimation(); mReturnAnimator = null; } }); mReturnAnimator.start(); } super.endDrag(); } @Override @Override protected void callOnDragEnd() { protected void callOnDragEnd() { super.callOnDragEnd(); super.callOnDragEnd(); Loading @@ -432,56 +485,20 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im SurfaceControl dragSurface = dragEvent.getDragSurface(); SurfaceControl dragSurface = dragEvent.getDragSurface(); // For top level icons, the target is the icon itself // For top level icons, the target is the icon itself View target = btv; View target = findTaskbarTargetForIconView(btv); Object tag = btv.getTag(); if (tag instanceof ItemInfo) { ItemInfo item = (ItemInfo) tag; TaskbarViewController taskbarViewController = mControllers.taskbarViewController; if (item.container == CONTAINER_ALL_APPS || item.container == CONTAINER_PREDICTION) { // Since all apps closes when the drag starts, target the all apps button instead. target = taskbarViewController.getAllAppsButtonView(); } else if (item.container >= 0) { // Since folders close when the drag starts, target the folder icon instead. Predicate<ItemInfo> matcher = ItemInfoMatcher.forFolderMatch( ItemInfoMatcher.ofItemIds(IntSet.wrap(item.id))); target = taskbarViewController.getFirstIconMatch(matcher); } else if (item.itemType == ITEM_TYPE_DEEP_SHORTCUT) { // Find first icon with same package/user as the deep shortcut. Predicate<ItemInfo> packageUserMatcher = ItemInfoMatcher.ofPackages( Collections.singleton(item.getTargetPackage()), item.user); target = taskbarViewController.getFirstIconMatch(packageUserMatcher); } } // Finish any pending return animation before starting a new drag if (mReturnAnimator != null) { mReturnAnimator.end(); } float fromX = dragEvent.getX() - dragEvent.getOffsetX(); float fromX = dragEvent.getX() - dragEvent.getOffsetX(); float fromY = dragEvent.getY() - dragEvent.getOffsetY(); 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(); final ViewRootImpl viewRoot = target.getViewRootImpl(); SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); mReturnAnimator = ValueAnimator.ofFloat(0f, 1f); setupReturnDragAnimator(fromX, fromY, btv, mReturnAnimator.setDuration(300); (x, y, scale, alpha) -> { mReturnAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); tx.setPosition(dragSurface, x, y); 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.setScale(dragSurface, scale, scale); tx.setAlpha(dragSurface, alpha); tx.setAlpha(dragSurface, alpha); tx.apply(); tx.apply(); } }); }); mReturnAnimator.addListener(new AnimatorListenerAdapter() { mReturnAnimator.addListener(new AnimatorListenerAdapter() { private boolean mCanceled = false; private boolean mCanceled = false; Loading Loading @@ -517,6 +534,63 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im mReturnAnimator.start(); mReturnAnimator.start(); } } private View findTaskbarTargetForIconView(@NonNull View iconView) { Object tag = iconView.getTag(); if (tag instanceof ItemInfo) { ItemInfo item = (ItemInfo) tag; TaskbarViewController taskbarViewController = mControllers.taskbarViewController; if (item.container == CONTAINER_ALL_APPS || item.container == CONTAINER_PREDICTION) { // Since all apps closes when the drag starts, target the all apps button instead. return taskbarViewController.getAllAppsButtonView(); } else if (item.container >= 0) { // Since folders close when the drag starts, target the folder icon instead. Predicate<ItemInfo> matcher = ItemInfoMatcher.forFolderMatch( ItemInfoMatcher.ofItemIds(IntSet.wrap(item.id))); return taskbarViewController.getFirstIconMatch(matcher); } else if (item.itemType == ITEM_TYPE_DEEP_SHORTCUT) { // Find first icon with same package/user as the deep shortcut. Predicate<ItemInfo> packageUserMatcher = ItemInfoMatcher.ofPackages( Collections.singleton(item.getTargetPackage()), item.user); return taskbarViewController.getFirstIconMatch(packageUserMatcher); } } return iconView; } private void setupReturnDragAnimator(float fromX, float fromY, View originalView, TaskbarReturnPropertiesListener animListener) { // Finish any pending return animation before starting a new return if (mReturnAnimator != null) { mReturnAnimator.end(); } // For top level icons, the target is the icon itself View target = findTaskbarTargetForIconView(originalView); int[] toPosition = target.getLocationOnScreen(); float toScale = (float) target.getWidth() / mDragIconSize; float toAlpha = (target == originalView) ? 1f : 0f; MultiValueUpdateListener listener = new MultiValueUpdateListener() { final FloatProp mDx = new FloatProp(fromX, toPosition[0], 0, ANIM_DURATION_RETURN_ICON_TO_TASKBAR, Interpolators.FAST_OUT_SLOW_IN); final FloatProp mDy = new FloatProp(fromY, toPosition[1], 0, ANIM_DURATION_RETURN_ICON_TO_TASKBAR, FAST_OUT_SLOW_IN); final FloatProp mScale = new FloatProp(1f, toScale, 0, ANIM_DURATION_RETURN_ICON_TO_TASKBAR, FAST_OUT_SLOW_IN); final FloatProp mAlpha = new FloatProp(1f, toAlpha, 0, ANIM_DURATION_RETURN_ICON_TO_TASKBAR, Interpolators.ACCEL_2); @Override public void onUpdate(float percent, boolean initOnly) { animListener.updateDragShadow(mDx.value, mDy.value, mScale.value, mAlpha.value); } }; mReturnAnimator = ValueAnimator.ofFloat(0f, 1f); mReturnAnimator.setDuration(ANIM_DURATION_RETURN_ICON_TO_TASKBAR); mReturnAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); mReturnAnimator.addUpdateListener(listener); } @Override @Override protected float getX(MotionEvent ev) { protected float getX(MotionEvent ev) { // We will resize to fill the screen while dragging, so use screen coordinates. This ensures // We will resize to fill the screen while dragging, so use screen coordinates. This ensures Loading @@ -540,7 +614,7 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im @Override @Override protected void exitDrag() { protected void exitDrag() { if (mDragObject != null) { if (mDragObject != null && !mDisallowGlobalDrag) { mActivity.getDragLayer().removeView(mDragObject.dragView); mActivity.getDragLayer().removeView(mDragObject.dragView); } } } } Loading @@ -556,6 +630,10 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im return null; return null; } } interface TaskbarReturnPropertiesListener { void updateDragShadow(float x, float y, float scale, float alpha); } @Override @Override public void dumpLogs(String prefix, PrintWriter pw) { public void dumpLogs(String prefix, PrintWriter pw) { pw.println(prefix + "TaskbarDragController:"); pw.println(prefix + "TaskbarDragController:"); Loading @@ -566,5 +644,7 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im pw.println(prefix + "\tmRegistrationY=" + mRegistrationY); pw.println(prefix + "\tmRegistrationY=" + mRegistrationY); pw.println(prefix + "\tmIsSystemDragInProgress=" + mIsSystemDragInProgress); pw.println(prefix + "\tmIsSystemDragInProgress=" + mIsSystemDragInProgress); pw.println(prefix + "\tisInternalDragInProgess=" + super.isDragging()); pw.println(prefix + "\tisInternalDragInProgess=" + super.isDragging()); pw.println(prefix + "\tmDisallowGlobalDrag=" + mDisallowGlobalDrag); pw.println(prefix + "\tmDisallowLongClick=" + mDisallowLongClick); } } } } quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +6 −0 Original line number Original line Diff line number Diff line Loading @@ -39,6 +39,8 @@ import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; import com.android.launcher3.uioverrides.states.OverviewState; import com.android.launcher3.util.MultiValueAlpha; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationController; import com.android.quickstep.RecentsAnimationController; Loading Loading @@ -117,6 +119,10 @@ import java.util.StringJoiner; mLauncherState = finalState; mLauncherState = finalState; updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, false); updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, false); applyState(); applyState(); mControllers.taskbarDragController.setDisallowGlobalDrag( (finalState instanceof OverviewState)); mControllers.taskbarDragController.setDisallowLongClick( finalState == LauncherState.OVERVIEW_SPLIT_SELECT); } } }; }; Loading Loading
quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java +129 −49 Original line number Original line Diff line number Diff line Loading @@ -18,10 +18,12 @@ package com.android.launcher3.taskbar; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import android.animation.Animator; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.content.ClipData; import android.content.ClipData; import android.content.ClipDescription; import android.content.ClipDescription; import android.content.Intent; import android.content.Intent; Loading Loading @@ -49,7 +51,6 @@ import com.android.launcher3.DragSource; import com.android.launcher3.DropTarget; import com.android.launcher3.DropTarget; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.accessibility.DragViewStateAnnouncer; import com.android.launcher3.accessibility.DragViewStateAnnouncer; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.config.FeatureFlags; Loading @@ -70,6 +71,7 @@ import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.ItemInfoMatcher; import com.android.quickstep.util.LogUtils; import com.android.quickstep.util.LogUtils; import com.android.quickstep.util.MultiValueUpdateListener; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.Task; import java.io.PrintWriter; import java.io.PrintWriter; Loading @@ -83,7 +85,8 @@ import java.util.function.Predicate; public class TaskbarDragController extends DragController<BaseTaskbarContext> implements public class TaskbarDragController extends DragController<BaseTaskbarContext> implements TaskbarControllers.LoggableTaskbarController { TaskbarControllers.LoggableTaskbarController { private static boolean DEBUG_DRAG_SHADOW_SURFACE = false; private static final boolean DEBUG_DRAG_SHADOW_SURFACE = false; private static final int ANIM_DURATION_RETURN_ICON_TO_TASKBAR = 300; private final int mDragIconSize; private final int mDragIconSize; private final int[] mTempXY = new int[2]; private final int[] mTempXY = new int[2]; Loading @@ -99,6 +102,8 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im // Animation for the drag shadow back into position after an unsuccessful drag // Animation for the drag shadow back into position after an unsuccessful drag private ValueAnimator mReturnAnimator; private ValueAnimator mReturnAnimator; private boolean mDisallowGlobalDrag; private boolean mDisallowLongClick; public TaskbarDragController(BaseTaskbarContext activity) { public TaskbarDragController(BaseTaskbarContext activity) { super(activity); super(activity); Loading @@ -110,6 +115,14 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im mControllers = controllers; mControllers = controllers; } } public void setDisallowGlobalDrag(boolean disallowGlobalDrag) { mDisallowGlobalDrag = disallowGlobalDrag; } public void setDisallowLongClick(boolean disallowLongClick) { mDisallowLongClick = disallowLongClick; } /** /** * Attempts to start a system drag and drop operation for the given View, using its tag to * Attempts to start a system drag and drop operation for the given View, using its tag to * generate the ClipDescription and Intent. * generate the ClipDescription and Intent. Loading @@ -131,7 +144,7 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im View view, View view, @Nullable DragPreviewProvider dragPreviewProvider, @Nullable DragPreviewProvider dragPreviewProvider, @Nullable Point iconShift) { @Nullable Point iconShift) { if (!(view instanceof BubbleTextView)) { if (!(view instanceof BubbleTextView) || mDisallowLongClick) { return false; return false; } } TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onTaskbarItemLongClick"); TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onTaskbarItemLongClick"); Loading Loading @@ -293,6 +306,7 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im } } private void startSystemDrag(BubbleTextView btv) { private void startSystemDrag(BubbleTextView btv) { if (mDisallowGlobalDrag) return; View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(btv) { View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(btv) { @Override @Override Loading Loading @@ -421,6 +435,45 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im } } } } @Override protected void endDrag() { if (mDisallowGlobalDrag) { // We need to explicitly set deferDragViewCleanupPostAnimation to true here so the // super call doesn't remove it from the drag layer before the animation completes. // This variable gets set in to false in super.dispatchDropComplete() because it // (rightfully so, perhaps) thinks this drag operation has failed, and does its own // internal cleanup. // Another way to approach this would be to make all of overview a drop target and // accept the drop as successful and then run the setupReturnDragAnimator to simulate // drop failure to the user mDragObject.deferDragViewCleanupPostAnimation = true; float fromX = mDragObject.x - mDragObject.xOffset; float fromY = mDragObject.y - mDragObject.yOffset; DragView dragView = mDragObject.dragView; setupReturnDragAnimator(fromX, fromY, (View) mDragObject.originalView, (x, y, scale, alpha) -> { dragView.setTranslationX(x); dragView.setTranslationY(y); dragView.setScaleX(scale); dragView.setScaleY(scale); dragView.setAlpha(alpha); }); mReturnAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { callOnDragEnd(); dragView.remove(); dragView.clearAnimation(); mReturnAnimator = null; } }); mReturnAnimator.start(); } super.endDrag(); } @Override @Override protected void callOnDragEnd() { protected void callOnDragEnd() { super.callOnDragEnd(); super.callOnDragEnd(); Loading @@ -432,56 +485,20 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im SurfaceControl dragSurface = dragEvent.getDragSurface(); SurfaceControl dragSurface = dragEvent.getDragSurface(); // For top level icons, the target is the icon itself // For top level icons, the target is the icon itself View target = btv; View target = findTaskbarTargetForIconView(btv); Object tag = btv.getTag(); if (tag instanceof ItemInfo) { ItemInfo item = (ItemInfo) tag; TaskbarViewController taskbarViewController = mControllers.taskbarViewController; if (item.container == CONTAINER_ALL_APPS || item.container == CONTAINER_PREDICTION) { // Since all apps closes when the drag starts, target the all apps button instead. target = taskbarViewController.getAllAppsButtonView(); } else if (item.container >= 0) { // Since folders close when the drag starts, target the folder icon instead. Predicate<ItemInfo> matcher = ItemInfoMatcher.forFolderMatch( ItemInfoMatcher.ofItemIds(IntSet.wrap(item.id))); target = taskbarViewController.getFirstIconMatch(matcher); } else if (item.itemType == ITEM_TYPE_DEEP_SHORTCUT) { // Find first icon with same package/user as the deep shortcut. Predicate<ItemInfo> packageUserMatcher = ItemInfoMatcher.ofPackages( Collections.singleton(item.getTargetPackage()), item.user); target = taskbarViewController.getFirstIconMatch(packageUserMatcher); } } // Finish any pending return animation before starting a new drag if (mReturnAnimator != null) { mReturnAnimator.end(); } float fromX = dragEvent.getX() - dragEvent.getOffsetX(); float fromX = dragEvent.getX() - dragEvent.getOffsetX(); float fromY = dragEvent.getY() - dragEvent.getOffsetY(); 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(); final ViewRootImpl viewRoot = target.getViewRootImpl(); SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); mReturnAnimator = ValueAnimator.ofFloat(0f, 1f); setupReturnDragAnimator(fromX, fromY, btv, mReturnAnimator.setDuration(300); (x, y, scale, alpha) -> { mReturnAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); tx.setPosition(dragSurface, x, y); 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.setScale(dragSurface, scale, scale); tx.setAlpha(dragSurface, alpha); tx.setAlpha(dragSurface, alpha); tx.apply(); tx.apply(); } }); }); mReturnAnimator.addListener(new AnimatorListenerAdapter() { mReturnAnimator.addListener(new AnimatorListenerAdapter() { private boolean mCanceled = false; private boolean mCanceled = false; Loading Loading @@ -517,6 +534,63 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im mReturnAnimator.start(); mReturnAnimator.start(); } } private View findTaskbarTargetForIconView(@NonNull View iconView) { Object tag = iconView.getTag(); if (tag instanceof ItemInfo) { ItemInfo item = (ItemInfo) tag; TaskbarViewController taskbarViewController = mControllers.taskbarViewController; if (item.container == CONTAINER_ALL_APPS || item.container == CONTAINER_PREDICTION) { // Since all apps closes when the drag starts, target the all apps button instead. return taskbarViewController.getAllAppsButtonView(); } else if (item.container >= 0) { // Since folders close when the drag starts, target the folder icon instead. Predicate<ItemInfo> matcher = ItemInfoMatcher.forFolderMatch( ItemInfoMatcher.ofItemIds(IntSet.wrap(item.id))); return taskbarViewController.getFirstIconMatch(matcher); } else if (item.itemType == ITEM_TYPE_DEEP_SHORTCUT) { // Find first icon with same package/user as the deep shortcut. Predicate<ItemInfo> packageUserMatcher = ItemInfoMatcher.ofPackages( Collections.singleton(item.getTargetPackage()), item.user); return taskbarViewController.getFirstIconMatch(packageUserMatcher); } } return iconView; } private void setupReturnDragAnimator(float fromX, float fromY, View originalView, TaskbarReturnPropertiesListener animListener) { // Finish any pending return animation before starting a new return if (mReturnAnimator != null) { mReturnAnimator.end(); } // For top level icons, the target is the icon itself View target = findTaskbarTargetForIconView(originalView); int[] toPosition = target.getLocationOnScreen(); float toScale = (float) target.getWidth() / mDragIconSize; float toAlpha = (target == originalView) ? 1f : 0f; MultiValueUpdateListener listener = new MultiValueUpdateListener() { final FloatProp mDx = new FloatProp(fromX, toPosition[0], 0, ANIM_DURATION_RETURN_ICON_TO_TASKBAR, Interpolators.FAST_OUT_SLOW_IN); final FloatProp mDy = new FloatProp(fromY, toPosition[1], 0, ANIM_DURATION_RETURN_ICON_TO_TASKBAR, FAST_OUT_SLOW_IN); final FloatProp mScale = new FloatProp(1f, toScale, 0, ANIM_DURATION_RETURN_ICON_TO_TASKBAR, FAST_OUT_SLOW_IN); final FloatProp mAlpha = new FloatProp(1f, toAlpha, 0, ANIM_DURATION_RETURN_ICON_TO_TASKBAR, Interpolators.ACCEL_2); @Override public void onUpdate(float percent, boolean initOnly) { animListener.updateDragShadow(mDx.value, mDy.value, mScale.value, mAlpha.value); } }; mReturnAnimator = ValueAnimator.ofFloat(0f, 1f); mReturnAnimator.setDuration(ANIM_DURATION_RETURN_ICON_TO_TASKBAR); mReturnAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); mReturnAnimator.addUpdateListener(listener); } @Override @Override protected float getX(MotionEvent ev) { protected float getX(MotionEvent ev) { // We will resize to fill the screen while dragging, so use screen coordinates. This ensures // We will resize to fill the screen while dragging, so use screen coordinates. This ensures Loading @@ -540,7 +614,7 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im @Override @Override protected void exitDrag() { protected void exitDrag() { if (mDragObject != null) { if (mDragObject != null && !mDisallowGlobalDrag) { mActivity.getDragLayer().removeView(mDragObject.dragView); mActivity.getDragLayer().removeView(mDragObject.dragView); } } } } Loading @@ -556,6 +630,10 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im return null; return null; } } interface TaskbarReturnPropertiesListener { void updateDragShadow(float x, float y, float scale, float alpha); } @Override @Override public void dumpLogs(String prefix, PrintWriter pw) { public void dumpLogs(String prefix, PrintWriter pw) { pw.println(prefix + "TaskbarDragController:"); pw.println(prefix + "TaskbarDragController:"); Loading @@ -566,5 +644,7 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im pw.println(prefix + "\tmRegistrationY=" + mRegistrationY); pw.println(prefix + "\tmRegistrationY=" + mRegistrationY); pw.println(prefix + "\tmIsSystemDragInProgress=" + mIsSystemDragInProgress); pw.println(prefix + "\tmIsSystemDragInProgress=" + mIsSystemDragInProgress); pw.println(prefix + "\tisInternalDragInProgess=" + super.isDragging()); pw.println(prefix + "\tisInternalDragInProgess=" + super.isDragging()); pw.println(prefix + "\tmDisallowGlobalDrag=" + mDisallowGlobalDrag); pw.println(prefix + "\tmDisallowLongClick=" + mDisallowLongClick); } } } }
quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +6 −0 Original line number Original line Diff line number Diff line Loading @@ -39,6 +39,8 @@ import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; import com.android.launcher3.util.MultiPropertyFactory.MultiProperty; import com.android.launcher3.uioverrides.states.OverviewState; import com.android.launcher3.util.MultiValueAlpha; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationController; import com.android.quickstep.RecentsAnimationController; Loading Loading @@ -117,6 +119,10 @@ import java.util.StringJoiner; mLauncherState = finalState; mLauncherState = finalState; updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, false); updateStateForFlag(FLAG_TRANSITION_STATE_RUNNING, false); applyState(); applyState(); mControllers.taskbarDragController.setDisallowGlobalDrag( (finalState instanceof OverviewState)); mControllers.taskbarDragController.setDisallowLongClick( finalState == LauncherState.OVERVIEW_SPLIT_SELECT); } } }; }; Loading