diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt index 915e7f63ffb22..e5933e6a9aea8 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt @@ -16,7 +16,6 @@ package com.android.systemui.shared.animation import android.graphics.Point -import android.util.MathUtils.lerp import android.view.Surface import android.view.View import android.view.WindowManager @@ -27,7 +26,7 @@ import java.lang.ref.WeakReference * Creates an animation where all registered views are moved into their final location * by moving from the center of the screen to the sides */ -class UnfoldMoveFromCenterAnimator( +class UnfoldMoveFromCenterAnimator @JvmOverloads constructor( private val windowManager: WindowManager, /** * Allows to set custom translation applier @@ -36,14 +35,13 @@ class UnfoldMoveFromCenterAnimator( * using custom methods instead of [View.setTranslationX] or * [View.setTranslationY] */ - var translationApplier: TranslationApplier = object : TranslationApplier {} + private val translationApplier: TranslationApplier = object : TranslationApplier {}, ) : UnfoldTransitionProgressProvider.TransitionProgressListener { private val screenSize = Point() private var isVerticalFold = false private val animatedViews: MutableList = arrayListOf() - private val tmpArray = IntArray(2) /** * Updates display properties in order to calculate the initial position for the views @@ -82,45 +80,52 @@ class UnfoldMoveFromCenterAnimator( it.view.get()?.let { view -> translationApplier.apply( view = view, - x = lerp(it.startTranslationX, it.finishTranslationX, progress), - y = lerp(it.startTranslationY, it.finishTranslationY, progress) + x = it.startTranslationX * (1 - progress), + y = it.startTranslationY * (1 - progress) ) } } } private fun createAnimatedView(view: View): AnimatedView { - val viewLocation = tmpArray - view.getLocationOnScreen(viewLocation) + val viewCenter = getViewCenter(view) + val viewCenterX = viewCenter.x + val viewCenterY = viewCenter.y - val viewX = viewLocation[0].toFloat() - val viewY = viewLocation[1].toFloat() - - val viewCenterX = viewX + view.width / 2 - val viewCenterY = viewY + view.height / 2 - - val translationXDiff: Float - val translationYDiff: Float + val translationX: Float + val translationY: Float if (isVerticalFold) { val distanceFromScreenCenterToViewCenter = screenSize.x / 2 - viewCenterX - translationXDiff = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE - translationYDiff = 0f + translationX = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE + translationY = 0f } else { val distanceFromScreenCenterToViewCenter = screenSize.y / 2 - viewCenterY - translationXDiff = 0f - translationYDiff = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE + translationX = 0f + translationY = distanceFromScreenCenterToViewCenter * TRANSLATION_PERCENTAGE } return AnimatedView( view = WeakReference(view), - startTranslationX = view.translationX + translationXDiff, - startTranslationY = view.translationY + translationYDiff, - finishTranslationX = view.translationX, - finishTranslationY = view.translationY + startTranslationX = translationX, + startTranslationY = translationY ) } + private fun getViewCenter(view: View): Point { + val viewLocation = IntArray(2) + view.getLocationOnScreen(viewLocation) + + val viewX = viewLocation[0] + val viewY = viewLocation[1] + + val outPoint = Point() + outPoint.x = viewX + view.width / 2 + outPoint.y = viewY + view.height / 2 + + return outPoint + } + /** * Interface that allows to use custom logic to apply translation to view */ @@ -137,9 +142,7 @@ class UnfoldMoveFromCenterAnimator( private class AnimatedView( val view: WeakReference, val startTranslationX: Float, - val startTranslationY: Float, - val finishTranslationX: Float, - val finishTranslationY: Float + val startTranslationY: Float ) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt index a9c6a53533501..ebc6f2aa6e9a8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt @@ -56,45 +56,71 @@ class UnfoldMoveFromCenterAnimatorTest : SysuiTestCase() { @Test fun testRegisterViewOnTheLeftOfVerticalFold_halfProgress_viewTranslatedToTheRight() { givenScreen(width = 100, height = 100, rotation = ROTATION_0) - val view = createView(x = 20) + val view = createView(x = 20, width = 10, height = 10) animator.registerViewForAnimation(view) animator.onTransitionStarted() animator.onTransitionProgress(0.5f) // Positive translationX -> translated to the right - assertThat(view.translationX).isWithin(0.1f).of(3.75f) + // 10x10 view center is 25px from the center, + // When progress is 0.5 it should be translated at: + // 25 * 0.3 * (1 - 0.5) = 3.75px + assertThat(view.translationX).isWithin(0.01f).of(3.75f) } @Test fun testRegisterViewOnTheLeftOfVerticalFold_zeroProgress_viewTranslatedToTheRight() { givenScreen(width = 100, height = 100, rotation = ROTATION_0) - val view = createView(x = 20) + val view = createView(x = 20, width = 10, height = 10) animator.registerViewForAnimation(view) animator.onTransitionStarted() animator.onTransitionProgress(0f) // Positive translationX -> translated to the right - assertThat(view.translationX).isWithin(0.1f).of(7.5f) + // 10x10 view center is 25px from the center, + // When progress is 0 it should be translated at: + // 25 * 0.3 * (1 - 0) = 7.5px + assertThat(view.translationX).isWithin(0.01f).of(7.5f) } @Test fun testRegisterViewOnTheLeftOfVerticalFold_fullProgress_viewTranslatedToTheOriginalPosition() { givenScreen(width = 100, height = 100, rotation = ROTATION_0) - val view = createView(x = 20) + val view = createView(x = 20, width = 10, height = 10) animator.registerViewForAnimation(view) animator.onTransitionStarted() animator.onTransitionProgress(1f) + // Positive translationX -> translated to the right + // 10x10 view center is 25px from the center, + // When progress is 1 it should be translated at: + // 25 * 0.3 * 0 = 0px assertThat(view.translationX).isEqualTo(0f) } + @Test + fun testViewOnTheLeftOfVerticalFoldWithTranslation_halfProgress_viewTranslatedToTheRight() { + givenScreen(width = 100, height = 100, rotation = ROTATION_0) + val view = createView(x = 20, width = 10, height = 10, translationX = 100f) + animator.registerViewForAnimation(view) + animator.onTransitionStarted() + + animator.onTransitionProgress(0.5f) + + // Positive translationX -> translated to the right, original translation is ignored + // 10x10 view center is 25px from the center, + // When progress is 0.5 it should be translated at: + // 25 * 0.3 * (1 - 0.5) = 3.75px + assertThat(view.translationX).isWithin(0.01f).of(3.75f) + } + @Test fun testRegisterViewAndUnregister_halfProgress_viewIsNotUpdated() { givenScreen(width = 100, height = 100, rotation = ROTATION_0) - val view = createView(x = 20) + val view = createView(x = 20, width = 10, height = 10) animator.registerViewForAnimation(view) animator.onTransitionStarted() animator.clearRegisteredViews() @@ -107,7 +133,7 @@ class UnfoldMoveFromCenterAnimatorTest : SysuiTestCase() { @Test fun testRegisterViewUpdateProgressAndUnregister_halfProgress_viewIsNotUpdated() { givenScreen(width = 100, height = 100, rotation = ROTATION_0) - val view = createView(x = 20) + val view = createView(x = 20, width = 10, height = 10) animator.registerViewForAnimation(view) animator.onTransitionStarted() animator.onTransitionProgress(0.2f) @@ -121,14 +147,14 @@ class UnfoldMoveFromCenterAnimatorTest : SysuiTestCase() { @Test fun testRegisterViewOnTheTopOfHorizontalFold_halfProgress_viewTranslatedToTheBottom() { givenScreen(width = 100, height = 100, rotation = ROTATION_90) - val view = createView(y = 20) + val view = createView(y = 20, width = 10, height = 10) animator.registerViewForAnimation(view) animator.onTransitionStarted() animator.onTransitionProgress(0.5f) // Positive translationY -> translated to the bottom - assertThat(view.translationY).isWithin(0.1f).of(3.75f) + assertThat(view.translationY).isWithin(0.01f).of(3.75f) } private fun createView( @@ -156,9 +182,11 @@ class UnfoldMoveFromCenterAnimatorTest : SysuiTestCase() { } } - private fun givenScreen(width: Int = 100, - height: Int = 100, - rotation: Int = ROTATION_0) { + private fun givenScreen( + width: Int = 100, + height: Int = 100, + rotation: Int = ROTATION_0 + ) { val display = mock(Display::class.java) whenever(display.getSize(any())).thenAnswer { val size = (it.arguments[0] as Point)