[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:
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user