Merge "Drag and drop from the search view on the overview screen." into main

This commit is contained in:
Mykola Podolian
2025-03-20 13:40:29 -07:00
committed by Android (Google) Code Review
7 changed files with 255 additions and 78 deletions
@@ -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(
@@ -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) {
@@ -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}.
@@ -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);
@@ -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);
}
@@ -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
@@ -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)
}
}