summaryrefslogtreecommitdiff
path: root/quickstep/src
diff options
context:
space:
mode:
author Mykola Podolian <mpodolian@google.com> 2025-03-20 13:40:29 -0700
committer Android (Google) Code Review <android-gerrit@google.com> 2025-03-20 13:40:29 -0700
commitc12d67c4e07f01b562e6dba64c925347d3645985 (patch)
tree93e5d78746b49a6ec636c86b7165d42fa269e9a7 /quickstep/src
parent0d5889118714cf4ab86563309e34822515e413c6 (diff)
parent6ddfa5dfd5e5860de3bdaf7b2c887b6b49c674e2 (diff)
Merge "Drag and drop from the search view on the overview screen." into main
Diffstat (limited to 'quickstep/src')
-rw-r--r--quickstep/src/com/android/launcher3/taskbar/BarsLocationAnimatorHelper.kt34
-rw-r--r--quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java15
-rw-r--r--quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java57
-rw-r--r--quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java81
-rw-r--r--quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java5
-rw-r--r--quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt9
-rw-r--r--quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt132
7 files changed, 255 insertions, 78 deletions
diff --git a/quickstep/src/com/android/launcher3/taskbar/BarsLocationAnimatorHelper.kt b/quickstep/src/com/android/launcher3/taskbar/BarsLocationAnimatorHelper.kt
index b8060e1792..ad847b47ee 100644
--- a/quickstep/src/com/android/launcher3/taskbar/BarsLocationAnimatorHelper.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/BarsLocationAnimatorHelper.kt
@@ -20,6 +20,7 @@ import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
+import android.content.Context
import android.view.View
import androidx.dynamicanimation.animation.SpringForce
import com.android.app.animation.Interpolators
@@ -30,11 +31,10 @@ import com.android.wm.shell.shared.bubbles.BubbleBarLocation
/** Animator helper that creates bars animators. */
object BarsLocationAnimatorHelper {
-
- private const val FADE_OUT_ANIM_ALPHA_DURATION_MS: Long = 50L
- private const val FADE_OUT_ANIM_ALPHA_DELAY_MS: Long = 50L
- private const val FADE_OUT_ANIM_POSITION_DURATION_MS: Long = 100L
- private const val FADE_IN_ANIM_ALPHA_DURATION_MS: Long = 100L
+ const val FADE_OUT_ANIM_ALPHA_DURATION_MS: Long = 50L
+ const val FADE_OUT_ANIM_ALPHA_DELAY_MS: Long = 50L
+ const val FADE_OUT_ANIM_POSITION_DURATION_MS: Long = 100L
+ const val FADE_IN_ANIM_ALPHA_DURATION_MS: Long = 100L
// Use STIFFNESS_MEDIUMLOW which is not defined in the API constants
private const val FADE_IN_ANIM_POSITION_SPRING_STIFFNESS: Float = 400f
@@ -45,13 +45,13 @@ object BarsLocationAnimatorHelper {
// During fade in animation we shift the bubble bar 1/60th of the screen width
private const val FADE_IN_ANIM_POSITION_SHIFT: Float = 1 / 60f
- private val View.screenWidth: Int
+ private val Context.screenWidth: Int
get() = resources.displayMetrics.widthPixels
- private val View.outShift: Float
+ val Context.outShift: Float
get() = screenWidth * FADE_OUT_ANIM_POSITION_SHIFT
- private val View.inShiftX: Float
+ val Context.inShiftX: Float
get() = screenWidth * FADE_IN_ANIM_POSITION_SHIFT
/**
@@ -108,7 +108,7 @@ object BarsLocationAnimatorHelper {
targetViewAlphaAnim: ObjectAnimator,
bubbleBarView: View,
): Animator {
- val shift: Float = bubbleBarView.outShift
+ val shift: Float = bubbleBarView.context.outShift
val onLeft = newLocation.isOnLeft(bubbleBarView.isLayoutRtl)
val startTx: Float
@@ -132,15 +132,19 @@ object BarsLocationAnimatorHelper {
return createLocationInAnimator(startTx, finalTx, targetViewAlphaAnim, bubbleBarView)
}
- /** Creates an animator for the bubble bar view out part. */
+ /**
+ * Creates an animator for the bubble bar view out part.
+ *
+ * @param targetLocation the location bubble bar should animate to.
+ */
@JvmStatic
fun getBubbleBarLocationOutAnimator(
bubbleBarView: View,
- bubbleBarLocation: BubbleBarLocation,
+ targetLocation: BubbleBarLocation,
targetViewAlphaAnim: ObjectAnimator,
): Animator {
- val onLeft = bubbleBarLocation.isOnLeft(bubbleBarView.isLayoutRtl)
- val shift = bubbleBarView.outShift
+ val onLeft = targetLocation.isOnLeft(bubbleBarView.isLayoutRtl)
+ val shift = bubbleBarView.context.outShift
val finalTx = bubbleBarView.translationX + (if (onLeft) -shift else shift)
return this.createLocationOutAnimator(finalTx, targetViewAlphaAnim, bubbleBarView)
}
@@ -152,7 +156,7 @@ object BarsLocationAnimatorHelper {
navButtonsView: View,
navBarTargetTranslationX: Float,
): Animator {
- val outShift: Float = navButtonsView.outShift
+ val outShift: Float = navButtonsView.context.outShift
val isNavBarOnRight: Boolean = location.isOnLeft(navButtonsView.isLayoutRtl)
val finalOutTx =
navButtonsView.translationX + (if (isNavBarOnRight) outShift else -outShift)
@@ -162,7 +166,7 @@ object BarsLocationAnimatorHelper {
ObjectAnimator.ofFloat(navButtonsView, LauncherAnimUtils.VIEW_ALPHA, 0f),
navButtonsView,
)
- val inShift: Float = navButtonsView.inShiftX
+ val inShift: Float = navButtonsView.context.inShiftX
val inStartX = navBarTargetTranslationX + (if (isNavBarOnRight) -inShift else inShift)
val fadeIn: Animator =
createLocationInAnimator(
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 142f458b3b..4b977e0d23 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -510,6 +510,8 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im
} else {
// This will take care of calling maybeOnDragEnd() after the animation
animateGlobalDragViewToOriginalPosition(btv, dragEvent);
+ //TODO(b/399678274): hide drop target in shell
+ notifyBubbleBarItemDragCanceled();
}
mActivity.getDragLayer().setOnDragListener(null);
@@ -536,10 +538,10 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im
mControllers.taskbarAutohideSuspendController.updateFlag(
TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING, false);
mActivity.onDragEnd();
+ // If an item is dropped on the bubble bar, the bubble bar handles the drop,
+ // so it should not collapse along with the taskbar.
+ boolean droppedOnBubbleBar = notifyBubbleBarItemDropped();
if (mReturnAnimator == null) {
- // If an item is dropped on the bubble bar, the bubble bar handles the drop,
- // so it should not collapse along with the taskbar.
- boolean droppedOnBubbleBar = notifyBubbleBarItemDropped();
// Upon successful drag, immediately stash taskbar.
// Note, this must be done last to ensure no AutohideSuspendFlags are active, as
// that will prevent us from stashing until the timeout.
@@ -563,12 +565,17 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im
BubbleBarViewController bubbleBarViewController = bc.bubbleBarViewController;
boolean showingDropTarget = bubbleBarViewController.isShowingDropTarget();
if (showingDropTarget) {
- bubbleBarViewController.onItemDroppedInBubbleBarDragZone();
+ bubbleBarViewController.onItemDragCompleted();
}
return showingDropTarget;
}).orElse(false);
}
+ private void notifyBubbleBarItemDragCanceled() {
+ mControllers.bubbleControllers.ifPresent(bc ->
+ bc.bubbleBarViewController.onItemDraggedOutsideBubbleBarDropZone());
+ }
+
@Override
protected void endDrag() {
if (mDisallowGlobalDrag && !mIsDropHandledByDropTarget) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index 1abef8a63f..6380c2371b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -18,6 +18,7 @@ package com.android.launcher3.taskbar.bubbles;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
@@ -560,30 +561,52 @@ public class BubbleBarView extends FrameLayout {
// First animator hides the bar.
// After it completes, bubble positions in the bar and arrow position is updated.
// Second animator is started to show the bar.
- ObjectAnimator alphaOutAnim = ObjectAnimator.ofFloat(
- this, getLocationAnimAlphaProperty(), 0f);
- mBubbleBarLocationAnimator = BarsLocationAnimatorHelper.getBubbleBarLocationOutAnimator(
- this,
- bubbleBarLocation,
- alphaOutAnim);
+ mBubbleBarLocationAnimator = animateToBubbleBarLocationOut(bubbleBarLocation);
mBubbleBarLocationAnimator.addListener(AnimatorListeners.forEndCallback(() -> {
- updateBubblesLayoutProperties(bubbleBarLocation);
- mBubbleBarBackground.setAnchorLeft(bubbleBarLocation.isOnLeft(isLayoutRtl()));
- ObjectAnimator alphaInAnim = ObjectAnimator.ofFloat(BubbleBarView.this,
- getLocationAnimAlphaProperty(), 1f);
-
// Animate it in
- mBubbleBarLocationAnimator = BarsLocationAnimatorHelper.getBubbleBarLocationInAnimator(
- bubbleBarLocation,
- mBubbleBarLocation,
- getDistanceFromOtherSide(),
- alphaInAnim,
- BubbleBarView.this);
+ mBubbleBarLocationAnimator = animateToBubbleBarLocationIn(mBubbleBarLocation,
+ bubbleBarLocation);
mBubbleBarLocationAnimator.start();
}));
mBubbleBarLocationAnimator.start();
}
+ /** Creates animator for animating bubble bar in. */
+ public Animator animateToBubbleBarLocationIn(BubbleBarLocation fromLocation,
+ BubbleBarLocation toLocation) {
+ updateBubblesLayoutProperties(toLocation);
+ mBubbleBarBackground.setAnchorLeft(toLocation.isOnLeft(isLayoutRtl()));
+ ObjectAnimator alphaInAnim = ObjectAnimator.ofFloat(BubbleBarView.this,
+ getLocationAnimAlphaProperty(), 1f);
+ return BarsLocationAnimatorHelper.getBubbleBarLocationInAnimator(toLocation, fromLocation,
+ getDistanceFromOtherSide(), alphaInAnim, this);
+ }
+
+ /**
+ * Creates animator for animating bubble bar out.
+ *
+ * @param targetLocation the location bubble br should animate to.
+ */
+ public Animator animateToBubbleBarLocationOut(BubbleBarLocation targetLocation) {
+ ObjectAnimator alphaOutAnim = ObjectAnimator.ofFloat(
+ this, getLocationAnimAlphaProperty(), 0f);
+ Animator outAnimation = BarsLocationAnimatorHelper.getBubbleBarLocationOutAnimator(
+ this,
+ targetLocation,
+ alphaOutAnim);
+ outAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(@NonNull Animator animation, boolean isReverse) {
+ // need to restore the original bar view state in case icon is dropped to the bubble
+ // bar original location
+ updateBubblesLayoutProperties(targetLocation);
+ mBubbleBarBackground.setAnchorLeft(targetLocation.isOnLeft(isLayoutRtl()));
+ setTranslationX(0f);
+ }
+ });
+ return outAnimation;
+ }
+
/**
* Get property that can be used to animate the alpha value for the bar.
* When a bubble is being dragged, uses {@link #BUBBLE_DRAG_ALPHA}.
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index 9fb283cccf..ce4a14f551 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -194,9 +194,11 @@ public class BubbleBarViewController {
private boolean mHiddenForStashed;
private boolean mShouldShowEducation;
public boolean mOverflowAdded;
- private boolean mIsLocationUpdatedForDropTarget = false;
private boolean mWasStashedBeforeEnteringBubbleDragZone = false;
+ /** This field is used solely to track the bubble bar location prior to the start of the drag */
+ private @Nullable BubbleBarLocation mBubbleBarDragLocation;
+
private BubbleBarViewAnimator mBubbleBarViewAnimator;
private final FrameLayout mBubbleBarContainer;
private BubbleBarFlyoutController mBubbleBarFlyoutController;
@@ -364,7 +366,7 @@ public class BubbleBarViewController {
@Override
public boolean isOnLeft() {
boolean shouldRevertLocation =
- mBarView.isShowingDropTarget() && mIsLocationUpdatedForDropTarget;
+ mBarView.isShowingDropTarget() && isLocationUpdatedForDropTarget();
boolean isOnLeft = mBarView.getBubbleBarLocation().isOnLeft(mBarView.isLayoutRtl());
return shouldRevertLocation != isOnLeft;
}
@@ -616,6 +618,17 @@ public class BubbleBarViewController {
mBarView.animateToBubbleBarLocation(bubbleBarLocation);
}
+ /** Return animator for animating bubble bar in. */
+ public Animator animateBubbleBarLocationIn(BubbleBarLocation fromLocation,
+ BubbleBarLocation toLocation) {
+ return mBarView.animateToBubbleBarLocationIn(fromLocation, toLocation);
+ }
+
+ /** Return animator for animating bubble bar out. */
+ public Animator animateBubbleBarLocationOut(BubbleBarLocation toLocation) {
+ return mBarView.animateToBubbleBarLocationOut(toLocation);
+ }
+
/** Returns whether the Bubble Bar is currently displaying a drop target. */
public boolean isShowingDropTarget() {
return mBarView.isShowingDropTarget();
@@ -628,25 +641,18 @@ public class BubbleBarViewController {
* updated.
*/
public void onDragItemOverBubbleBarDragZone(@NonNull BubbleBarLocation bubbleBarLocation) {
- Log.w("BBAnimation", "onDragItemOverBubbleBarDragZone()");
+ mBubbleBarDragLocation = bubbleBarLocation;
mBarView.showDropTarget(/* isDropTarget = */ true);
- boolean isRtl = mBarView.isLayoutRtl();
- mIsLocationUpdatedForDropTarget = getBubbleBarLocation().isOnLeft(isRtl)
- != bubbleBarLocation.isOnLeft(isRtl);
mWasStashedBeforeEnteringBubbleDragZone = hasBubbles()
&& mBubbleStashController.isStashed();
if (mWasStashedBeforeEnteringBubbleDragZone) {
- if (mIsLocationUpdatedForDropTarget) {
- // bubble bar is stashed an location updated
- //TODO(b/399678274) add animation
- mBubbleStashController.showBubbleBarImmediate();
- animateBubbleBarLocation(bubbleBarLocation);
- } else {
- // bubble bar is stashed and location the same - just un-stash
- mBubbleStashController.showBubbleBar(/* expandBubbles = */ false);
- }
+ // bubble bar is stashed - un-stash at drag location
+ mBubbleStashController.showBubbleBarAtLocation(
+ /* fromLocation = */ getBubbleBarLocation(),
+ /* toLocation = */ mBubbleBarDragLocation
+ );
} else if (hasBubbles()) {
- if (mIsLocationUpdatedForDropTarget) {
+ if (isLocationUpdatedForDropTarget()) {
// bubble bar has bubbles and location is changed - animate bar to the opposite side
animateBubbleBarLocation(bubbleBarLocation);
}
@@ -661,7 +667,12 @@ public class BubbleBarViewController {
* {@link #onDragItemOverBubbleBarDragZone}}.
*/
public boolean isLocationUpdatedForDropTarget() {
- return mIsLocationUpdatedForDropTarget;
+ if (mBubbleBarDragLocation == null) {
+ return false;
+ }
+ boolean isRtl = mBarView.isLayoutRtl();
+ return getBubbleBarLocation().isOnLeft(isRtl)
+ != mBubbleBarDragLocation.isOnLeft(isRtl);
}
/**
@@ -671,39 +682,34 @@ public class BubbleBarViewController {
* mode and reset the value returned from {@link #isLocationUpdatedForDropTarget()} to false.
*/
public void onItemDraggedOutsideBubbleBarDropZone() {
- Log.w("BBAnimation", "onItemDraggedOutsideBubbleBarDropZone()");
- mBarView.showDropTarget(/* isDropTarget = */ false);
- if (mWasStashedBeforeEnteringBubbleDragZone) {
- if (mIsLocationUpdatedForDropTarget) {
- // bubble bar was stashed and location updated
- //TODO(b/399678274) add animation
- animateBubbleBarLocation(getBubbleBarLocation());
- mBubbleStashController.stashBubbleBarImmediate();
- } else {
- // bubble bar was stashed and location the same - just stash it back
- mBubbleStashController.stashBubbleBar();
- }
+ if (!isShowingDropTarget()) {
+ return;
+ }
+ if (mWasStashedBeforeEnteringBubbleDragZone && mBubbleBarDragLocation != null) {
+ // bubble bar was stashed - stash at original location
+ mBubbleStashController.stashBubbleBarToLocation(
+ /* fromLocation = */ mBubbleBarDragLocation,
+ /* toLocation = */ getBubbleBarLocation()
+ );
} else if (hasBubbles()) {
- if (mIsLocationUpdatedForDropTarget) {
- // bubble bar has bubbles and location was changed - return to the original location
+ if (isLocationUpdatedForDropTarget()) {
+ // bubble bar has bubbles and location was changed - return to the original
+ // location
animateBubbleBarLocation(getBubbleBarLocation());
}
}
- mBubbleBarPinController.hideDropTarget();
- mIsLocationUpdatedForDropTarget = false;
- mWasStashedBeforeEnteringBubbleDragZone = false;
+ onItemDragCompleted();
}
/**
* Notifies the controller that the drag has completed over the Bubble Bar drop zone.
* The controller will hide the drop target if there are no bubbles and exit drop target mode.
*/
- public void onItemDroppedInBubbleBarDragZone() {
- Log.w("BBAnimation", "onItemDroppedInBubbleBarDragZone()");
+ public void onItemDragCompleted() {
mBarView.showDropTarget(/* isDropTarget = */ false);
mBubbleBarPinController.hideDropTarget();
- mIsLocationUpdatedForDropTarget = false;
mWasStashedBeforeEnteringBubbleDragZone = false;
+ mBubbleBarDragLocation = null;
}
/**
@@ -842,6 +848,7 @@ public class BubbleBarViewController {
boolean hiddenForStashedAndNotAnimating =
mHiddenForStashed && !mBubbleBarViewAnimator.isAnimating();
if (mHiddenForSysui || mHiddenForNoBubbles || hiddenForStashedAndNotAnimating) {
+ //TODO(b/404870188) this visibility change cause search view drag misbehavior
mBarView.setVisibility(INVISIBLE);
} else {
mBarView.setVisibility(VISIBLE);
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
index 3640c3b60e..ec540e0088 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
@@ -272,6 +272,11 @@ public class BubbleStashedHandleViewController {
updateTranslationY();
}
+ /** Sets translation X for stash handle. */
+ public void setTranslationX(float translationX) {
+ mStashedHandleView.setTranslationX(translationX);
+ }
+
private void updateTranslationY() {
mStashedHandleView.setTranslationY(mTranslationForSwipeY + mTranslationForStashY);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt
index fec1eaf55c..ec272ac873 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/BubbleStashController.kt
@@ -131,6 +131,12 @@ interface BubbleStashController {
*/
fun stashBubbleBar()
+ /**
+ * Animates the bubble bar to the handle at provided location. Does not update bubble bar
+ * location.
+ */
+ fun stashBubbleBarToLocation(fromLocation: BubbleBarLocation, toLocation: BubbleBarLocation) {}
+
/** Shows the bubble bar, and expands bubbles depending on [expandBubbles]. */
fun showBubbleBar(expandBubbles: Boolean) {
showBubbleBar(expandBubbles = expandBubbles, bubbleBarGesture = false)
@@ -144,6 +150,9 @@ interface BubbleStashController {
*/
fun showBubbleBar(expandBubbles: Boolean, bubbleBarGesture: Boolean)
+ /** Animates the bubble bar at the provided location. Does not update bubble bar location. */
+ fun showBubbleBarAtLocation(fromLocation: BubbleBarLocation, toLocation: BubbleBarLocation) {}
+
// TODO(b/354218264): Move to BubbleBarViewAnimator
/**
* The difference on the Y axis between the center of the handle and the center of the bubble
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt
index 9c148e2191..82bb071bc3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/stashing/TransientBubbleStashController.kt
@@ -18,6 +18,7 @@ package com.android.launcher3.taskbar.bubbles.stashing
import android.animation.Animator
import android.animation.AnimatorSet
+import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Rect
import android.view.MotionEvent
@@ -31,6 +32,12 @@ import com.android.app.animation.Interpolators.LINEAR
import com.android.launcher3.R
import com.android.launcher3.anim.AnimatedFloat
import com.android.launcher3.anim.SpringAnimationBuilder
+import com.android.launcher3.taskbar.BarsLocationAnimatorHelper.FADE_IN_ANIM_ALPHA_DURATION_MS
+import com.android.launcher3.taskbar.BarsLocationAnimatorHelper.FADE_OUT_ANIM_ALPHA_DELAY_MS
+import com.android.launcher3.taskbar.BarsLocationAnimatorHelper.FADE_OUT_ANIM_ALPHA_DURATION_MS
+import com.android.launcher3.taskbar.BarsLocationAnimatorHelper.FADE_OUT_ANIM_POSITION_DURATION_MS
+import com.android.launcher3.taskbar.BarsLocationAnimatorHelper.inShiftX
+import com.android.launcher3.taskbar.BarsLocationAnimatorHelper.outShift
import com.android.launcher3.taskbar.TaskbarInsetsController
import com.android.launcher3.taskbar.TaskbarStashController.TASKBAR_STASH_ALPHA_START_DELAY
import com.android.launcher3.taskbar.TaskbarStashController.TRANSIENT_TASKBAR_STASH_ALPHA_DURATION
@@ -44,6 +51,7 @@ import com.android.launcher3.taskbar.bubbles.stashing.BubbleStashController.Task
import com.android.launcher3.util.MultiPropertyFactory
import com.android.wm.shell.shared.animation.PhysicsAnimator
import com.android.wm.shell.shared.bubbles.BubbleBarLocation
+import com.android.wm.shell.shared.bubbles.ContextUtils.isRtl
import kotlin.math.max
class TransientBubbleStashController(
@@ -187,6 +195,11 @@ class TransientBubbleStashController(
}
override fun showBubbleBarImmediate(bubbleBarTranslationY: Float) {
+ showBubbleBarImmediateVisually(bubbleBarTranslationY)
+ onIsStashedChanged()
+ }
+
+ private fun showBubbleBarImmediateVisually(bubbleBarTranslationY: Float) {
bubbleStashedHandleViewController?.setTranslationYForSwipe(0f)
stashHandleViewAlpha?.value = 0f
this.bubbleBarTranslationYAnimator.updateValue(bubbleBarTranslationY)
@@ -197,10 +210,14 @@ class TransientBubbleStashController(
bubbleBarBackgroundScaleY.updateValue(1f)
isStashed = false
bubbleBarViewController.setHiddenForStashed(false)
- onIsStashedChanged()
}
override fun stashBubbleBarImmediate() {
+ stashBubbleBarImmediateVisually()
+ onIsStashedChanged()
+ }
+
+ private fun stashBubbleBarImmediateVisually() {
bubbleStashedHandleViewController?.setTranslationYForSwipe(0f)
stashHandleViewAlpha?.value = 1f
this.bubbleBarTranslationYAnimator.updateValue(getStashTranslation())
@@ -212,7 +229,6 @@ class TransientBubbleStashController(
bubbleBarBackgroundScaleY.updateValue(getStashScaleY())
isStashed = true
bubbleBarViewController.setHiddenForStashed(true)
- onIsStashedChanged()
}
override fun getTouchableHeight(): Int =
@@ -247,6 +263,29 @@ class TransientBubbleStashController(
updateStashedAndExpandedState(stash = true, expand = false)
}
+ override fun stashBubbleBarToLocation(
+ fromLocation: BubbleBarLocation,
+ toLocation: BubbleBarLocation,
+ ) {
+ if (fromLocation.isSameSideWith(toLocation)) {
+ updateStashedAndExpandedState(
+ stash = true,
+ expand = false,
+ updateTouchRegionOnEnd = false,
+ )
+ return
+ }
+ cancelAnimation()
+ animator =
+ AnimatorSet().apply {
+ playSequentially(
+ bubbleBarViewController.animateBubbleBarLocationOut(toLocation),
+ createHandleInAnimator(location = toLocation),
+ )
+ start()
+ }
+ }
+
override fun showBubbleBar(expandBubbles: Boolean, bubbleBarGesture: Boolean) {
updateStashedAndExpandedState(
stash = false,
@@ -255,6 +294,33 @@ class TransientBubbleStashController(
)
}
+ override fun showBubbleBarAtLocation(
+ fromLocation: BubbleBarLocation,
+ toLocation: BubbleBarLocation,
+ ) {
+ if (fromLocation.isSameSideWith(toLocation)) {
+ updateStashedAndExpandedState(
+ stash = false,
+ expand = false,
+ updateTouchRegionOnEnd = false,
+ )
+ return
+ }
+ cancelAnimation()
+ val bubbleBarInAnimation =
+ bubbleBarViewController.animateBubbleBarLocationIn(fromLocation, toLocation).apply {
+ doOnStart { showBubbleBarImmediateVisually(bubbleBarTranslationY) }
+ }
+ animator =
+ AnimatorSet().apply {
+ playSequentially(
+ createHandleOutAnimator(location = toLocation),
+ bubbleBarInAnimation,
+ )
+ start()
+ }
+ }
+
override fun getDiffBetweenHandleAndBarCenters(): Float {
// the difference between the centers of the handle and the bubble bar is the difference
// between their distance from the bottom of the screen.
@@ -392,7 +458,7 @@ class TransientBubbleStashController(
bubbleBarAlpha.value = 1f
}
animatorSet.doOnEnd {
- animator = null
+ cancelAnimation()
controllersAfterInitAction.runAfterInit {
if (isStashed) {
bubbleBarAlpha.value = 0f
@@ -486,6 +552,7 @@ class TransientBubbleStashController(
stash: Boolean,
expand: Boolean,
bubbleBarGesture: Boolean = false,
+ updateTouchRegionOnEnd: Boolean = true,
) {
if (bubbleBarViewController.isHiddenForNoBubbles) {
// If there are no bubbles the bar and handle are invisible, nothing to do here.
@@ -498,11 +565,13 @@ class TransientBubbleStashController(
// notify the view controller that the stash state is about to change so that it can
// cancel an ongoing animation if there is one.
bubbleBarViewController.onStashStateChanging()
- animator?.cancel()
+ cancelAnimation()
animator =
createStashAnimator(isStashed, BAR_STASH_DURATION).apply {
updateBarVisibility(isStashed)
- updateTouchRegionOnAnimationEnd()
+ if (updateTouchRegionOnEnd) {
+ updateTouchRegionOnAnimationEnd()
+ }
start()
}
}
@@ -512,6 +581,11 @@ class TransientBubbleStashController(
}
}
+ private fun cancelAnimation() {
+ animator?.cancel()
+ animator = null
+ }
+
override fun getHandleViewAlpha(): MultiPropertyFactory<View>.MultiProperty? =
// only return handle alpha if the bubble bar is stashed and has bubbles
if (isStashed && bubbleBarViewController.hasBubbles()) {
@@ -534,6 +608,49 @@ class TransientBubbleStashController(
return this
}
+ // TODO(b/399678274) add tests
+ private fun createHandleInAnimator(location: BubbleBarLocation): Animator? {
+ val stashHandleViewController = bubbleStashedHandleViewController ?: return null
+ val handleAlpha = stashHandleViewController.stashedHandleAlpha.get(0)
+ val shift = context.inShiftX
+ val startX = if (location.isOnLeft(context.isRtl)) shift else -shift
+ val handleTranslationX =
+ ValueAnimator.ofFloat(startX, 0f).apply {
+ addUpdateListener { v ->
+ stashHandleViewController.setTranslationX(v.animatedValue as Float)
+ }
+ duration = FADE_IN_ANIM_ALPHA_DURATION_MS
+ }
+ val handleAlphaAnimation =
+ handleAlpha.animateToValue(1f).apply { duration = FADE_IN_ANIM_ALPHA_DURATION_MS }
+ return AnimatorSet().apply {
+ playTogether(handleTranslationX, handleAlphaAnimation)
+ doOnStart { stashBubbleBarImmediateVisually() }
+ }
+ }
+
+ private fun createHandleOutAnimator(location: BubbleBarLocation): Animator? {
+ val stashHandleViewController = bubbleStashedHandleViewController ?: return null
+ val handleAlpha = stashHandleViewController.stashedHandleAlpha.get(0)
+ val shift = context.outShift
+ val endX = if (location.isOnLeft(context.isRtl)) -shift else shift
+ val handleTranslationX =
+ ValueAnimator.ofFloat(0f, endX).apply {
+ addUpdateListener { v ->
+ stashHandleViewController.setTranslationX(v.animatedValue as Float)
+ }
+ duration = FADE_OUT_ANIM_POSITION_DURATION_MS
+ // in case item dropped to the opposite side - need to clear translation
+ doOnEnd { stashHandleViewController.setTranslationX(0f) }
+ }
+ val handleAlphaAnimation =
+ handleAlpha.animateToValue(0f).apply {
+ duration = FADE_OUT_ANIM_ALPHA_DURATION_MS
+ startDelay = FADE_OUT_ANIM_ALPHA_DELAY_MS
+ }
+ return AnimatorSet().apply { playTogether(handleTranslationX, handleAlphaAnimation) }
+ }
+
private fun Animator.setBubbleBarPivotDuringAnim(pivotX: Float, pivotY: Float): Animator {
var initialPivotX = Float.NaN
var initialPivotY = Float.NaN
@@ -549,4 +666,9 @@ class TransientBubbleStashController(
}
return this
}
+
+ private fun BubbleBarLocation.isSameSideWith(anotherLocation: BubbleBarLocation): Boolean {
+ val isRtl = context.isRtl
+ return this.isOnLeft(isRtl) == anotherLocation.isOnLeft(isRtl)
+ }
}