Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f9f94bb4 authored by Nick Chameyev's avatar Nick Chameyev
Browse files

[Taskbar icons unfold animation issue] Do not take into account initial translation

Removes taking into account initial translation in
move from center animation. Initially it was done
because in StatusBar items are aligned using translations
but we decided to use different approach there so it is
not necessary anymore.

Now move from center animator can only set translations
from positive/negative value when progress is 0 and sets
it to 0 when progress is 1 (previously it was 'capturing'
the initial translation and animated the translation to
its original value).

Taskbar icons are pre-aligned using translations when
user is on launcher. After several folds/unfolds these
translations were accumulating that led to incorrect
positioning of the icons.

Found one more issue that we didn't clear the animated
views list after finishing the animation in taskbar unfold
animation controller but it didn't affect the animation
itself.

Test: atest com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimatorTest
Test: unfold on launcher and use gesture nav to swipe to an app
Fixes: 199126683
Change-Id: I159313aae50a19bbef8c79f227dcae0d5463872d
parent 5c9e2243
Loading
Loading
Loading
Loading
+30 −27
Original line number Diff line number Diff line
@@ -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<AnimatedView> = 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 viewX = viewLocation[0].toFloat()
        val viewY = viewLocation[1].toFloat()

        val viewCenterX = viewX + view.width / 2
        val viewCenterY = viewY + view.height / 2
        val viewCenter = getViewCenter(view)
        val viewCenterX = viewCenter.x
        val viewCenterY = viewCenter.y

        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<View>,
        val startTranslationX: Float,
        val startTranslationY: Float,
        val finishTranslationX: Float,
        val finishTranslationY: Float
        val startTranslationY: Float
    )
}

+40 −12
Original line number Diff line number Diff line
@@ -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,
    private fun givenScreen(
        width: Int = 100,
        height: Int = 100,
                            rotation: Int = ROTATION_0) {
        rotation: Int = ROTATION_0
    ) {
        val display = mock(Display::class.java)
        whenever(display.getSize(any())).thenAnswer {
            val size = (it.arguments[0] as Point)