diff options
| author | 2025-02-17 16:03:11 +0100 | |
|---|---|---|
| committer | 2025-02-17 16:44:08 +0100 | |
| commit | cad8f822d132b4bafa003061d44977ad40761f6f (patch) | |
| tree | d80e33d044f5543bfd2beee5bb41b1a25425e1b3 | |
| parent | b9e8a0eae92f987230200fc848a400d09b0ac8ea (diff) | |
Clean-up ExpandableController
This CL cleans up ExpandableController so that we don't expose State
properties and instead expose normal properties (invisibly backed by a
State). This is because it's general good practice to not expose State
parameters, and this old code was adhering to this practice.
Bug: 285250939
Test: N/A
Flag: EXEMPT simple clean-up
Change-Id: If0c48e56cadf43b01f9909a2642c37ac72e50d63
| -rw-r--r-- | packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt | 25 | ||||
| -rw-r--r-- | packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt | 97 |
2 files changed, 53 insertions, 69 deletions
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt index d79fbd608b7b..a1d362a4a11d 100644 --- a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt +++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt @@ -218,26 +218,23 @@ fun Expandable( // animating. AnimatedContentInOverlay( color, - controller.boundsInComposeViewRoot.value.size, - controller.animatorState, - controller.overlay.value + controller.boundsInComposeViewRoot.size, + controller.overlay ?: error("AnimatedContentInOverlay shouldn't be composed with null overlay."), controller, wrappedContent, controller.composeViewRoot, - { controller.currentComposeViewInOverlay.value = it }, + { controller.currentComposeViewInOverlay = it }, controller.density, ) } - controller.isDialogShowing.value -> { + controller.isDialogShowing -> { Box( modifier .updateExpandableSize() .then(minInteractiveSizeModifier) .drawWithContent { /* Don't draw anything when the dialog is shown. */ } - .onGloballyPositioned { - controller.boundsInComposeViewRoot.value = it.boundsInRoot() - } + .onGloballyPositioned { controller.boundsInComposeViewRoot = it.boundsInRoot() } ) { wrappedContent(controller.expandable) } @@ -250,9 +247,7 @@ fun Expandable( .then(clickModifier(controller, onClick, interactionSource)) .background(color, shape) .border(controller) - .onGloballyPositioned { - controller.boundsInComposeViewRoot.value = it.boundsInRoot() - } + .onGloballyPositioned { controller.boundsInComposeViewRoot = it.boundsInRoot() } ) { wrappedContent(controller.expandable) } @@ -309,7 +304,6 @@ private fun clickModifier( private fun AnimatedContentInOverlay( color: Color, sizeInOriginalLayout: Size, - animatorState: State<TransitionAnimator.State?>, overlay: ViewGroupOverlay, controller: ExpandableControllerImpl, content: @Composable (Expandable) -> Unit, @@ -332,7 +326,7 @@ private fun AnimatedContentInOverlay( // so that its content is laid out exactly the same way. .requiredSize(with(density) { sizeInOriginalLayout.toDpSize() }) .drawWithContent { - val animatorState = animatorState.value ?: return@drawWithContent + val animatorState = controller.animatorState ?: return@drawWithContent // Scale the content with the background while keeping its aspect ratio. val widthRatio = @@ -356,7 +350,8 @@ private fun AnimatedContentInOverlay( setContent { Box( Modifier.fillMaxSize().drawWithContent { - val animatorState = animatorState.value ?: return@drawWithContent + val animatorState = + controller.animatorState ?: return@drawWithContent if (!animatorState.visible) { return@drawWithContent } @@ -393,7 +388,7 @@ private fun AnimatedContentInOverlay( overlay.add(composeViewInOverlay) val startState = - animatorState.value + controller.animatorState ?: throw IllegalStateException( "AnimatedContentInOverlay shouldn't be composed with null animatorState." ) diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt index 16150f813b05..377ea96c5723 100644 --- a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt +++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt @@ -25,12 +25,11 @@ import androidx.compose.foundation.BorderStroke import androidx.compose.material3.contentColorFor import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.State import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Rect import androidx.compose.ui.geometry.Size @@ -78,24 +77,9 @@ fun rememberExpandableController( val density = LocalDensity.current val layoutDirection = LocalLayoutDirection.current - // The current animation state, if we are currently animating a dialog or activity. - val animatorState = remember { mutableStateOf<TransitionAnimator.State?>(null) } - - // Whether a dialog controlled by this ExpandableController is currently showing. - val isDialogShowing = remember { mutableStateOf(false) } - - // The overlay in which we should animate the launch. - val overlay = remember { mutableStateOf<ViewGroupOverlay?>(null) } - - // The current [ComposeView] being animated in the [overlay], if any. - val currentComposeViewInOverlay = remember { mutableStateOf<View?>(null) } - - // The bounds in [composeViewRoot] of the expandable controlled by this controller. - val boundsInComposeViewRoot = remember { mutableStateOf(Rect.Zero) } - // Whether this composable is still composed. We only do the dialog exit animation if this is // true. - val isComposed = remember { mutableStateOf(true) } + var isComposed by remember { mutableStateOf(true) } val controller = remember( @@ -114,19 +98,14 @@ fun rememberExpandableController( borderStroke, composeViewRoot, density, - animatorState, - isDialogShowing, - overlay, - currentComposeViewInOverlay, - boundsInComposeViewRoot, layoutDirection, - isComposed, + { isComposed }, ) } DisposableEffect(Unit) { onDispose { - isComposed.value = false + isComposed = false if (TransitionAnimator.returnAnimationsEnabled()) { controller.onDispose() } @@ -143,14 +122,27 @@ internal class ExpandableControllerImpl( internal val borderStroke: BorderStroke?, internal val composeViewRoot: View, internal val density: Density, - internal val animatorState: MutableState<TransitionAnimator.State?>, - internal val isDialogShowing: MutableState<Boolean>, - internal val overlay: MutableState<ViewGroupOverlay?>, - internal val currentComposeViewInOverlay: MutableState<View?>, - internal val boundsInComposeViewRoot: MutableState<Rect>, private val layoutDirection: LayoutDirection, - private val isComposed: State<Boolean>, + private val isComposed: () -> Boolean, ) : ExpandableController { + /** The current animation state, if we are currently animating a dialog or activity. */ + var animatorState by mutableStateOf<TransitionAnimator.State?>(null) + private set + + /** Whether a dialog controlled by this ExpandableController is currently showing. */ + var isDialogShowing by mutableStateOf(false) + private set + + /** The overlay in which we should animate the launch. */ + var overlay by mutableStateOf<ViewGroupOverlay?>(null) + private set + + /** The current [ComposeView] being animated in the [overlay], if any. */ + var currentComposeViewInOverlay by mutableStateOf<View?>(null) + + /** The bounds in [composeViewRoot] of the expandable controlled by this controller. */ + var boundsInComposeViewRoot by mutableStateOf(Rect.Zero) + /** The [ActivityTransitionAnimator.Controller] to be cleaned up [onDispose]. */ private var activityControllerForDisposal: ActivityTransitionAnimator.Controller? = null @@ -163,7 +155,7 @@ internal class ExpandableControllerImpl( returnCujType: Int?, isEphemeral: Boolean, ): ActivityTransitionAnimator.Controller? { - if (!isComposed.value) { + if (!isComposed()) { return null } @@ -179,7 +171,7 @@ internal class ExpandableControllerImpl( override fun dialogTransitionController( cuj: DialogCuj? ): DialogTransitionAnimator.Controller? { - if (!isComposed.value) { + if (!isComposed()) { return null } @@ -187,9 +179,7 @@ internal class ExpandableControllerImpl( } } - override val isAnimating: Boolean by derivedStateOf { - animatorState.value != null && overlay.value != null - } + override val isAnimating: Boolean by derivedStateOf { animatorState != null && overlay != null } override fun onDispose() { activityControllerForDisposal?.onDispose() @@ -213,7 +203,7 @@ internal class ExpandableControllerImpl( override val isLaunching: Boolean = true override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) { - animatorState.value = null + animatorState = null } override fun onTransitionAnimationProgress( @@ -223,7 +213,7 @@ internal class ExpandableControllerImpl( ) { // We copy state given that it's always the same object that is mutated by // ActivityTransitionAnimator. - animatorState.value = + animatorState = TransitionAnimator.State( state.top, state.bottom, @@ -236,13 +226,11 @@ internal class ExpandableControllerImpl( // Force measure and layout the ComposeView in the overlay whenever the animation // state changes. - currentComposeViewInOverlay.value?.let { - measureAndLayoutComposeViewInOverlay(it, state) - } + currentComposeViewInOverlay?.let { measureAndLayoutComposeViewInOverlay(it, state) } } override fun createAnimatorState(): TransitionAnimator.State { - val boundsInRoot = boundsInComposeViewRoot.value + val boundsInRoot = boundsInComposeViewRoot val outline = shape.createOutline( Size(boundsInRoot.width, boundsInRoot.height), @@ -294,7 +282,7 @@ internal class ExpandableControllerImpl( private fun rootLocationOnScreen(): Offset { composeViewRoot.getLocationOnScreen(rootLocationOnScreen) - val boundsInRoot = boundsInComposeViewRoot.value + val boundsInRoot = boundsInComposeViewRoot val x = rootLocationOnScreen[0] + boundsInRoot.left val y = rootLocationOnScreen[1] + boundsInRoot.top return Offset(x, y) @@ -328,14 +316,14 @@ internal class ExpandableControllerImpl( override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) { delegate.onTransitionAnimationStart(isExpandingFullyAbove) - overlay.value = transitionContainer.overlay as ViewGroupOverlay + overlay = transitionContainer.overlay as ViewGroupOverlay cujType?.let { InteractionJankMonitor.getInstance().begin(composeViewRoot, it) } } override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) { cujType?.let { InteractionJankMonitor.getInstance().end(it) } delegate.onTransitionAnimationEnd(isExpandingFullyAbove) - overlay.value = null + overlay = null } } } @@ -348,14 +336,14 @@ internal class ExpandableControllerImpl( override fun startDrawingInOverlayOf(viewGroup: ViewGroup) { val newOverlay = viewGroup.overlay as ViewGroupOverlay - if (newOverlay != overlay.value) { - overlay.value = newOverlay + if (newOverlay != overlay) { + overlay = newOverlay } } override fun stopDrawingInOverlay() { - if (overlay.value != null) { - overlay.value = null + if (overlay != null) { + overlay = null } } @@ -366,7 +354,7 @@ internal class ExpandableControllerImpl( delegate.onTransitionAnimationEnd(isExpandingFullyAbove) // Make sure we don't draw this expandable when the dialog is showing. - isDialogShowing.value = true + isDialogShowing = true } } } @@ -376,16 +364,17 @@ internal class ExpandableControllerImpl( return object : TransitionAnimator.Controller by delegate { override fun onTransitionAnimationEnd(isExpandingFullyAbove: Boolean) { delegate.onTransitionAnimationEnd(isExpandingFullyAbove) - isDialogShowing.value = false + isDialogShowing = false } } } - override fun shouldAnimateExit(): Boolean = - isComposed.value && composeViewRoot.isAttachedToWindow && composeViewRoot.isShown + override fun shouldAnimateExit(): Boolean { + return isComposed() && composeViewRoot.isAttachedToWindow && composeViewRoot.isShown + } override fun onExitAnimationCancelled() { - isDialogShowing.value = false + isDialogShowing = false } override fun jankConfigurationBuilder(): InteractionJankMonitor.Configuration.Builder? { |