[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
This commit is contained in:
Nick Chameyev
2021-09-08 16:39:15 +01:00
parent 5c9e2243a0
commit f9f94bb4a2
2 changed files with 70 additions and 39 deletions

View File

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

View File

@@ -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)