Reverse dream overlay animations on exiting low light
This CL reuses the callback added in ag/20953423 to reverse the direction the overlay text animates in upon exiting low light to match the spec, instead of disabling the animation altogether. Bug: 260638159 Test: atest DreamOverlayAnimationsControllerTest DreamOverlayContainerViewControllerTest Change-Id: Ib9925bf6424753daed6334c606a353874e8a1337
This commit is contained in:
@@ -43,7 +43,6 @@ import com.android.systemui.util.concurrency.DelayableExecutor
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -131,9 +130,17 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
/** Starts the dream content and dream overlay entry animations. */
|
||||
/**
|
||||
* Starts the dream content and dream overlay entry animations.
|
||||
*
|
||||
* @param downwards if true, the entry animation translations downwards into position rather
|
||||
* than upwards.
|
||||
*/
|
||||
@JvmOverloads
|
||||
fun startEntryAnimations(animatorBuilder: () -> AnimatorSet = { AnimatorSet() }) {
|
||||
fun startEntryAnimations(
|
||||
downwards: Boolean,
|
||||
animatorBuilder: () -> AnimatorSet = { AnimatorSet() }
|
||||
) {
|
||||
cancelAnimations()
|
||||
|
||||
mAnimator =
|
||||
@@ -153,7 +160,7 @@ constructor(
|
||||
interpolator = Interpolators.LINEAR
|
||||
),
|
||||
translationYAnimator(
|
||||
from = mDreamInTranslationYDistance.toFloat(),
|
||||
from = mDreamInTranslationYDistance.toFloat() * (if (downwards) -1 else 1),
|
||||
to = 0f,
|
||||
durationMs = mDreamInTranslationYDurationMs,
|
||||
interpolator = Interpolators.EMPHASIZED_DECELERATE
|
||||
@@ -182,19 +189,6 @@ constructor(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the dream content and dream overlay animations, if they're currently running.
|
||||
*
|
||||
* @see [AnimatorSet.end]
|
||||
*/
|
||||
fun endAnimations() {
|
||||
mAnimator =
|
||||
mAnimator?.let {
|
||||
it.end()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun blurAnimator(
|
||||
view: View,
|
||||
fromBlurRadius: Float,
|
||||
|
||||
@@ -143,19 +143,18 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
};
|
||||
|
||||
/**
|
||||
* If true, overlay entry animations should be skipped once.
|
||||
*
|
||||
* This is turned on when exiting low light and should be turned off once the entry animations
|
||||
* are skipped once.
|
||||
* If {@code true}, the dream has just transitioned from the low light dream back to the user
|
||||
* dream and we should play an entry animation where the overlay slides in downwards from the
|
||||
* top instead of the typicla slide in upwards from the bottom.
|
||||
*/
|
||||
private boolean mSkipEntryAnimations;
|
||||
private boolean mExitingLowLight;
|
||||
|
||||
private final DreamOverlayStateController.Callback
|
||||
mDreamOverlayStateCallback =
|
||||
new DreamOverlayStateController.Callback() {
|
||||
@Override
|
||||
public void onExitLowLight() {
|
||||
mSkipEntryAnimations = true;
|
||||
mExitingLowLight = true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -219,14 +218,10 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
||||
|
||||
// Start dream entry animations. Skip animations for low light clock.
|
||||
if (!mStateController.isLowLightActive()) {
|
||||
mDreamOverlayAnimationsController.startEntryAnimations();
|
||||
|
||||
if (mSkipEntryAnimations) {
|
||||
// If we're transitioning from the low light dream back to the user dream, skip the
|
||||
// overlay animations and show immediately.
|
||||
mDreamOverlayAnimationsController.endAnimations();
|
||||
mSkipEntryAnimations = false;
|
||||
}
|
||||
// If this is transitioning from the low light dream to the user dream, the overlay
|
||||
// should translate in downwards instead of upwards.
|
||||
mDreamOverlayAnimationsController.startEntryAnimations(mExitingLowLight);
|
||||
mExitingLowLight = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.android.systemui.dreams
|
||||
|
||||
import android.animation.AnimatorSet
|
||||
import android.animation.ValueAnimator
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.view.View
|
||||
import androidx.test.filters.SmallTest
|
||||
@@ -14,9 +15,11 @@ import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.anyLong
|
||||
import org.mockito.Mockito.eq
|
||||
@@ -87,7 +90,7 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
|
||||
fun testWakeUpAfterStartWillCancel() {
|
||||
val mockStartAnimator: AnimatorSet = mock()
|
||||
|
||||
controller.startEntryAnimations(animatorBuilder = { mockStartAnimator })
|
||||
controller.startEntryAnimations(false, animatorBuilder = { mockStartAnimator })
|
||||
|
||||
verify(mockStartAnimator, never()).cancel()
|
||||
|
||||
@@ -100,4 +103,50 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
|
||||
// animator.
|
||||
verify(mockStartAnimator, times(1)).cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEntryAnimations_translatesUpwards() {
|
||||
val mockStartAnimator: AnimatorSet = mock()
|
||||
|
||||
controller.startEntryAnimations(
|
||||
/* downwards= */ false,
|
||||
animatorBuilder = { mockStartAnimator }
|
||||
)
|
||||
|
||||
val animatorCaptor = ArgumentCaptor.forClass(Animator::class.java)
|
||||
verify(mockStartAnimator).playTogether(animatorCaptor.capture())
|
||||
|
||||
// Check if there's a ValueAnimator starting at the expected Y distance.
|
||||
val animators: List<ValueAnimator> = animatorCaptor.allValues as List<ValueAnimator>
|
||||
assertTrue(
|
||||
animators.any {
|
||||
// Call setCurrentFraction so the animated value jumps to the initial value.
|
||||
it.setCurrentFraction(0f)
|
||||
it.animatedValue == DREAM_IN_TRANSLATION_Y_DISTANCE.toFloat()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEntryAnimations_translatesDownwards() {
|
||||
val mockStartAnimator: AnimatorSet = mock()
|
||||
|
||||
controller.startEntryAnimations(
|
||||
/* downwards= */ true,
|
||||
animatorBuilder = { mockStartAnimator }
|
||||
)
|
||||
|
||||
val animatorCaptor = ArgumentCaptor.forClass(Animator::class.java)
|
||||
verify(mockStartAnimator).playTogether(animatorCaptor.capture())
|
||||
|
||||
// Check if there's a ValueAnimator starting at the expected Y distance.
|
||||
val animators: List<ValueAnimator> = animatorCaptor.allValues as List<ValueAnimator>
|
||||
assertTrue(
|
||||
animators.any {
|
||||
// Call setCurrentFraction so the animated value jumps to the initial value.
|
||||
it.setCurrentFraction(0f)
|
||||
it.animatedValue == -DREAM_IN_TRANSLATION_Y_DISTANCE.toFloat()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.dreams;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyFloat;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -200,7 +201,7 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
|
||||
|
||||
mController.onViewAttached();
|
||||
|
||||
verify(mAnimationsController).startEntryAnimations();
|
||||
verify(mAnimationsController).startEntryAnimations(false);
|
||||
verify(mAnimationsController, never()).cancelAnimations();
|
||||
}
|
||||
|
||||
@@ -210,11 +211,11 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
|
||||
|
||||
mController.onViewAttached();
|
||||
|
||||
verify(mAnimationsController, never()).startEntryAnimations();
|
||||
verify(mAnimationsController, never()).startEntryAnimations(anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSkipEntryAnimationsWhenExitingLowLight() {
|
||||
public void testDownwardEntryAnimationsWhenExitingLowLight() {
|
||||
ArgumentCaptor<DreamOverlayStateController.Callback> callbackCaptor =
|
||||
ArgumentCaptor.forClass(DreamOverlayStateController.Callback.class);
|
||||
when(mStateController.isLowLightActive()).thenReturn(false);
|
||||
@@ -230,8 +231,7 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
|
||||
mController.onViewAttached();
|
||||
|
||||
// Entry animations should be started then immediately ended to skip to the end.
|
||||
verify(mAnimationsController).startEntryAnimations();
|
||||
verify(mAnimationsController).endAnimations();
|
||||
verify(mAnimationsController).startEntryAnimations(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user