Merge "Animate the stash handle for new bubbles" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
98bbc2b46d
@@ -96,6 +96,8 @@ public class BubbleBarView extends FrameLayout {
|
||||
|
||||
private final BubbleBarBackground mBubbleBarBackground;
|
||||
|
||||
private boolean mIsAnimatingNewBubble = false;
|
||||
|
||||
/**
|
||||
* The current bounds of all the bubble bar. Note that these bounds may not account for
|
||||
* translation. The bounds should be retrieved using {@link #getBubbleBarBounds()} which
|
||||
@@ -457,6 +459,7 @@ public class BubbleBarView extends FrameLayout {
|
||||
|
||||
/** Prepares for animating a bubble while being stashed. */
|
||||
public void prepareForAnimatingBubbleWhileStashed(String bubbleKey) {
|
||||
mIsAnimatingNewBubble = true;
|
||||
// we're about to animate the new bubble in. the new bubble has already been added to this
|
||||
// view, but we're currently stashed, so before we can start the animation we need make
|
||||
// everything else in the bubble bar invisible, except for the bubble that's being animated.
|
||||
@@ -477,6 +480,9 @@ public class BubbleBarView extends FrameLayout {
|
||||
|
||||
/** Resets the state after the bubble animation completed. */
|
||||
public void onAnimatingBubbleCompleted() {
|
||||
mIsAnimatingNewBubble = false;
|
||||
// setting the background triggers relayout so no need to explicitly invalidate after the
|
||||
// animation
|
||||
setBackground(mBubbleBarBackground);
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
final BubbleView view = (BubbleView) getChildAt(i);
|
||||
@@ -521,6 +527,12 @@ public class BubbleBarView extends FrameLayout {
|
||||
* on the expanded state.
|
||||
*/
|
||||
private void updateChildrenRenderNodeProperties() {
|
||||
if (mIsAnimatingNewBubble) {
|
||||
// don't update bubbles if a new bubble animation is playing.
|
||||
// the bubble bar will redraw itself via onLayout after the animation.
|
||||
return;
|
||||
}
|
||||
|
||||
final float widthState = (float) mWidthAnimator.getAnimatedValue();
|
||||
final float currentWidth = getWidth();
|
||||
final float expandedWidth = expandedWidth();
|
||||
|
||||
@@ -51,6 +51,15 @@ public class BubbleStashController {
|
||||
*/
|
||||
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.
|
||||
@@ -64,6 +73,7 @@ public class BubbleStashController {
|
||||
private AnimatedFloat mIconScaleForStash;
|
||||
private AnimatedFloat mIconTranslationYForStash;
|
||||
private MultiPropertyFactory.MultiProperty mBubbleStashedHandleAlpha;
|
||||
private AnimatedFloat mBubbleStashedHandleTranslationY;
|
||||
|
||||
private boolean mRequestedStashState;
|
||||
private boolean mRequestedExpandedState;
|
||||
@@ -95,6 +105,7 @@ public class BubbleStashController {
|
||||
|
||||
mBubbleStashedHandleAlpha = mHandleViewController.getStashedHandleAlpha().get(
|
||||
StashedHandleViewController.ALPHA_INDEX_STASHED);
|
||||
mBubbleStashedHandleTranslationY = mHandleViewController.getStashedHandleTranslationY();
|
||||
|
||||
mStashedHeight = mHandleViewController.getStashedHeight();
|
||||
mUnstashedHeight = mHandleViewController.getUnstashedHeight();
|
||||
@@ -362,4 +373,35 @@ public class BubbleStashController {
|
||||
public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
|
||||
mHandleViewController.setBubbleBarLocation(bubbleBarLocation);
|
||||
}
|
||||
|
||||
/** Returns the x position of the center of the stashed handle. */
|
||||
public float getStashedHandleCenterX() {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
+27
-5
@@ -29,6 +29,7 @@ import android.view.View;
|
||||
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;
|
||||
@@ -47,7 +48,7 @@ public class BubbleStashedHandleViewController {
|
||||
|
||||
private final TaskbarActivityContext mActivity;
|
||||
private final StashedHandleView mStashedHandleView;
|
||||
private final MultiValueAlpha mTaskbarStashedHandleAlpha;
|
||||
private final MultiValueAlpha mStashedHandleAlpha;
|
||||
|
||||
// Initialized in init.
|
||||
private BubbleBarViewController mBarViewController;
|
||||
@@ -58,6 +59,12 @@ public class BubbleStashedHandleViewController {
|
||||
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();
|
||||
|
||||
@@ -75,7 +82,7 @@ public class BubbleStashedHandleViewController {
|
||||
StashedHandleView stashedHandleView) {
|
||||
mActivity = activity;
|
||||
mStashedHandleView = stashedHandleView;
|
||||
mTaskbarStashedHandleAlpha = new MultiValueAlpha(mStashedHandleView, 1);
|
||||
mStashedHandleAlpha = new MultiValueAlpha(mStashedHandleView, 1);
|
||||
}
|
||||
|
||||
public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
|
||||
@@ -93,7 +100,7 @@ public class BubbleStashedHandleViewController {
|
||||
R.dimen.transient_taskbar_bottom_margin);
|
||||
mStashedHandleView.getLayoutParams().height = mBarSize + bottomMargin;
|
||||
|
||||
mTaskbarStashedHandleAlpha.get(0).setValue(0);
|
||||
mStashedHandleAlpha.get(0).setValue(0);
|
||||
|
||||
mStashedTaskbarHeight = resources.getDimensionPixelSize(
|
||||
R.dimen.bubblebar_stashed_size);
|
||||
@@ -231,18 +238,33 @@ public class BubbleStashedHandleViewController {
|
||||
}
|
||||
}
|
||||
|
||||
/** 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) {
|
||||
mStashedHandleView.setTranslationY(transY);
|
||||
mSwipeUpTranslationY = transY;
|
||||
updateTranslationY();
|
||||
}
|
||||
|
||||
private void updateTranslationY() {
|
||||
mStashedHandleView.setTranslationY(mStashedHandleTranslationY.value + mSwipeUpTranslationY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by {@link BubbleStashController} to animate the handle when stashing or un stashing.
|
||||
*/
|
||||
public MultiPropertyFactory<View> getStashedHandleAlpha() {
|
||||
return mTaskbarStashedHandleAlpha;
|
||||
return mStashedHandleAlpha;
|
||||
}
|
||||
|
||||
/** Returns the x position of the center of the stashed handle. */
|
||||
public float getStashedHandleCenterX() {
|
||||
return mStashedHandleBounds.exactCenterX();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+89
-22
@@ -18,12 +18,16 @@ package com.android.launcher3.taskbar.bubbles.animation
|
||||
|
||||
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. */
|
||||
@@ -39,7 +43,17 @@ constructor(
|
||||
/** 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_TRANSLATION_Y = -50f
|
||||
const val BUBBLE_ANIMATION_FINAL_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
|
||||
/** 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
|
||||
}
|
||||
|
||||
/** An interface for scheduling jobs. */
|
||||
@@ -78,41 +92,94 @@ constructor(
|
||||
// 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 hideAnimation = buildHideAnimation(animator)
|
||||
val hideAnimation = buildHideAnimation(bubbleView)
|
||||
scheduler.post(showAnimation)
|
||||
scheduler.postDelayed(FLYOUT_DELAY_MS, hideAnimation)
|
||||
}
|
||||
|
||||
/** Returns a lambda that starts the animation that shows the new bubble. */
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
private fun buildShowAnimation(
|
||||
bubbleView: BubbleView,
|
||||
key: String,
|
||||
animator: PhysicsAnimator<BubbleView>
|
||||
bubbleAnimator: PhysicsAnimator<BubbleView>
|
||||
): () -> Unit = {
|
||||
// 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)
|
||||
animator.setDefaultSpringConfig(springConfig)
|
||||
animator
|
||||
bubbleAnimator.setDefaultSpringConfig(springConfig)
|
||||
bubbleAnimator
|
||||
.spring(DynamicAnimation.ALPHA, 1f)
|
||||
.spring(DynamicAnimation.TRANSLATION_Y, BUBBLE_ANIMATION_TRANSLATION_Y)
|
||||
.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
|
||||
animator.start()
|
||||
// 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)
|
||||
}
|
||||
stashedHandleAnimation.start()
|
||||
}
|
||||
|
||||
/** Returns a lambda that starts the animation that hides the new bubble. */
|
||||
private fun buildHideAnimation(animator: PhysicsAnimator<BubbleView>): () -> Unit = {
|
||||
animator.setDefaultSpringConfig(springConfig)
|
||||
animator
|
||||
.spring(DynamicAnimation.ALPHA, 0f)
|
||||
.spring(DynamicAnimation.TRANSLATION_Y, 0f)
|
||||
.addEndListener { _, _, _, canceled, _, _, allRelevantPropertyAnimsEnded ->
|
||||
if (!canceled && allRelevantPropertyAnimsEnded) {
|
||||
if (bubbleStashController.isStashed) {
|
||||
bubbleBarView.alpha = 0f
|
||||
}
|
||||
bubbleBarView.onAnimatingBubbleCompleted()
|
||||
}
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
)
|
||||
bubbleView.alpha = 0f
|
||||
stashAnimation.start()
|
||||
bubbleView.translationY = 0f
|
||||
bubbleView.scaleY = 1f
|
||||
if (bubbleStashController.isStashed) {
|
||||
bubbleBarView.alpha = 0f
|
||||
}
|
||||
animator.start()
|
||||
bubbleBarView.onAnimatingBubbleCompleted()
|
||||
}
|
||||
hideBubbleAnimation.start()
|
||||
}
|
||||
}
|
||||
|
||||
/** The X position in screen coordinates of the center of the bubble. */
|
||||
private val BubbleView.centerXOnScreen: Float
|
||||
get() {
|
||||
val screenCoordinates = IntArray(2)
|
||||
getLocationOnScreen(screenCoordinates)
|
||||
return screenCoordinates[0] + width / 2f
|
||||
}
|
||||
|
||||
+54
-7
@@ -16,6 +16,9 @@
|
||||
|
||||
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
|
||||
@@ -24,6 +27,8 @@ import android.view.LayoutInflater
|
||||
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
|
||||
@@ -39,10 +44,14 @@ import com.android.launcher3.taskbar.bubbles.BubbleView
|
||||
import com.android.wm.shell.common.bubbles.BubbleInfo
|
||||
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
|
||||
@@ -52,6 +61,10 @@ class BubbleBarViewAnimatorTest {
|
||||
private val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
private val animatorScheduler = TestBubbleBarViewAnimatorScheduler()
|
||||
|
||||
companion object {
|
||||
@JvmField @ClassRule val animatorTestRule = AnimatorTestRule()
|
||||
}
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
PhysicsAnimatorTestUtils.prepareForTest()
|
||||
@@ -86,6 +99,15 @@ class BubbleBarViewAnimatorTest {
|
||||
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 animator =
|
||||
BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
|
||||
|
||||
@@ -93,29 +115,44 @@ class BubbleBarViewAnimatorTest {
|
||||
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)
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
|
||||
|
||||
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.TRANSLATION_Y,
|
||||
DynamicAnimation.SCALE_Y,
|
||||
)
|
||||
|
||||
assertThat(bubbleView.alpha).isEqualTo(1)
|
||||
assertThat(bubbleView.translationY).isEqualTo(-50)
|
||||
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)
|
||||
}
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().waitForIdleSync()
|
||||
|
||||
PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(
|
||||
DynamicAnimation.ALPHA,
|
||||
DynamicAnimation.TRANSLATION_Y
|
||||
)
|
||||
assertThat(showHandleAnimationStarted).isTrue()
|
||||
|
||||
assertThat(bubbleView.alpha).isEqualTo(1)
|
||||
assertThat(bubbleView.visibility).isEqualTo(VISIBLE)
|
||||
@@ -125,6 +162,16 @@ class BubbleBarViewAnimatorTest {
|
||||
assertThat(overflowView.visibility).isEqualTo(VISIBLE)
|
||||
}
|
||||
|
||||
private fun AnimatorSet.doOnStart(onStart: () -> Unit) {
|
||||
addListener(
|
||||
object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationStart(animator: Animator) {
|
||||
onStart()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private class TestBubbleBarViewAnimatorScheduler : BubbleBarViewAnimator.Scheduler {
|
||||
|
||||
var delayedBlock: (() -> Unit)? = null
|
||||
|
||||
Reference in New Issue
Block a user