Merge "Update new bubble animation" into main
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
index 61a2e22..76d86de 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
@@ -23,6 +23,7 @@
import android.annotation.Nullable;
import android.view.InsetsController;
import android.view.MotionEvent;
+import android.view.View;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.taskbar.StashedHandleViewController;
@@ -32,6 +33,7 @@
import com.android.launcher3.taskbar.TaskbarStashController;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.wm.shell.common.bubbles.BubbleBarLocation;
+import com.android.wm.shell.shared.animation.PhysicsAnimator;
/**
* Coordinates between controllers such as BubbleBarView and BubbleHandleViewController to
@@ -51,15 +53,6 @@
*/
private static final float STASHED_BAR_SCALE = 0.5f;
- /** The duration of hiding and showing the stashed handle as part of a new bubble animation. */
- private static final long NEW_BUBBLE_HANDLE_ANIMATION_DURATION_MS = 200;
-
- /** The translation Y value the handle animates to when hiding it for a new bubble. */
- private static final int NEW_BUBBLE_HIDE_HANDLE_ANIMATION_TRANSLATION_Y = -20;
-
- /** The alpha value the handle animates to when hiding it for a new bubble. */
- public static final float NEW_BUBBLE_HIDE_HANDLE_ANIMATION_ALPHA = 0.5f;
-
protected final TaskbarActivityContext mActivity;
// Initialized in init.
@@ -73,7 +66,6 @@
private AnimatedFloat mIconScaleForStash;
private AnimatedFloat mIconTranslationYForStash;
private MultiPropertyFactory.MultiProperty mBubbleStashedHandleAlpha;
- private AnimatedFloat mBubbleStashedHandleTranslationY;
private boolean mRequestedStashState;
private boolean mRequestedExpandedState;
@@ -105,7 +97,6 @@
mBubbleStashedHandleAlpha = mHandleViewController.getStashedHandleAlpha().get(
StashedHandleViewController.ALPHA_INDEX_STASHED);
- mBubbleStashedHandleTranslationY = mHandleViewController.getStashedHandleTranslationY();
mStashedHeight = mHandleViewController.getStashedHeight();
mUnstashedHeight = mHandleViewController.getUnstashedHeight();
@@ -379,29 +370,8 @@
return mHandleViewController.getStashedHandleCenterX();
}
- /** Returns the animation for hiding the handle before a new bubble animates in. */
- public AnimatorSet buildHideHandleAnimationForNewBubble() {
- AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.playTogether(
- mBubbleStashedHandleTranslationY.animateToValue(
- NEW_BUBBLE_HIDE_HANDLE_ANIMATION_TRANSLATION_Y),
- mBubbleStashedHandleAlpha.animateToValue(NEW_BUBBLE_HIDE_HANDLE_ANIMATION_ALPHA));
- animatorSet.setDuration(NEW_BUBBLE_HANDLE_ANIMATION_DURATION_MS);
- return animatorSet;
- }
-
- /** Sets the alpha value of the stashed handle. */
- public void setStashAlpha(float alpha) {
- mBubbleStashedHandleAlpha.setValue(alpha);
- }
-
- /** Returns the animation for showing the handle after a new bubble animated in. */
- public AnimatorSet buildShowHandleAnimationForNewBubble() {
- AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.playTogether(
- mBubbleStashedHandleTranslationY.animateToValue(0),
- mBubbleStashedHandleAlpha.animateToValue(1));
- animatorSet.setDuration(NEW_BUBBLE_HANDLE_ANIMATION_DURATION_MS);
- return animatorSet;
+ /** Returns the [PhysicsAnimator] for the stashed handle view. */
+ public PhysicsAnimator<View> getStashedHandlePhysicsAnimator() {
+ return mHandleViewController.getPhysicsAnimator();
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
index 2a5912a..6f1a093 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
@@ -29,7 +29,6 @@
import android.view.ViewOutlineProvider;
import com.android.launcher3.R;
-import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.RevealOutlineAnimation;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.taskbar.StashedHandleView;
@@ -40,6 +39,7 @@
import com.android.launcher3.util.MultiValueAlpha;
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
import com.android.wm.shell.common.bubbles.BubbleBarLocation;
+import com.android.wm.shell.shared.animation.PhysicsAnimator;
/**
* Handles properties/data collection, then passes the results to our stashed handle View to render.
@@ -59,12 +59,6 @@
private int mStashedHandleWidth;
private int mStashedHandleHeight;
- private final AnimatedFloat mStashedHandleTranslationY =
- new AnimatedFloat(this::updateTranslationY);
-
- // Modified when swipe up is happening on the stashed handle or task bar.
- private float mSwipeUpTranslationY;
-
// The bounds we want to clip to in the settled state when showing the stashed handle.
private final Rect mStashedHandleBounds = new Rect();
@@ -129,6 +123,11 @@
updateBounds(mBarViewController.getBubbleBarLocation()));
}
+ /** Returns the [PhysicsAnimator] for the stashed handle view. */
+ public PhysicsAnimator<View> getPhysicsAnimator() {
+ return PhysicsAnimator.getInstance(mStashedHandleView);
+ }
+
private void updateBounds(BubbleBarLocation bubbleBarLocation) {
// As more bubbles get added, the icon bounds become larger. To ensure a consistent
// handle bar position, we pin it to the edge of the screen.
@@ -238,21 +237,11 @@
}
}
- /** Returns an animator for translation Y. */
- public AnimatedFloat getStashedHandleTranslationY() {
- return mStashedHandleTranslationY;
- }
-
/**
* Sets the translation of the stashed handle during the swipe up gesture.
*/
public void setTranslationYForSwipe(float transY) {
- mSwipeUpTranslationY = transY;
- updateTranslationY();
- }
-
- private void updateTranslationY() {
- mStashedHandleView.setTranslationY(mStashedHandleTranslationY.value + mSwipeUpTranslationY);
+ mStashedHandleView.setTranslationY(transY);
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
index 1db5103..2d8983f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
@@ -18,16 +18,12 @@
import android.view.View
import android.view.View.VISIBLE
-import androidx.core.animation.AnimatorSet
-import androidx.core.animation.ObjectAnimator
-import androidx.core.animation.doOnEnd
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.SpringForce
import com.android.launcher3.taskbar.bubbles.BubbleBarBubble
import com.android.launcher3.taskbar.bubbles.BubbleBarView
import com.android.launcher3.taskbar.bubbles.BubbleStashController
import com.android.launcher3.taskbar.bubbles.BubbleView
-import com.android.systemui.util.doOnEnd
import com.android.wm.shell.shared.animation.PhysicsAnimator
/** Handles animations for bubble bar bubbles. */
@@ -43,17 +39,19 @@
/** The time to show the flyout. */
const val FLYOUT_DELAY_MS: Long = 2500
/** The translation Y the new bubble will animate to. */
- const val BUBBLE_ANIMATION_FINAL_TRANSLATION_Y = -50f
+ const val BUBBLE_ANIMATION_BUBBLE_TRANSLATION_Y = -50f
/** The initial translation Y value the new bubble is set to before the animation starts. */
// TODO(liranb): get rid of this and calculate this based on the y-distance between the
// bubble and the stash handle.
- const val BUBBLE_ANIMATION_INITIAL_TRANSLATION_Y = 50f
+ const val BUBBLE_ANIMATION_TRANSLATION_Y_OFFSET = 50f
/** The initial scale Y value that the new bubble is set to before the animation starts. */
const val BUBBLE_ANIMATION_INITIAL_SCALE_Y = 0.3f
- /** The initial alpha value that the new bubble is set to before the animation starts. */
- const val BUBBLE_ANIMATION_INITIAL_ALPHA = 0.5f
- /** The duration of the hide bubble animation. */
- const val HIDE_BUBBLE_ANIMATION_DURATION_MS = 250L
+ /**
+ * The distance the stashed handle will travel as it gets hidden as part of the new bubble
+ * animation.
+ */
+ // TODO(liranb): calculate this based on the position of the views
+ const val BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y = -20f
}
/** An interface for scheduling jobs. */
@@ -91,7 +89,7 @@
if (animator.isRunning()) animator.cancel()
// the animation of a new bubble is divided into 2 parts. The first part shows the bubble
// and the second part hides it after a delay.
- val showAnimation = buildShowAnimation(bubbleView, b.key, animator)
+ val showAnimation = buildShowAnimation(bubbleView, b.key)
val hideAnimation = buildHideAnimation(bubbleView)
scheduler.post(showAnimation)
scheduler.postDelayed(FLYOUT_DELAY_MS, hideAnimation)
@@ -100,71 +98,139 @@
/**
* Returns a lambda that starts the animation that shows the new bubble.
*
- * The animation is divided into 2 parts. First the stash handle starts animating up and fades
- * out. When it ends the bubble starts fading in. The bubble and stashed handle are aligned to
- * give the impression of the stash handle morphing into the bubble.
+ * Visually, the animation is divided into 2 parts. The stash handle starts animating up and
+ * fading out and then the bubble starts animating up and fading in.
+ *
+ * To make the transition from the handle to the bubble smooth, the positions and movement of
+ * the 2 views must be synchronized. To do that we use a single spring path along the Y axis,
+ * starting from the handle's position to the eventual bubble's position. The path is split into
+ * 3 parts.
+ * 1. In the first part, we only animate the handle.
+ * 1. In the second part the handle is fully hidden, and the bubble is animating in.
+ * 1. The third part is the overshoot of the spring animation, where we make the bubble fully
+ * visible which helps avoiding further updates when we re-enter the second part.
*/
private fun buildShowAnimation(
bubbleView: BubbleView,
key: String,
- bubbleAnimator: PhysicsAnimator<BubbleView>
): () -> Unit = {
+ bubbleBarView.prepareForAnimatingBubbleWhileStashed(key)
// calculate the initial translation x the bubble should have in order to align it with the
// stash handle.
val initialTranslationX =
bubbleStashController.stashedHandleCenterX - bubbleView.centerXOnScreen
- bubbleBarView.prepareForAnimatingBubbleWhileStashed(key)
- bubbleAnimator.setDefaultSpringConfig(springConfig)
- bubbleAnimator
- .spring(DynamicAnimation.ALPHA, 1f)
- .spring(DynamicAnimation.TRANSLATION_Y, BUBBLE_ANIMATION_FINAL_TRANSLATION_Y)
- .spring(DynamicAnimation.SCALE_Y, 1f)
// prepare the bubble for the animation
bubbleView.alpha = 0f
bubbleView.translationX = initialTranslationX
- bubbleView.translationY = BUBBLE_ANIMATION_INITIAL_TRANSLATION_Y
bubbleView.scaleY = BUBBLE_ANIMATION_INITIAL_SCALE_Y
bubbleView.visibility = VISIBLE
- // start the stashed handle animation. when it ends, start the bubble animation.
- val stashedHandleAnimation = bubbleStashController.buildHideHandleAnimationForNewBubble()
- stashedHandleAnimation.doOnEnd {
- bubbleView.alpha = BUBBLE_ANIMATION_INITIAL_ALPHA
- bubbleAnimator.start()
- bubbleStashController.setStashAlpha(0f)
+
+ // this is the total distance that both the stashed handle and the bubble will be traveling
+ val totalTranslationY =
+ BUBBLE_ANIMATION_BUBBLE_TRANSLATION_Y + BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y
+ val animator = bubbleStashController.stashedHandlePhysicsAnimator
+ animator.setDefaultSpringConfig(springConfig)
+ animator.spring(DynamicAnimation.TRANSLATION_Y, totalTranslationY)
+ animator.addUpdateListener { target, values ->
+ val ty = values[DynamicAnimation.TRANSLATION_Y]?.value ?: return@addUpdateListener
+ when {
+ ty >= BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y -> {
+ // we're in the first leg of the animation. only animate the handle. the bubble
+ // remains hidden during this part of the animation
+
+ // map the path [0, BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y] to [0,1]
+ val fraction = ty / BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y
+ target.alpha = 1 - fraction / 2
+ }
+ ty >= totalTranslationY -> {
+ // this is the second leg of the animation. the handle should be completely
+ // hidden and the bubble should start animating in.
+ // it's possible that we're re-entering this leg because this is a spring
+ // animation, so only set the alpha and scale for the bubble if we didn't
+ // already fully animate in.
+ target.alpha = 0f
+ bubbleView.translationY = ty + BUBBLE_ANIMATION_TRANSLATION_Y_OFFSET
+ if (bubbleView.alpha != 1f) {
+ // map the path
+ // [BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y, totalTranslationY]
+ // to [0, 1]
+ val fraction =
+ (ty - BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y) /
+ BUBBLE_ANIMATION_BUBBLE_TRANSLATION_Y
+ bubbleView.alpha = fraction
+ bubbleView.scaleY =
+ BUBBLE_ANIMATION_INITIAL_SCALE_Y +
+ (1 - BUBBLE_ANIMATION_INITIAL_SCALE_Y) * fraction
+ }
+ }
+ else -> {
+ // we're past the target animated value, set the alpha and scale for the bubble
+ // so that it's fully visible and no longer changing, but keep moving it along
+ // the animation path
+ bubbleView.alpha = 1f
+ bubbleView.scaleY = 1f
+ bubbleView.translationY = ty + BUBBLE_ANIMATION_TRANSLATION_Y_OFFSET
+ }
+ }
}
- stashedHandleAnimation.start()
+ animator.start()
}
/**
* Returns a lambda that starts the animation that hides the new bubble.
*
- * Similarly to the show animation, this is divided into 2 parts. We first animate the bubble
- * out, and then animate the stash handle in. At the end of the animation we reset the values of
- * the bubble.
+ * Similarly to the show animation, this is visually divided into 2 parts. We first animate the
+ * bubble out, and then animate the stash handle in. At the end of the animation we reset the
+ * values of the bubble.
+ *
+ * This is a spring animation that goes along the same path of the show animation in the
+ * opposite order, and is split into 3 parts:
+ * 1. In the first part the bubble animates out.
+ * 1. In the second part the bubble is fully hidden and the handle animates in.
+ * 1. The third part is the overshoot. The handle is made fully visible.
*/
private fun buildHideAnimation(bubbleView: BubbleView): () -> Unit = {
- val stashAnimation = bubbleStashController.buildShowHandleAnimationForNewBubble()
- val alphaAnimator =
- ObjectAnimator.ofFloat(bubbleView, View.ALPHA, BUBBLE_ANIMATION_INITIAL_ALPHA)
- val translationYAnimator =
- ObjectAnimator.ofFloat(
- bubbleView,
- View.TRANSLATION_Y,
- BUBBLE_ANIMATION_INITIAL_TRANSLATION_Y
- )
- val scaleYAnimator =
- ObjectAnimator.ofFloat(bubbleView, View.SCALE_Y, BUBBLE_ANIMATION_INITIAL_SCALE_Y)
- val hideBubbleAnimation = AnimatorSet()
- hideBubbleAnimation.playTogether(alphaAnimator, translationYAnimator, scaleYAnimator)
- hideBubbleAnimation.duration = HIDE_BUBBLE_ANIMATION_DURATION_MS
- hideBubbleAnimation.doOnEnd {
- // the bubble is now hidden, start the stash handle animation and reset bubble
- // properties
- bubbleStashController.setStashAlpha(
- BubbleStashController.NEW_BUBBLE_HIDE_HANDLE_ANIMATION_ALPHA
- )
+ // this is the total distance that both the stashed handle and the bubble will be traveling
+ val totalTranslationY =
+ BUBBLE_ANIMATION_BUBBLE_TRANSLATION_Y + BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y
+ val animator = bubbleStashController.stashedHandlePhysicsAnimator
+ animator.setDefaultSpringConfig(springConfig)
+ animator.spring(DynamicAnimation.TRANSLATION_Y, 0f)
+ animator.addUpdateListener { target, values ->
+ val ty = values[DynamicAnimation.TRANSLATION_Y]?.value ?: return@addUpdateListener
+ when {
+ ty <= BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y -> {
+ // this is the first leg of the animation. only animate the bubble. the handle
+ // is hidden during this part
+ bubbleView.translationY = ty + BUBBLE_ANIMATION_TRANSLATION_Y_OFFSET
+ // map the path
+ // [totalTranslationY, BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y]
+ // to [0, 1]
+ val fraction = (totalTranslationY - ty) / BUBBLE_ANIMATION_BUBBLE_TRANSLATION_Y
+ bubbleView.alpha = 1 - fraction / 2
+ bubbleView.scaleY = 1 - (1 - BUBBLE_ANIMATION_INITIAL_SCALE_Y) * fraction
+ }
+ ty <= 0 -> {
+ // this is the second part of the animation. make the bubble invisible and
+ // start fading in the handle, but don't update the alpha if it's already fully
+ // visible
+ bubbleView.alpha = 0f
+ if (target.alpha != 1f) {
+ // map the path [BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y, 0] to [0, 1]
+ val fraction =
+ (BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y - ty) /
+ BUBBLE_ANIMATION_STASH_HANDLE_TRANSLATION_Y
+ target.alpha = fraction
+ }
+ }
+ else -> {
+ // we reached the target value. set the alpha of the handle to 1
+ target.alpha = 1f
+ }
+ }
+ }
+ animator.addEndListener { _, _, _, _, _, _, _ ->
bubbleView.alpha = 0f
- stashAnimation.start()
bubbleView.translationY = 0f
bubbleView.scaleY = 1f
if (bubbleStashController.isStashed) {
@@ -172,7 +238,7 @@
}
bubbleBarView.onAnimatingBubbleCompleted()
}
- hideBubbleAnimation.start()
+ animator.start()
}
}
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
index b478efa..d90e048 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
@@ -16,19 +16,15 @@
package com.android.launcher3.taskbar.bubbles.animation
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.AnimatorSet
import android.content.Context
import android.graphics.Color
import android.graphics.Path
import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
+import android.view.View
import android.view.View.INVISIBLE
import android.view.View.VISIBLE
import android.widget.FrameLayout
-import androidx.core.animation.AnimatorTestRule
-import androidx.core.animation.doOnEnd
import androidx.core.graphics.drawable.toBitmap
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.test.core.app.ApplicationProvider
@@ -42,16 +38,13 @@
import com.android.launcher3.taskbar.bubbles.BubbleStashController
import com.android.launcher3.taskbar.bubbles.BubbleView
import com.android.wm.shell.common.bubbles.BubbleInfo
+import com.android.wm.shell.shared.animation.PhysicsAnimator
import com.android.wm.shell.shared.animation.PhysicsAnimatorTestUtils
import com.google.common.truth.Truth.assertThat
-import java.util.concurrent.Semaphore
-import java.util.concurrent.TimeUnit
import org.junit.Before
-import org.junit.ClassRule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.mock
-import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
@SmallTest
@@ -61,10 +54,6 @@
private val context = ApplicationProvider.getApplicationContext<Context>()
private val animatorScheduler = TestBubbleBarViewAnimatorScheduler()
- companion object {
- @JvmField @ClassRule val animatorTestRule = AnimatorTestRule()
- }
-
@Before
fun setUp() {
PhysicsAnimatorTestUtils.prepareForTest()
@@ -99,14 +88,9 @@
val bubbleStashController = mock<BubbleStashController>()
whenever(bubbleStashController.isStashed).thenReturn(true)
- val semaphore = Semaphore(0)
- val hideHandleAnimator = AnimatorSet()
- hideHandleAnimator.duration = 0
- whenever(bubbleStashController.buildHideHandleAnimationForNewBubble())
- .thenReturn(hideHandleAnimator)
- // add an end listener to the hide handle animation. we add it when the animation starts
- // to ensure that it gets called after all other end listeners.
- hideHandleAnimator.doOnStart { hideHandleAnimator.doOnEnd { semaphore.release() } }
+ val handle = View(context)
+ val handleAnimator = PhysicsAnimator.getInstance(handle)
+ whenever(bubbleStashController.stashedHandlePhysicsAnimator).thenReturn(handleAnimator)
val animator =
BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
@@ -115,44 +99,26 @@
animator.animateBubbleInForStashed(bubble)
}
- // wait for the stash handle animation to complete
- assertThat(semaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue()
- // stash handle animation finished. verify that the stash handle is now hidden
- verify(bubbleStashController).setStashAlpha(0f)
-
+ // let the animation start and wait for it to complete
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+ PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
+ assertThat(handle.alpha).isEqualTo(0)
+ assertThat(handle.translationY).isEqualTo(-70)
assertThat(overflowView.visibility).isEqualTo(INVISIBLE)
assertThat(bubbleBarView.visibility).isEqualTo(VISIBLE)
assertThat(bubbleView.visibility).isEqualTo(VISIBLE)
-
- // wait for the show bubble animation to complete
- PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(
- DynamicAnimation.ALPHA,
- DynamicAnimation.TRANSLATION_Y,
- DynamicAnimation.SCALE_Y,
- )
-
assertThat(bubbleView.alpha).isEqualTo(1)
- assertThat(bubbleView.translationY).isEqualTo(-50)
+ assertThat(bubbleView.translationY).isEqualTo(-20)
assertThat(bubbleView.scaleY).isEqualTo(1)
- val showHandleAnimator = AnimatorSet()
- showHandleAnimator.duration = 0
- whenever(bubbleStashController.buildShowHandleAnimationForNewBubble())
- .thenReturn(showHandleAnimator)
- var showHandleAnimationStarted = false
- showHandleAnimator.doOnStart { showHandleAnimationStarted = true }
-
// execute the hide bubble animation
assertThat(animatorScheduler.delayedBlock).isNotNull()
InstrumentationRegistry.getInstrumentation().runOnMainSync(animatorScheduler.delayedBlock!!)
- // finish the hide bubble animation
- InstrumentationRegistry.getInstrumentation().runOnMainSync {
- animatorTestRule.advanceTimeBy(250)
- }
- assertThat(showHandleAnimationStarted).isTrue()
+ // let the animation start and wait for it to complete
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+ PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(DynamicAnimation.TRANSLATION_Y)
assertThat(bubbleView.alpha).isEqualTo(1)
assertThat(bubbleView.visibility).isEqualTo(VISIBLE)
@@ -160,16 +126,8 @@
assertThat(bubbleBarView.alpha).isEqualTo(0)
assertThat(overflowView.alpha).isEqualTo(1)
assertThat(overflowView.visibility).isEqualTo(VISIBLE)
- }
-
- private fun AnimatorSet.doOnStart(onStart: () -> Unit) {
- addListener(
- object : AnimatorListenerAdapter() {
- override fun onAnimationStart(animator: Animator) {
- onStart()
- }
- }
- )
+ assertThat(handle.alpha).isEqualTo(1)
+ assertThat(handle.translationY).isEqualTo(0)
}
private class TestBubbleBarViewAnimatorScheduler : BubbleBarViewAnimator.Scheduler {