Loading packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt +25 −7 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import androidx.dynamicanimation.animation.FloatPropertyCompat import androidx.dynamicanimation.animation.SpringAnimation import androidx.dynamicanimation.animation.SpringForce import com.android.systemui.util.animation.PhysicsAnimator.Companion.getInstance import java.lang.ref.WeakReference import java.util.WeakHashMap import kotlin.math.abs import kotlin.math.max Loading Loading @@ -87,7 +88,9 @@ private var verboseLogging = false * * @param T The type of the object being animated. */ class PhysicsAnimator<T> private constructor (val target: T) { class PhysicsAnimator<T> private constructor (target: T) { /** Weak reference to the animation target. */ val weakTarget = WeakReference(target) /** Data class for representing animation frame updates. */ data class AnimationUpdate(val value: Float, val velocity: Float) Loading Loading @@ -307,6 +310,11 @@ class PhysicsAnimator<T> private constructor (val target: T) { springConfig: SpringConfig, flingMustReachMinOrMax: Boolean = false ): PhysicsAnimator<T> { val target = weakTarget.get() if (target == null) { Log.w(TAG, "Trying to animate a GC-ed target.") return this } val flingConfigCopy = flingConfig.copy() val springConfigCopy = springConfig.copy() val toAtLeast = if (startVelocity < 0) flingConfig.min else flingConfig.max Loading Loading @@ -454,6 +462,11 @@ class PhysicsAnimator<T> private constructor (val target: T) { "this message in a test, call PhysicsAnimatorTestUtils#prepareForTest in " + "your test setup.") } val target = weakTarget.get() if (target == null) { Log.w(TAG, "Trying to animate a GC-ed object.") return } // Functions that will actually start the animations. These are run after we build and add // the InternalListener, since some animations might update/end immediately and we don't Loading Loading @@ -489,7 +502,7 @@ class PhysicsAnimator<T> private constructor (val target: T) { cancel(animatedProperty) // Apply the configuration and start the animation. getFlingAnimation(animatedProperty) getFlingAnimation(animatedProperty, target) .also { flingConfig.applyToAnimation(it) } .start() } Loading @@ -502,7 +515,7 @@ class PhysicsAnimator<T> private constructor (val target: T) { // If there is no corresponding fling config, we're only springing. if (flingConfig == null) { // Apply the configuration and start the animation. val springAnim = getSpringAnimation(animatedProperty) val springAnim = getSpringAnimation(animatedProperty, target) springConfig.applyToAnimation(springAnim) animationStartActions.add(springAnim::start) } else { Loading Loading @@ -558,7 +571,7 @@ class PhysicsAnimator<T> private constructor (val target: T) { } // Apply the configuration and start the spring animation. getSpringAnimation(animatedProperty) getSpringAnimation(animatedProperty, target) .also { springConfig.applyToAnimation(it) } .start() } Loading @@ -570,6 +583,7 @@ class PhysicsAnimator<T> private constructor (val target: T) { // Add an internal listener that will dispatch animation events to the provided listeners. internalListeners.add(InternalListener( target, getAnimatedProperties(), ArrayList(updateListeners), ArrayList(endListeners), Loading @@ -594,7 +608,10 @@ class PhysicsAnimator<T> private constructor (val target: T) { } /** Retrieves a spring animation for the given property, building one if needed. */ private fun getSpringAnimation(property: FloatPropertyCompat<in T>): SpringAnimation { private fun getSpringAnimation( property: FloatPropertyCompat<in T>, target: T ): SpringAnimation { return springAnimations.getOrPut( property, { configureDynamicAnimation(SpringAnimation(target, property), property) Loading @@ -602,7 +619,7 @@ class PhysicsAnimator<T> private constructor (val target: T) { } /** Retrieves a fling animation for the given property, building one if needed. */ private fun getFlingAnimation(property: FloatPropertyCompat<in T>): FlingAnimation { private fun getFlingAnimation(property: FloatPropertyCompat<in T>, target: T): FlingAnimation { return flingAnimations.getOrPut( property, { configureDynamicAnimation(FlingAnimation(target, property), property) Loading Loading @@ -638,6 +655,7 @@ class PhysicsAnimator<T> private constructor (val target: T) { * appropriate value for allEnded to [EndListener.onAnimationEnd]. */ internal inner class InternalListener constructor( private val target: T, private var properties: Set<FloatPropertyCompat<in T>>, private var updateListeners: List<UpdateListener<T>>, private var endListeners: List<EndListener<T>>, Loading packages/SystemUI/tests/src/com/android/systemui/util/animation/PhysicsAnimatorTest.kt +5 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import org.junit.Assert import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Ignore Loading Loading @@ -590,8 +591,10 @@ class PhysicsAnimatorTest : SysuiTestCase() { updatesForProperty.remove(update) } val target = animator.weakTarget.get() assertNotNull(target) // Mark this invocation verified. verify(mockUpdateListener).onAnimationUpdateForProperty(animator.target, updateMap) verify(mockUpdateListener).onAnimationUpdateForProperty(target!!, updateMap) } verifyNoMoreInteractions(mockUpdateListener) Loading Loading
packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt +25 −7 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import androidx.dynamicanimation.animation.FloatPropertyCompat import androidx.dynamicanimation.animation.SpringAnimation import androidx.dynamicanimation.animation.SpringForce import com.android.systemui.util.animation.PhysicsAnimator.Companion.getInstance import java.lang.ref.WeakReference import java.util.WeakHashMap import kotlin.math.abs import kotlin.math.max Loading Loading @@ -87,7 +88,9 @@ private var verboseLogging = false * * @param T The type of the object being animated. */ class PhysicsAnimator<T> private constructor (val target: T) { class PhysicsAnimator<T> private constructor (target: T) { /** Weak reference to the animation target. */ val weakTarget = WeakReference(target) /** Data class for representing animation frame updates. */ data class AnimationUpdate(val value: Float, val velocity: Float) Loading Loading @@ -307,6 +310,11 @@ class PhysicsAnimator<T> private constructor (val target: T) { springConfig: SpringConfig, flingMustReachMinOrMax: Boolean = false ): PhysicsAnimator<T> { val target = weakTarget.get() if (target == null) { Log.w(TAG, "Trying to animate a GC-ed target.") return this } val flingConfigCopy = flingConfig.copy() val springConfigCopy = springConfig.copy() val toAtLeast = if (startVelocity < 0) flingConfig.min else flingConfig.max Loading Loading @@ -454,6 +462,11 @@ class PhysicsAnimator<T> private constructor (val target: T) { "this message in a test, call PhysicsAnimatorTestUtils#prepareForTest in " + "your test setup.") } val target = weakTarget.get() if (target == null) { Log.w(TAG, "Trying to animate a GC-ed object.") return } // Functions that will actually start the animations. These are run after we build and add // the InternalListener, since some animations might update/end immediately and we don't Loading Loading @@ -489,7 +502,7 @@ class PhysicsAnimator<T> private constructor (val target: T) { cancel(animatedProperty) // Apply the configuration and start the animation. getFlingAnimation(animatedProperty) getFlingAnimation(animatedProperty, target) .also { flingConfig.applyToAnimation(it) } .start() } Loading @@ -502,7 +515,7 @@ class PhysicsAnimator<T> private constructor (val target: T) { // If there is no corresponding fling config, we're only springing. if (flingConfig == null) { // Apply the configuration and start the animation. val springAnim = getSpringAnimation(animatedProperty) val springAnim = getSpringAnimation(animatedProperty, target) springConfig.applyToAnimation(springAnim) animationStartActions.add(springAnim::start) } else { Loading Loading @@ -558,7 +571,7 @@ class PhysicsAnimator<T> private constructor (val target: T) { } // Apply the configuration and start the spring animation. getSpringAnimation(animatedProperty) getSpringAnimation(animatedProperty, target) .also { springConfig.applyToAnimation(it) } .start() } Loading @@ -570,6 +583,7 @@ class PhysicsAnimator<T> private constructor (val target: T) { // Add an internal listener that will dispatch animation events to the provided listeners. internalListeners.add(InternalListener( target, getAnimatedProperties(), ArrayList(updateListeners), ArrayList(endListeners), Loading @@ -594,7 +608,10 @@ class PhysicsAnimator<T> private constructor (val target: T) { } /** Retrieves a spring animation for the given property, building one if needed. */ private fun getSpringAnimation(property: FloatPropertyCompat<in T>): SpringAnimation { private fun getSpringAnimation( property: FloatPropertyCompat<in T>, target: T ): SpringAnimation { return springAnimations.getOrPut( property, { configureDynamicAnimation(SpringAnimation(target, property), property) Loading @@ -602,7 +619,7 @@ class PhysicsAnimator<T> private constructor (val target: T) { } /** Retrieves a fling animation for the given property, building one if needed. */ private fun getFlingAnimation(property: FloatPropertyCompat<in T>): FlingAnimation { private fun getFlingAnimation(property: FloatPropertyCompat<in T>, target: T): FlingAnimation { return flingAnimations.getOrPut( property, { configureDynamicAnimation(FlingAnimation(target, property), property) Loading Loading @@ -638,6 +655,7 @@ class PhysicsAnimator<T> private constructor (val target: T) { * appropriate value for allEnded to [EndListener.onAnimationEnd]. */ internal inner class InternalListener constructor( private val target: T, private var properties: Set<FloatPropertyCompat<in T>>, private var updateListeners: List<UpdateListener<T>>, private var endListeners: List<EndListener<T>>, Loading
packages/SystemUI/tests/src/com/android/systemui/util/animation/PhysicsAnimatorTest.kt +5 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import org.junit.Assert import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Ignore Loading Loading @@ -590,8 +591,10 @@ class PhysicsAnimatorTest : SysuiTestCase() { updatesForProperty.remove(update) } val target = animator.weakTarget.get() assertNotNull(target) // Mark this invocation verified. verify(mockUpdateListener).onAnimationUpdateForProperty(animator.target, updateMap) verify(mockUpdateListener).onAnimationUpdateForProperty(target!!, updateMap) } verifyNoMoreInteractions(mockUpdateListener) Loading