Loading packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt +20 −12 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ constructor( } companion object { @JvmField val GUTS_ANIMATION_DURATION = 500L @JvmField val GUTS_ANIMATION_DURATION = 234L } /** A listener when the current dimensions of the player change */ Loading Loading @@ -234,7 +234,8 @@ constructor( currentStartLocation, currentEndLocation, currentTransitionProgress, applyImmediately = false applyImmediately = false, isGutsAnimation = true, ) } Loading @@ -254,7 +255,8 @@ constructor( currentStartLocation, currentEndLocation, currentTransitionProgress, applyImmediately = immediate applyImmediately = immediate, isGutsAnimation = true, ) } Loading Loading @@ -414,7 +416,10 @@ constructor( * it's not available, it will recreate one by measuring, which may be expensive. */ @VisibleForTesting fun obtainViewState(state: MediaHostState?): TransitionViewState? { fun obtainViewState( state: MediaHostState?, isGutsAnimation: Boolean = false ): TransitionViewState? { if (state == null || state.measurementInput == null) { return null } Loading @@ -423,7 +428,7 @@ constructor( val viewState = viewStates[cacheKey] if (viewState != null) { // we already have cached this measurement, let's continue if (state.squishFraction <= 1f) { if (state.squishFraction <= 1f && !isGutsAnimation) { return squishViewState(viewState, state.squishFraction) } return viewState Loading Loading @@ -455,13 +460,14 @@ constructor( // Given that we have a measurement and a view, let's get (guaranteed) viewstates // from the start and end state and interpolate them val startViewState = obtainViewState(startState) as TransitionViewState val startViewState = obtainViewState(startState, isGutsAnimation) as TransitionViewState val endState = state.copy().also { it.expansion = 1.0f } val endViewState = obtainViewState(endState) as TransitionViewState val endViewState = obtainViewState(endState, isGutsAnimation) as TransitionViewState result = layoutController.getInterpolatedState(startViewState, endViewState, state.expansion) } if (state.squishFraction <= 1f) { // Skip the adjustments of squish view state if UMO changes due to guts animation. if (state.squishFraction <= 1f && !isGutsAnimation) { return squishViewState(result, state.squishFraction) } return result Loading Loading @@ -521,7 +527,8 @@ constructor( @MediaLocation startLocation: Int, @MediaLocation endLocation: Int, transitionProgress: Float, applyImmediately: Boolean applyImmediately: Boolean, isGutsAnimation: Boolean = false, ) = traceSection("MediaViewController#setCurrentState") { currentEndLocation = endLocation Loading @@ -537,7 +544,7 @@ constructor( // Obtain the view state that we'd want to be at the end // The view might not be bound yet or has never been measured and in that case will be // reset once the state is fully available var endViewState = obtainViewState(endHostState) ?: return var endViewState = obtainViewState(endHostState, isGutsAnimation) ?: return endViewState = updateViewStateSize(endViewState, endLocation, tmpState2)!! layoutController.setMeasureState(endViewState) Loading @@ -548,7 +555,7 @@ constructor( } val result: TransitionViewState var startViewState = obtainViewState(startHostState) var startViewState = obtainViewState(startHostState, isGutsAnimation) startViewState = updateViewStateSize(startViewState, startLocation, tmpState3) if (!endHostState.visible) { Loading Loading @@ -602,7 +609,8 @@ constructor( applyImmediately, shouldAnimate, animationDuration, animationDelay animationDelay, isGutsAnimation, ) } Loading packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt +109 −36 Original line number Diff line number Diff line Loading @@ -25,6 +25,16 @@ import com.android.app.animation.Interpolators * The fraction after which we start fading in when going from a gone widget to a visible one */ private const val GONE_FADE_FRACTION = 0.8f /** * The fraction after which we start fading in going from a gone widget to a visible one in guts * animation. */ private const val GONE_FADE_GUTS_FRACTION = 0.286f /** * The fraction before which we fade out when going from a visible widget to a gone one in guts * animation. */ private const val VISIBLE_FADE_GUTS_FRACTION = 0.355f /** * The amont we're scaling appearing views Loading @@ -45,6 +55,7 @@ open class TransitionLayoutController { private var animationStartState: TransitionViewState? = null private var state = TransitionViewState() private var animator: ValueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f) private var isGutsAnimation = false private var currentHeight: Int = 0 private var currentWidth: Int = 0 var sizeChangedListener: ((Int, Int) -> Unit)? = null Loading Loading @@ -152,15 +163,6 @@ open class TransitionLayoutController { // this looks quite ugly val nowGone: Boolean if (widgetStart.gone) { // Only fade it in at the very end alphaProgress = MathUtils.map(GONE_FADE_FRACTION, 1.0f, 0.0f, 1.0f, progress) nowGone = progress < GONE_FADE_FRACTION // Scale it just a little, not all the way val endScale = widgetEnd.scale newScale = MathUtils.lerp(GONE_SCALE_AMOUNT * endScale, endScale, progress) // don't clip widthProgress = 1.0f Loading @@ -168,25 +170,52 @@ open class TransitionLayoutController { resultMeasureWidth = widgetEnd.measureWidth resultMeasureHeight = widgetEnd.measureHeight // Let's make sure we're centering the view in the gone view instead of having // the left at 0 resultX = MathUtils.lerp(widgetStart.x - resultMeasureWidth / 2.0f, widgetEnd.x, progress) resultY = MathUtils.lerp(widgetStart.y - resultMeasureHeight / 2.0f, widgetEnd.y, progress) if (isGutsAnimation) { // if animation is open/close guts, fade in starts early. alphaProgress = MathUtils.map( GONE_FADE_GUTS_FRACTION, 1.0f, 0.0f, 1.0f, progress ) nowGone = progress < GONE_FADE_GUTS_FRACTION // Do not change scale of widget. newScale = 1.0f // We do not want any horizontal or vertical movement. resultX = widgetStart.x resultY = widgetStart.y } else { // Fadeout in the very beginning alphaProgress = MathUtils.map(0.0f, 1.0f - GONE_FADE_FRACTION, 0.0f, 1.0f, progress) nowGone = progress > 1.0f - GONE_FADE_FRACTION // Only fade it in at the very end alphaProgress = MathUtils.map( GONE_FADE_FRACTION, 1.0f, 0.0f, 1.0f, progress ) nowGone = progress < GONE_FADE_FRACTION // Scale it just a little, not all the way val startScale = widgetStart.scale newScale = MathUtils.lerp(startScale, startScale * GONE_SCALE_AMOUNT, progress) val endScale = widgetEnd.scale newScale = MathUtils.lerp(GONE_SCALE_AMOUNT * endScale, endScale, progress) // Let's make sure we're centering the view in the gone view instead of // having the left at 0 resultX = MathUtils.lerp( widgetStart.x - resultMeasureWidth / 2.0f, widgetEnd.x, progress ) resultY = MathUtils.lerp( widgetStart.y - resultMeasureHeight / 2.0f, widgetEnd.y, progress ) } } else { // Don't clip widthProgress = 0.0f Loading @@ -194,14 +223,54 @@ open class TransitionLayoutController { resultMeasureWidth = widgetStart.measureWidth resultMeasureHeight = widgetStart.measureHeight // Let's make sure we're centering the view in the gone view instead of having // the left at 0 resultX = MathUtils.lerp(widgetStart.x, // Fadeout in the very beginning if (isGutsAnimation) { alphaProgress = MathUtils.map( 0.0f, VISIBLE_FADE_GUTS_FRACTION, 0.0f, 1.0f, progress ) nowGone = progress > VISIBLE_FADE_GUTS_FRACTION // Do not change scale of widget during open/close guts animation. newScale = 1.0f // We do not want any horizontal or vertical movement. resultX = widgetEnd.x resultY = widgetEnd.y } else { alphaProgress = MathUtils.map( 0.0f, 1.0f - GONE_FADE_FRACTION, 0.0f, 1.0f, progress ) nowGone = progress > 1.0f - GONE_FADE_FRACTION // Scale it just a little, not all the way val startScale = widgetStart.scale newScale = MathUtils.lerp( startScale, startScale * GONE_SCALE_AMOUNT, progress ) // Let's make sure we're centering the view in the gone view instead of // having the left at 0 resultX = MathUtils.lerp( widgetStart.x, widgetEnd.x - resultMeasureWidth / 2.0f, progress) resultY = MathUtils.lerp(widgetStart.y, progress ) resultY = MathUtils.lerp( widgetStart.y, widgetEnd.y - resultMeasureHeight / 2.0f, progress) progress ) } } resultWidgetState.gone = nowGone } else { Loading Loading @@ -279,8 +348,10 @@ open class TransitionLayoutController { applyImmediately: Boolean, animate: Boolean, duration: Long = 0, delay: Long = 0 delay: Long = 0, isGuts: Boolean, ) { isGutsAnimation = isGuts val animated = animate && currentState.width != 0 this.state = state.copy() if (applyImmediately || transitionLayout == null) { Loading @@ -291,6 +362,8 @@ open class TransitionLayoutController { animationStartState = currentState.copy() animator.duration = duration animator.startDelay = delay animator.interpolator = if (isGutsAnimation) Interpolators.LINEAR else Interpolators.FAST_OUT_SLOW_IN animator.start() } else if (!animator.isRunning) { applyStateToLayout(this.state) Loading Loading
packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt +20 −12 Original line number Diff line number Diff line Loading @@ -60,7 +60,7 @@ constructor( } companion object { @JvmField val GUTS_ANIMATION_DURATION = 500L @JvmField val GUTS_ANIMATION_DURATION = 234L } /** A listener when the current dimensions of the player change */ Loading Loading @@ -234,7 +234,8 @@ constructor( currentStartLocation, currentEndLocation, currentTransitionProgress, applyImmediately = false applyImmediately = false, isGutsAnimation = true, ) } Loading @@ -254,7 +255,8 @@ constructor( currentStartLocation, currentEndLocation, currentTransitionProgress, applyImmediately = immediate applyImmediately = immediate, isGutsAnimation = true, ) } Loading Loading @@ -414,7 +416,10 @@ constructor( * it's not available, it will recreate one by measuring, which may be expensive. */ @VisibleForTesting fun obtainViewState(state: MediaHostState?): TransitionViewState? { fun obtainViewState( state: MediaHostState?, isGutsAnimation: Boolean = false ): TransitionViewState? { if (state == null || state.measurementInput == null) { return null } Loading @@ -423,7 +428,7 @@ constructor( val viewState = viewStates[cacheKey] if (viewState != null) { // we already have cached this measurement, let's continue if (state.squishFraction <= 1f) { if (state.squishFraction <= 1f && !isGutsAnimation) { return squishViewState(viewState, state.squishFraction) } return viewState Loading Loading @@ -455,13 +460,14 @@ constructor( // Given that we have a measurement and a view, let's get (guaranteed) viewstates // from the start and end state and interpolate them val startViewState = obtainViewState(startState) as TransitionViewState val startViewState = obtainViewState(startState, isGutsAnimation) as TransitionViewState val endState = state.copy().also { it.expansion = 1.0f } val endViewState = obtainViewState(endState) as TransitionViewState val endViewState = obtainViewState(endState, isGutsAnimation) as TransitionViewState result = layoutController.getInterpolatedState(startViewState, endViewState, state.expansion) } if (state.squishFraction <= 1f) { // Skip the adjustments of squish view state if UMO changes due to guts animation. if (state.squishFraction <= 1f && !isGutsAnimation) { return squishViewState(result, state.squishFraction) } return result Loading Loading @@ -521,7 +527,8 @@ constructor( @MediaLocation startLocation: Int, @MediaLocation endLocation: Int, transitionProgress: Float, applyImmediately: Boolean applyImmediately: Boolean, isGutsAnimation: Boolean = false, ) = traceSection("MediaViewController#setCurrentState") { currentEndLocation = endLocation Loading @@ -537,7 +544,7 @@ constructor( // Obtain the view state that we'd want to be at the end // The view might not be bound yet or has never been measured and in that case will be // reset once the state is fully available var endViewState = obtainViewState(endHostState) ?: return var endViewState = obtainViewState(endHostState, isGutsAnimation) ?: return endViewState = updateViewStateSize(endViewState, endLocation, tmpState2)!! layoutController.setMeasureState(endViewState) Loading @@ -548,7 +555,7 @@ constructor( } val result: TransitionViewState var startViewState = obtainViewState(startHostState) var startViewState = obtainViewState(startHostState, isGutsAnimation) startViewState = updateViewStateSize(startViewState, startLocation, tmpState3) if (!endHostState.visible) { Loading Loading @@ -602,7 +609,8 @@ constructor( applyImmediately, shouldAnimate, animationDuration, animationDelay animationDelay, isGutsAnimation, ) } Loading
packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt +109 −36 Original line number Diff line number Diff line Loading @@ -25,6 +25,16 @@ import com.android.app.animation.Interpolators * The fraction after which we start fading in when going from a gone widget to a visible one */ private const val GONE_FADE_FRACTION = 0.8f /** * The fraction after which we start fading in going from a gone widget to a visible one in guts * animation. */ private const val GONE_FADE_GUTS_FRACTION = 0.286f /** * The fraction before which we fade out when going from a visible widget to a gone one in guts * animation. */ private const val VISIBLE_FADE_GUTS_FRACTION = 0.355f /** * The amont we're scaling appearing views Loading @@ -45,6 +55,7 @@ open class TransitionLayoutController { private var animationStartState: TransitionViewState? = null private var state = TransitionViewState() private var animator: ValueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f) private var isGutsAnimation = false private var currentHeight: Int = 0 private var currentWidth: Int = 0 var sizeChangedListener: ((Int, Int) -> Unit)? = null Loading Loading @@ -152,15 +163,6 @@ open class TransitionLayoutController { // this looks quite ugly val nowGone: Boolean if (widgetStart.gone) { // Only fade it in at the very end alphaProgress = MathUtils.map(GONE_FADE_FRACTION, 1.0f, 0.0f, 1.0f, progress) nowGone = progress < GONE_FADE_FRACTION // Scale it just a little, not all the way val endScale = widgetEnd.scale newScale = MathUtils.lerp(GONE_SCALE_AMOUNT * endScale, endScale, progress) // don't clip widthProgress = 1.0f Loading @@ -168,25 +170,52 @@ open class TransitionLayoutController { resultMeasureWidth = widgetEnd.measureWidth resultMeasureHeight = widgetEnd.measureHeight // Let's make sure we're centering the view in the gone view instead of having // the left at 0 resultX = MathUtils.lerp(widgetStart.x - resultMeasureWidth / 2.0f, widgetEnd.x, progress) resultY = MathUtils.lerp(widgetStart.y - resultMeasureHeight / 2.0f, widgetEnd.y, progress) if (isGutsAnimation) { // if animation is open/close guts, fade in starts early. alphaProgress = MathUtils.map( GONE_FADE_GUTS_FRACTION, 1.0f, 0.0f, 1.0f, progress ) nowGone = progress < GONE_FADE_GUTS_FRACTION // Do not change scale of widget. newScale = 1.0f // We do not want any horizontal or vertical movement. resultX = widgetStart.x resultY = widgetStart.y } else { // Fadeout in the very beginning alphaProgress = MathUtils.map(0.0f, 1.0f - GONE_FADE_FRACTION, 0.0f, 1.0f, progress) nowGone = progress > 1.0f - GONE_FADE_FRACTION // Only fade it in at the very end alphaProgress = MathUtils.map( GONE_FADE_FRACTION, 1.0f, 0.0f, 1.0f, progress ) nowGone = progress < GONE_FADE_FRACTION // Scale it just a little, not all the way val startScale = widgetStart.scale newScale = MathUtils.lerp(startScale, startScale * GONE_SCALE_AMOUNT, progress) val endScale = widgetEnd.scale newScale = MathUtils.lerp(GONE_SCALE_AMOUNT * endScale, endScale, progress) // Let's make sure we're centering the view in the gone view instead of // having the left at 0 resultX = MathUtils.lerp( widgetStart.x - resultMeasureWidth / 2.0f, widgetEnd.x, progress ) resultY = MathUtils.lerp( widgetStart.y - resultMeasureHeight / 2.0f, widgetEnd.y, progress ) } } else { // Don't clip widthProgress = 0.0f Loading @@ -194,14 +223,54 @@ open class TransitionLayoutController { resultMeasureWidth = widgetStart.measureWidth resultMeasureHeight = widgetStart.measureHeight // Let's make sure we're centering the view in the gone view instead of having // the left at 0 resultX = MathUtils.lerp(widgetStart.x, // Fadeout in the very beginning if (isGutsAnimation) { alphaProgress = MathUtils.map( 0.0f, VISIBLE_FADE_GUTS_FRACTION, 0.0f, 1.0f, progress ) nowGone = progress > VISIBLE_FADE_GUTS_FRACTION // Do not change scale of widget during open/close guts animation. newScale = 1.0f // We do not want any horizontal or vertical movement. resultX = widgetEnd.x resultY = widgetEnd.y } else { alphaProgress = MathUtils.map( 0.0f, 1.0f - GONE_FADE_FRACTION, 0.0f, 1.0f, progress ) nowGone = progress > 1.0f - GONE_FADE_FRACTION // Scale it just a little, not all the way val startScale = widgetStart.scale newScale = MathUtils.lerp( startScale, startScale * GONE_SCALE_AMOUNT, progress ) // Let's make sure we're centering the view in the gone view instead of // having the left at 0 resultX = MathUtils.lerp( widgetStart.x, widgetEnd.x - resultMeasureWidth / 2.0f, progress) resultY = MathUtils.lerp(widgetStart.y, progress ) resultY = MathUtils.lerp( widgetStart.y, widgetEnd.y - resultMeasureHeight / 2.0f, progress) progress ) } } resultWidgetState.gone = nowGone } else { Loading Loading @@ -279,8 +348,10 @@ open class TransitionLayoutController { applyImmediately: Boolean, animate: Boolean, duration: Long = 0, delay: Long = 0 delay: Long = 0, isGuts: Boolean, ) { isGutsAnimation = isGuts val animated = animate && currentState.width != 0 this.state = state.copy() if (applyImmediately || transitionLayout == null) { Loading @@ -291,6 +362,8 @@ open class TransitionLayoutController { animationStartState = currentState.copy() animator.duration = duration animator.startDelay = delay animator.interpolator = if (isGutsAnimation) Interpolators.LINEAR else Interpolators.FAST_OUT_SLOW_IN animator.start() } else if (!animator.isRunning) { applyStateToLayout(this.state) Loading