Merge "Move ContentState.Transition back into TransitionState.Transition (1/2)" into main
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
index bcdb259..eae46e9 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt
@@ -111,7 +111,7 @@
1f
}
- val dir = if (transition.toScene == splitShadeLargeClockScene) -1f else 1f
+ val dir = if (transition.toContent == splitShadeLargeClockScene) -1f else 1f
val distance = dir * getClockCenteringDistance()
val largeClock = checkNotNull(currentClock).largeClock
largeClock.animations.onPositionUpdated(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaContentPicker.kt b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaContentPicker.kt
index 70c0db1..5dccb68 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaContentPicker.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaContentPicker.kt
@@ -21,7 +21,7 @@
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.SceneTransitionLayoutState
import com.android.compose.animation.scene.StaticElementContentPicker
-import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
import com.android.systemui.scene.shared.model.Scenes
/** [ElementContentPicker] implementation for the media carousel object. */
@@ -38,7 +38,7 @@
override fun contentDuringTransition(
element: ElementKey,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
fromContentZIndex: Float,
toContentZIndex: Float
): ContentKey {
@@ -64,7 +64,7 @@
}
/** Returns true when the media should be laid on top of the rest for the given [transition]. */
- fun shouldElevateMedia(transition: ContentState.Transition<*>): Boolean {
+ fun shouldElevateMedia(transition: TransitionState.Transition): Boolean {
return transition.isTransitioningBetween(Scenes.Lockscreen, Scenes.Shade)
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
index 0555346..fc4a8a5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettings.kt
@@ -98,7 +98,7 @@
else -> QSSceneAdapter.State.CLOSED
}
}
- is TransitionState.Transition ->
+ is TransitionState.Transition.ChangeCurrentScene ->
with(transitionState) {
when {
isSplitShade -> UnsquishingQS(squishiness)
@@ -108,16 +108,16 @@
fromScene == Scenes.QuickSettings && toScene == Scenes.Shade -> {
Collapsing { progress }
}
- fromScene == Scenes.Shade || toScene == Scenes.Shade -> {
+ fromContent == Scenes.Shade || toContent == Scenes.Shade -> {
UnsquishingQQS(squishiness)
}
- fromScene == Scenes.QuickSettings || toScene == Scenes.QuickSettings -> {
+ fromContent == Scenes.QuickSettings || toContent == Scenes.QuickSettings -> {
QSSceneAdapter.State.QS
}
else ->
error(
- "Bad transition for QuickSettings: fromScene=$fromScene," +
- " toScene=$toScene"
+ "Bad transition for QuickSettings: fromContent=$fromContent," +
+ " toScene=$toContent"
)
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index e064724..d16ba0d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -253,7 +253,7 @@
val isScrollable =
when (val state = layoutState.transitionState) {
is TransitionState.Idle -> true
- is TransitionState.Transition -> state.fromScene == Scenes.QuickSettings
+ is TransitionState.Transition -> state.fromContent == Scenes.QuickSettings
}
LaunchedEffect(isCustomizing, scrollState) {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateContent.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateContent.kt
index 5eabd22..2bc8c87 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateContent.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateContent.kt
@@ -19,14 +19,14 @@
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.AnimationVector1D
import androidx.compose.animation.core.SpringSpec
-import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
internal fun CoroutineScope.animateContent(
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
oneOffAnimation: OneOffAnimation,
targetProgress: Float,
startTransition: () -> Unit,
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
index ae5a84b..ea708a5 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
@@ -396,8 +396,8 @@
return sharedValue[layoutImpl.state.transitionState.currentScene]
}
- val fromValue = sharedValue[transition.fromScene]
- val toValue = sharedValue[transition.toScene]
+ val fromValue = sharedValue[transition.fromContent]
+ val toValue = sharedValue[transition.toContent]
return if (fromValue != null && toValue != null) {
if (fromValue == toValue) {
// Optimization: avoid reading progress if the values are the same, so we don't
@@ -411,7 +411,7 @@
if (canOverflow) transition.progress
else transition.progress.fastCoerceIn(0f, 1f)
}
- overscrollSpec.scene == transition.toScene -> 1f
+ overscrollSpec.scene == transition.toContent -> 1f
else -> 0f
}
@@ -426,12 +426,12 @@
if (element != null) {
layoutImpl.elements[element]?.stateByContent?.let { sceneStates ->
layoutImpl.state.currentTransitions.fastLastOrNull { transition ->
- transition.fromScene in sceneStates || transition.toScene in sceneStates
+ transition.fromContent in sceneStates || transition.toContent in sceneStates
}
}
} else {
layoutImpl.state.currentTransitions.fastLastOrNull { transition ->
- transition.fromScene in targetValues || transition.toScene in targetValues
+ transition.fromContent in targetValues || transition.toContent in targetValues
}
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
index 920c234..f2c2a36 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
@@ -28,7 +28,7 @@
layoutState: MutableSceneTransitionLayoutStateImpl,
target: SceneKey,
transitionKey: TransitionKey?,
-): TransitionState.Transition? {
+): TransitionState.Transition.ChangeCurrentScene? {
val transitionState = layoutState.transitionState
if (transitionState.currentScene == target) {
// This can happen in 3 different situations, for which there isn't anything else to do:
@@ -52,7 +52,7 @@
replacedTransition = null,
)
}
- is TransitionState.Transition -> {
+ is TransitionState.Transition.ChangeCurrentScene -> {
val isInitiatedByUserInput = transitionState.isInitiatedByUserInput
// A transition is currently running: first check whether `transition.toScene` or
@@ -136,7 +136,7 @@
reversed: Boolean = false,
fromScene: SceneKey = layoutState.transitionState.currentScene,
chain: Boolean = true,
-): TransitionState.Transition {
+): TransitionState.Transition.ChangeCurrentScene {
val oneOffAnimation = OneOffAnimation()
val targetProgress = if (reversed) 0f else 1f
val transition =
@@ -181,7 +181,7 @@
override val isInitiatedByUserInput: Boolean,
replacedTransition: TransitionState.Transition?,
private val oneOffAnimation: OneOffAnimation,
-) : TransitionState.Transition(fromScene, toScene, replacedTransition) {
+) : TransitionState.Transition.ChangeCurrentScene(fromScene, toScene, replacedTransition) {
override val progress: Float
get() = oneOffAnimation.progress
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index 83db724..7787458 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -31,9 +31,8 @@
import androidx.compose.ui.unit.round
import androidx.compose.ui.util.fastCoerceIn
import com.android.compose.animation.scene.content.Scene
-import com.android.compose.animation.scene.content.state.ContentState
-import com.android.compose.animation.scene.content.state.ContentState.HasOverscrollProperties.Companion.DistanceUnspecified
import com.android.compose.animation.scene.content.state.TransitionState
+import com.android.compose.animation.scene.content.state.TransitionState.HasOverscrollProperties.Companion.DistanceUnspecified
import com.android.compose.nestedscroll.PriorityNestedScrollConnection
import kotlin.math.absoluteValue
import kotlinx.coroutines.CoroutineScope
@@ -582,8 +581,8 @@
replacedTransition: SwipeTransition?,
var lastDistance: Float = DistanceUnspecified,
) :
- TransitionState.Transition(_fromScene.key, _toScene.key, replacedTransition),
- ContentState.HasOverscrollProperties {
+ TransitionState.Transition.ChangeCurrentScene(_fromScene.key, _toScene.key, replacedTransition),
+ TransitionState.HasOverscrollProperties {
var _currentScene by mutableStateOf(_fromScene)
override val currentScene: SceneKey
get() = _currentScene.key
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
index e619814..7dac2e4 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
@@ -49,7 +49,6 @@
import androidx.compose.ui.util.fastLastOrNull
import androidx.compose.ui.util.lerp
import com.android.compose.animation.scene.content.Content
-import com.android.compose.animation.scene.content.state.ContentState
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.transformation.PropertyTransformation
import com.android.compose.animation.scene.transformation.SharedElementTransformation
@@ -69,7 +68,7 @@
* The last transition that was used when computing the state (size, position and alpha) of this
* element in any content, or `null` if it was last laid out when idle.
*/
- var lastTransition: ContentState.Transition<*>? = null
+ var lastTransition: TransitionState.Transition? = null
/** Whether this element was ever drawn in a content. */
var wasDrawnInAnyContent = false
@@ -312,7 +311,7 @@
}
private fun Placeable.PlacementScope.place(
- transition: ContentState.Transition<*>?,
+ transition: TransitionState.Transition?,
placeable: Placeable,
) {
with(layoutImpl.lookaheadScope) {
@@ -477,11 +476,11 @@
layoutImpl: SceneTransitionLayoutImpl,
element: Element,
transitions: List<TransitionState.Transition>,
-): ContentState.Transition<*>? {
+): TransitionState.Transition? {
val transition =
transitions.fastLastOrNull { transition ->
- transition.fromScene in element.stateByContent ||
- transition.toScene in element.stateByContent
+ transition.fromContent in element.stateByContent ||
+ transition.toContent in element.stateByContent
}
val previousTransition = element.lastTransition
@@ -504,8 +503,8 @@
private fun prepareInterruption(
layoutImpl: SceneTransitionLayoutImpl,
element: Element,
- transition: ContentState.Transition<*>,
- previousTransition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
+ previousTransition: TransitionState.Transition,
) {
if (transition.replacedTransition == previousTransition) {
return
@@ -552,7 +551,7 @@
*/
private fun reconcileStates(
element: Element,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
) {
val fromContentState = element.stateByContent[transition.fromContent] ?: return
val toContentState = element.stateByContent[transition.toContent] ?: return
@@ -621,7 +620,7 @@
*/
private inline fun <T> computeInterruptedValue(
layoutImpl: SceneTransitionLayoutImpl,
- transition: ContentState.Transition<*>?,
+ transition: TransitionState.Transition?,
value: T,
unspecifiedValue: T,
zeroValue: T,
@@ -668,7 +667,7 @@
private inline fun <T> setPlacementInterruptionDelta(
element: Element,
stateInContent: Element.State,
- transition: ContentState.Transition<*>?,
+ transition: TransitionState.Transition?,
delta: T,
setter: (Element.State, T) -> Unit,
) {
@@ -694,7 +693,7 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: Element,
- transition: ContentState.Transition<*>?,
+ transition: TransitionState.Transition?,
): Boolean {
// Always place the element if we are idle.
if (transition == null) {
@@ -732,7 +731,7 @@
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: ElementKey,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
): Boolean {
// If we are overscrolling, only place/compose the element in the overscrolling scene.
val overscrollScene = transition.currentOverscrollSpec?.scene
@@ -743,7 +742,7 @@
val scenePicker = element.contentPicker
val pickedScene =
when (transition) {
- is TransitionState.Transition -> {
+ is TransitionState.Transition.ChangeCurrentScene -> {
scenePicker.contentDuringTransition(
element = element,
transition = transition,
@@ -758,14 +757,14 @@
private fun isSharedElementEnabled(
element: ElementKey,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
): Boolean {
return sharedElementTransformation(element, transition)?.enabled ?: true
}
internal fun sharedElementTransformation(
element: ElementKey,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
): SharedElementTransformation? {
val transformationSpec = transition.transformationSpec
val sharedInFromContent =
@@ -793,7 +792,7 @@
private fun isElementOpaque(
content: Content,
element: Element,
- transition: ContentState.Transition<*>?,
+ transition: TransitionState.Transition?,
): Boolean {
if (transition == null) {
return true
@@ -827,7 +826,7 @@
private fun elementAlpha(
layoutImpl: SceneTransitionLayoutImpl,
element: Element,
- transition: ContentState.Transition<*>?,
+ transition: TransitionState.Transition?,
stateInContent: Element.State,
): Float {
val alpha =
@@ -858,7 +857,7 @@
private fun interruptedAlpha(
layoutImpl: SceneTransitionLayoutImpl,
element: Element,
- transition: ContentState.Transition<*>?,
+ transition: TransitionState.Transition?,
stateInContent: Element.State,
alpha: Float,
): Float {
@@ -888,7 +887,7 @@
private fun measure(
layoutImpl: SceneTransitionLayoutImpl,
element: Element,
- transition: ContentState.Transition<*>?,
+ transition: TransitionState.Transition?,
stateInContent: Element.State,
measurable: Measurable,
constraints: Constraints,
@@ -952,7 +951,7 @@
private fun ContentDrawScope.getDrawScale(
layoutImpl: SceneTransitionLayoutImpl,
element: Element,
- transition: ContentState.Transition<*>?,
+ transition: TransitionState.Transition?,
stateInContent: Element.State,
): Scale {
val scale =
@@ -1048,7 +1047,7 @@
layoutImpl: SceneTransitionLayoutImpl,
currentContentState: Element.State,
element: Element,
- transition: ContentState.Transition<*>?,
+ transition: TransitionState.Transition?,
contentValue: (Element.State) -> T,
transformation: (ElementTransformations) -> PropertyTransformation<T>?,
currentValue: () -> T,
@@ -1076,7 +1075,7 @@
}
val currentContent = currentContentState.content
- if (transition is ContentState.HasOverscrollProperties) {
+ if (transition is TransitionState.HasOverscrollProperties) {
val overscroll = transition.currentOverscrollSpec
if (overscroll?.scene == currentContent) {
val elementSpec =
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/InterruptionHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/InterruptionHandler.kt
index bf70ca9..6181cfb 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/InterruptionHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/InterruptionHandler.kt
@@ -37,7 +37,7 @@
* @see InterruptionResult
*/
fun onInterruption(
- interrupted: TransitionState.Transition,
+ interrupted: TransitionState.Transition.ChangeCurrentScene,
newTargetScene: SceneKey,
): InterruptionResult?
}
@@ -76,7 +76,7 @@
*/
object DefaultInterruptionHandler : InterruptionHandler {
override fun onInterruption(
- interrupted: TransitionState.Transition,
+ interrupted: TransitionState.Transition.ChangeCurrentScene,
newTargetScene: SceneKey,
): InterruptionResult {
return InterruptionResult(
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
index abecdd7..63d51f9 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
@@ -185,7 +185,7 @@
val contents = element.contentPicker.contents
val transition =
transitions.fastLastOrNull { transition ->
- transition.fromScene in contents || transition.toScene in contents
+ transition.fromContent in contents || transition.toContent in contents
} ?: return false
// Always compose movable elements in the scene picked by their scene picker.
@@ -215,7 +215,8 @@
// This code is only run during transitions (otherwise the content would be composed and the
// placeholder would not), so it's ok to cast the state into a Transition directly.
- val transition = layoutImpl.state.transitionState as TransitionState.Transition
+ val transition =
+ layoutImpl.state.transitionState as TransitionState.Transition.ChangeCurrentScene
// If the content was already composed in the other scene, we use that target size assuming it
// doesn't change between scenes.
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
index 8f1a4141..5071a7f 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
@@ -111,7 +111,7 @@
return snapshotFlow {
when (val state = transitionState) {
is TransitionState.Idle -> ObservableTransitionState.Idle(state.currentScene)
- is TransitionState.Transition -> {
+ is TransitionState.Transition.ChangeCurrentScene -> {
ObservableTransitionState.Transition(
fromScene = state.fromScene,
toScene = state.toScene,
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PredictiveBackHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PredictiveBackHandler.kt
index cc53a28..e7e6b2a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PredictiveBackHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PredictiveBackHandler.kt
@@ -70,7 +70,7 @@
val coroutineScope: CoroutineScope,
fromScene: SceneKey,
toScene: SceneKey,
-) : TransitionState.Transition(fromScene, toScene) {
+) : TransitionState.Transition.ChangeCurrentScene(fromScene, toScene) {
override var currentScene by mutableStateOf(fromScene)
private set
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
index 062d553..392ff7e 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
@@ -38,6 +38,7 @@
import androidx.compose.ui.util.fastForEachReversed
import com.android.compose.animation.scene.content.Content
import com.android.compose.animation.scene.content.Scene
+import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.ui.util.lerp
import kotlinx.coroutines.CoroutineScope
@@ -247,8 +248,12 @@
// Compose the new scene we are going to first.
transitions.fastForEachReversed { transition ->
- maybeAdd(transition.toScene)
- maybeAdd(transition.fromScene)
+ when (transition) {
+ is TransitionState.Transition.ChangeCurrentScene -> {
+ maybeAdd(transition.toScene)
+ maybeAdd(transition.fromScene)
+ }
+ }
}
}
}
@@ -284,7 +289,8 @@
val width: Int
val height: Int
- val transition = layoutImpl.state.currentTransition
+ val transition =
+ layoutImpl.state.currentTransition as? TransitionState.Transition.ChangeCurrentScene
if (transition == null) {
width = placeable.width
height = placeable.height
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
index 44f5964f..f37ded0 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
@@ -25,7 +25,6 @@
import androidx.compose.ui.util.fastAll
import androidx.compose.ui.util.fastFilter
import androidx.compose.ui.util.fastForEach
-import com.android.compose.animation.scene.content.state.ContentState
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.transition.link.LinkedTransition
import com.android.compose.animation.scene.transition.link.StateLink
@@ -209,7 +208,7 @@
targetScene: SceneKey,
coroutineScope: CoroutineScope,
transitionKey: TransitionKey?,
- ): TransitionState.Transition? {
+ ): TransitionState.Transition.ChangeCurrentScene? {
checkThread()
return coroutineScope.animateToScene(
@@ -228,13 +227,16 @@
*
* Important: you *must* call [finishTransition] once the transition is finished.
*/
- internal fun startTransition(transition: TransitionState.Transition, chain: Boolean = true) {
+ internal fun startTransition(
+ transition: TransitionState.Transition.ChangeCurrentScene,
+ chain: Boolean = true,
+ ) {
checkThread()
// Compute the [TransformationSpec] when the transition starts.
val fromScene = transition.fromScene
val toScene = transition.toScene
- val orientation = (transition as? ContentState.HasOverscrollProperties)?.orientation
+ val orientation = (transition as? TransitionState.HasOverscrollProperties)?.orientation
// Update the transition specs.
transition.transformationSpec =
@@ -312,8 +314,8 @@
appendLine(" Transitions (size=${transitionStates.size}):")
transitionStates.fastForEach { state ->
val transition = state as TransitionState.Transition
- val from = transition.fromScene
- val to = transition.toScene
+ val from = transition.fromContent
+ val to = transition.toContent
val indicator = if (finishedTransitions.contains(transition)) "x" else " "
appendLine(" [$indicator] $from => $to ($transition)")
}
@@ -329,27 +331,31 @@
}
private fun setupTransitionLinks(transition: TransitionState.Transition) {
- stateLinks.fastForEach { stateLink ->
- val matchingLinks =
- stateLink.transitionLinks.fastFilter { it.isMatchingLink(transition) }
- if (matchingLinks.isEmpty()) return@fastForEach
- if (matchingLinks.size > 1) error("More than one link matched.")
+ when (transition) {
+ is TransitionState.Transition.ChangeCurrentScene -> {
+ stateLinks.fastForEach { stateLink ->
+ val matchingLinks =
+ stateLink.transitionLinks.fastFilter { it.isMatchingLink(transition) }
+ if (matchingLinks.isEmpty()) return@fastForEach
+ if (matchingLinks.size > 1) error("More than one link matched.")
- val targetCurrentScene = stateLink.target.transitionState.currentScene
- val matchingLink = matchingLinks[0]
+ val targetCurrentScene = stateLink.target.transitionState.currentScene
+ val matchingLink = matchingLinks[0]
- if (!matchingLink.targetIsInValidState(targetCurrentScene)) return@fastForEach
+ if (!matchingLink.targetIsInValidState(targetCurrentScene)) return@fastForEach
- val linkedTransition =
- LinkedTransition(
- originalTransition = transition,
- fromScene = targetCurrentScene,
- toScene = matchingLink.targetTo,
- key = matchingLink.targetTransitionKey,
- )
+ val linkedTransition =
+ LinkedTransition(
+ originalTransition = transition,
+ fromScene = targetCurrentScene,
+ toScene = matchingLink.targetTo,
+ key = matchingLink.targetTransitionKey,
+ )
- stateLink.target.startTransition(linkedTransition)
- transition.activeTransitionLinks[stateLink] = linkedTransition
+ stateLink.target.startTransition(linkedTransition)
+ transition.activeTransitionLinks[stateLink] = linkedTransition
+ }
+ }
}
}
@@ -451,8 +457,8 @@
}
val shouldSnap =
- (isProgressCloseTo(0f) && transition.currentScene == transition.fromScene) ||
- (isProgressCloseTo(1f) && transition.currentScene == transition.toScene)
+ (isProgressCloseTo(0f) && transition.currentScene == transition.fromContent) ||
+ (isProgressCloseTo(1f) && transition.currentScene == transition.toContent)
return if (shouldSnap) {
finishAllTransitions()
true
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
index e38c849..5cc194d 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt
@@ -25,7 +25,7 @@
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
-import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
import kotlin.math.tanh
/** Define the [transitions][SceneTransitions] to be used with a [SceneTransitionLayout]. */
@@ -262,7 +262,7 @@
*/
fun contentDuringTransition(
element: ElementKey,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
fromContentZIndex: Float,
toContentZIndex: Float,
): ContentKey
@@ -278,7 +278,7 @@
*/
fun pickSingleContentIn(
contents: Set<ContentKey>,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
element: ElementKey,
): ContentKey {
val fromContent = transition.fromContent
@@ -331,7 +331,7 @@
object HighestZIndexContentPicker : ElementContentPicker {
override fun contentDuringTransition(
element: ElementKey,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
fromContentZIndex: Float,
toContentZIndex: Float
): ContentKey {
@@ -352,7 +352,7 @@
override fun contentDuringTransition(
element: ElementKey,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
fromContentZIndex: Float,
toContentZIndex: Float
): ContentKey {
@@ -373,7 +373,7 @@
object LowestZIndexContentPicker : ElementContentPicker {
override fun contentDuringTransition(
element: ElementKey,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
fromContentZIndex: Float,
toContentZIndex: Float
): ContentKey {
@@ -394,7 +394,7 @@
override fun contentDuringTransition(
element: ElementKey,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
fromContentZIndex: Float,
toContentZIndex: Float
): ContentKey {
@@ -428,7 +428,7 @@
) : StaticElementContentPicker {
override fun contentDuringTransition(
element: ElementKey,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
fromContentZIndex: Float,
toContentZIndex: Float,
): ContentKey {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/ContentState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/ContentState.kt
deleted file mode 100644
index 0bd676b..0000000
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/ContentState.kt
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.compose.animation.scene.content.state
-
-import androidx.compose.animation.core.Animatable
-import androidx.compose.animation.core.AnimationVector1D
-import androidx.compose.animation.core.spring
-import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.runtime.Stable
-import com.android.compose.animation.scene.ContentKey
-import com.android.compose.animation.scene.OverscrollScope
-import com.android.compose.animation.scene.OverscrollSpecImpl
-import com.android.compose.animation.scene.ProgressVisibilityThreshold
-import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.TransformationSpec
-import com.android.compose.animation.scene.TransformationSpecImpl
-import com.android.compose.animation.scene.TransitionKey
-import com.android.compose.animation.scene.transition.link.LinkedTransition
-import com.android.compose.animation.scene.transition.link.StateLink
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.launch
-
-/** The state associated to one or more contents. */
-@Stable
-sealed interface ContentState<out T : ContentKey> {
- /** The [content] is idle, it does not animate. */
- sealed class Idle<T : ContentKey>(val content: T) : ContentState<T>
-
- /** The content is transitioning with another content. */
- sealed class Transition<out T : ContentKey>(
- val fromContent: T,
- val toContent: T,
- internal val replacedTransition: Transition<T>?,
- ) : ContentState<T> {
- /**
- * The key of this transition. This should usually be null, but it can be specified to use a
- * specific set of transformations associated to this transition.
- */
- open val key: TransitionKey? = null
-
- /**
- * The progress of the transition. This is usually in the `[0; 1]` range, but it can also be
- * less than `0` or greater than `1` when using transitions with a spring AnimationSpec or
- * when flinging quickly during a swipe gesture.
- */
- abstract val progress: Float
-
- /** The current velocity of [progress], in progress units. */
- abstract val progressVelocity: Float
-
- /** Whether the transition was triggered by user input rather than being programmatic. */
- abstract val isInitiatedByUserInput: Boolean
-
- /** Whether user input is currently driving the transition. */
- abstract val isUserInputOngoing: Boolean
-
- /**
- * The progress of the preview transition. This is usually in the `[0; 1]` range, but it can
- * also be less than `0` or greater than `1` when using transitions with a spring
- * AnimationSpec or when flinging quickly during a swipe gesture.
- */
- internal open val previewProgress: Float = 0f
-
- /** The current velocity of [previewProgress], in progress units. */
- internal open val previewProgressVelocity: Float = 0f
-
- /** Whether the transition is currently in the preview stage */
- internal open val isInPreviewStage: Boolean = false
-
- /**
- * The current [TransformationSpecImpl] and [OverscrollSpecImpl] associated to this
- * transition.
- *
- * Important: These will be set exactly once, when this transition is
- * [started][MutableSceneTransitionLayoutStateImpl.startTransition].
- */
- internal var transformationSpec: TransformationSpecImpl = TransformationSpec.Empty
- internal var previewTransformationSpec: TransformationSpecImpl? = null
- private var fromOverscrollSpec: OverscrollSpecImpl? = null
- private var toOverscrollSpec: OverscrollSpecImpl? = null
-
- /** The current [OverscrollSpecImpl], if this transition is currently overscrolling. */
- internal val currentOverscrollSpec: OverscrollSpecImpl?
- get() {
- if (this !is HasOverscrollProperties) return null
- val progress = progress
- val bouncingContent = bouncingContent
- return when {
- progress < 0f || bouncingContent == fromContent -> fromOverscrollSpec
- progress > 1f || bouncingContent == toContent -> toOverscrollSpec
- else -> null
- }
- }
-
- /**
- * An animatable that animates from 1f to 0f. This will be used to nicely animate the sudden
- * jump of values when this transitions interrupts another one.
- */
- private var interruptionDecay: Animatable<Float, AnimationVector1D>? = null
-
- /** The map of active links that connects this transition to other transitions. */
- internal val activeTransitionLinks = mutableMapOf<StateLink, LinkedTransition>()
-
- init {
- check(fromContent != toContent)
- check(
- replacedTransition == null ||
- (replacedTransition.fromContent == fromContent &&
- replacedTransition.toContent == toContent)
- )
- }
-
- /**
- * Force this transition to finish and animate to an [Idle] state.
- *
- * Important: Once this is called, the effective state of the transition should remain
- * unchanged. For instance, in the case of a [TransitionState.Transition], its
- * [currentScene][TransitionState.Transition.currentScene] should never change once [finish]
- * is called.
- *
- * @return the [Job] that animates to the idle state. It can be used to wait until the
- * animation is complete or cancel it to snap the animation. Calling [finish] multiple
- * times will return the same [Job].
- */
- internal abstract fun finish(): Job
-
- /**
- * Whether we are transitioning. If [from] or [to] is empty, we will also check that they
- * match the contents we are animating from and/or to.
- */
- fun isTransitioning(from: ContentKey? = null, to: ContentKey? = null): Boolean {
- return (from == null || fromContent == from) && (to == null || toContent == to)
- }
-
- /** Whether we are transitioning from [content] to [other], or from [other] to [content]. */
- fun isTransitioningBetween(content: ContentKey, other: ContentKey): Boolean {
- return isTransitioning(from = content, to = other) ||
- isTransitioning(from = other, to = content)
- }
-
- internal fun updateOverscrollSpecs(
- fromSpec: OverscrollSpecImpl?,
- toSpec: OverscrollSpecImpl?,
- ) {
- fromOverscrollSpec = fromSpec
- toOverscrollSpec = toSpec
- }
-
- /** Returns if the [progress] value of this transition can go beyond range `[0; 1]` */
- internal fun isWithinProgressRange(progress: Float): Boolean {
- // If the properties are missing we assume that every [Transition] can overscroll
- if (this !is HasOverscrollProperties) return true
- // [OverscrollSpec] for the current scene, even if it hasn't started overscrolling yet.
- val specForCurrentScene =
- when {
- progress <= 0f -> fromOverscrollSpec
- progress >= 1f -> toOverscrollSpec
- else -> null
- } ?: return true
-
- return specForCurrentScene.transformationSpec.transformations.isNotEmpty()
- }
-
- internal open fun interruptionProgress(
- layoutImpl: SceneTransitionLayoutImpl,
- ): Float {
- if (!layoutImpl.state.enableInterruptions) {
- return 0f
- }
-
- if (replacedTransition != null) {
- return replacedTransition.interruptionProgress(layoutImpl)
- }
-
- fun create(): Animatable<Float, AnimationVector1D> {
- val animatable = Animatable(1f, visibilityThreshold = ProgressVisibilityThreshold)
- layoutImpl.coroutineScope.launch {
- val swipeSpec = layoutImpl.state.transitions.defaultSwipeSpec
- val progressSpec =
- spring(
- stiffness = swipeSpec.stiffness,
- dampingRatio = swipeSpec.dampingRatio,
- visibilityThreshold = ProgressVisibilityThreshold,
- )
- animatable.animateTo(0f, progressSpec)
- }
-
- return animatable
- }
-
- val animatable = interruptionDecay ?: create().also { interruptionDecay = it }
- return animatable.value
- }
- }
-
- interface HasOverscrollProperties {
- /**
- * The position of the [Transition.toContent].
- *
- * Used to understand the direction of the overscroll.
- */
- val isUpOrLeft: Boolean
-
- /**
- * The relative orientation between [Transition.fromContent] and [Transition.toContent].
- *
- * Used to understand the orientation of the overscroll.
- */
- val orientation: Orientation
-
- /**
- * Scope which can be used in the Overscroll DSL to define a transformation based on the
- * distance between [Transition.fromContent] and [Transition.toContent].
- */
- val overscrollScope: OverscrollScope
-
- /**
- * The content (scene or overlay) around which the transition is currently bouncing. When
- * not `null`, this transition is currently oscillating around this content and will soon
- * settle to that content.
- */
- val bouncingContent: ContentKey?
-
- companion object {
- const val DistanceUnspecified = 0f
- }
- }
-}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
index 77de22c..22df34b 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
@@ -16,16 +16,31 @@
package com.android.compose.animation.scene.content.state
+import androidx.compose.animation.core.Animatable
+import androidx.compose.animation.core.AnimationVector1D
+import androidx.compose.animation.core.spring
+import androidx.compose.foundation.gestures.Orientation
import androidx.compose.runtime.Stable
+import com.android.compose.animation.scene.ContentKey
+import com.android.compose.animation.scene.OverscrollScope
+import com.android.compose.animation.scene.OverscrollSpecImpl
+import com.android.compose.animation.scene.ProgressVisibilityThreshold
import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.SceneTransitionLayoutImpl
+import com.android.compose.animation.scene.TransformationSpec
+import com.android.compose.animation.scene.TransformationSpecImpl
+import com.android.compose.animation.scene.TransitionKey
+import com.android.compose.animation.scene.transition.link.LinkedTransition
+import com.android.compose.animation.scene.transition.link.StateLink
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.launch
-/** The state associated to one or more scenes. */
-// TODO(b/353679003): Rename to SceneState.
+/** The state associated to a [SceneTransitionLayout] at some specific point in time. */
@Stable
-sealed interface TransitionState : ContentState<SceneKey> {
+sealed interface TransitionState {
/**
- * The current effective scene. If a new transition was triggered, it would start from this
- * scene.
+ * The current effective scene. If a new scene transition was triggered, it would start from
+ * this scene.
*
* For instance, when swiping from scene A to scene B, the [currentScene] is A when the swipe
* gesture starts, but then if the user flings their finger and commits the transition to scene
@@ -37,17 +52,216 @@
/** The scene [currentScene] is idle. */
data class Idle(
override val currentScene: SceneKey,
- ) : TransitionState, ContentState.Idle<SceneKey>(currentScene)
+ ) : TransitionState
- /** There is a transition animating between [fromScene] and [toScene]. */
- abstract class Transition(
- /** The scene this transition is starting from. Can't be the same as toScene */
- val fromScene: SceneKey,
+ sealed class Transition(
+ val fromContent: ContentKey,
+ val toContent: ContentKey,
+ val replacedTransition: Transition? = null,
+ ) : TransitionState {
+ /** A transition animating between [fromScene] and [toScene]. */
+ abstract class ChangeCurrentScene(
+ /** The scene this transition is starting from. Can't be the same as toScene */
+ val fromScene: SceneKey,
- /** The scene this transition is going to. Can't be the same as fromScene */
- val toScene: SceneKey,
+ /** The scene this transition is going to. Can't be the same as fromScene */
+ val toScene: SceneKey,
- /** The transition that `this` transition is replacing, if any. */
- replacedTransition: Transition? = null,
- ) : TransitionState, ContentState.Transition<SceneKey>(fromScene, toScene, replacedTransition)
+ /** The transition that `this` transition is replacing, if any. */
+ replacedTransition: Transition? = null,
+ ) : Transition(fromScene, toScene, replacedTransition)
+
+ /**
+ * The key of this transition. This should usually be null, but it can be specified to use a
+ * specific set of transformations associated to this transition.
+ */
+ open val key: TransitionKey? = null
+
+ /**
+ * The progress of the transition. This is usually in the `[0; 1]` range, but it can also be
+ * less than `0` or greater than `1` when using transitions with a spring AnimationSpec or
+ * when flinging quickly during a swipe gesture.
+ */
+ abstract val progress: Float
+
+ /** The current velocity of [progress], in progress units. */
+ abstract val progressVelocity: Float
+
+ /** Whether the transition was triggered by user input rather than being programmatic. */
+ abstract val isInitiatedByUserInput: Boolean
+
+ /** Whether user input is currently driving the transition. */
+ abstract val isUserInputOngoing: Boolean
+
+ /**
+ * The progress of the preview transition. This is usually in the `[0; 1]` range, but it can
+ * also be less than `0` or greater than `1` when using transitions with a spring
+ * AnimationSpec or when flinging quickly during a swipe gesture.
+ */
+ internal open val previewProgress: Float = 0f
+
+ /** The current velocity of [previewProgress], in progress units. */
+ internal open val previewProgressVelocity: Float = 0f
+
+ /** Whether the transition is currently in the preview stage */
+ internal open val isInPreviewStage: Boolean = false
+
+ /**
+ * The current [TransformationSpecImpl] and [OverscrollSpecImpl] associated to this
+ * transition.
+ *
+ * Important: These will be set exactly once, when this transition is
+ * [started][MutableSceneTransitionLayoutStateImpl.startTransition].
+ */
+ internal var transformationSpec: TransformationSpecImpl = TransformationSpec.Empty
+ internal var previewTransformationSpec: TransformationSpecImpl? = null
+ private var fromOverscrollSpec: OverscrollSpecImpl? = null
+ private var toOverscrollSpec: OverscrollSpecImpl? = null
+
+ /** The current [OverscrollSpecImpl], if this transition is currently overscrolling. */
+ internal val currentOverscrollSpec: OverscrollSpecImpl?
+ get() {
+ if (this !is HasOverscrollProperties) return null
+ val progress = progress
+ val bouncingContent = bouncingContent
+ return when {
+ progress < 0f || bouncingContent == fromContent -> fromOverscrollSpec
+ progress > 1f || bouncingContent == toContent -> toOverscrollSpec
+ else -> null
+ }
+ }
+
+ /**
+ * An animatable that animates from 1f to 0f. This will be used to nicely animate the sudden
+ * jump of values when this transitions interrupts another one.
+ */
+ private var interruptionDecay: Animatable<Float, AnimationVector1D>? = null
+
+ /** The map of active links that connects this transition to other transitions. */
+ internal val activeTransitionLinks = mutableMapOf<StateLink, LinkedTransition>()
+
+ init {
+ check(fromContent != toContent)
+ check(
+ replacedTransition == null ||
+ (replacedTransition.fromContent == fromContent &&
+ replacedTransition.toContent == toContent)
+ )
+ }
+
+ /**
+ * Whether we are transitioning. If [from] or [to] is empty, we will also check that they
+ * match the contents we are animating from and/or to.
+ */
+ fun isTransitioning(from: ContentKey? = null, to: ContentKey? = null): Boolean {
+ return (from == null || fromContent == from) && (to == null || toContent == to)
+ }
+
+ /** Whether we are transitioning from [content] to [other], or from [other] to [content]. */
+ fun isTransitioningBetween(content: ContentKey, other: ContentKey): Boolean {
+ return isTransitioning(from = content, to = other) ||
+ isTransitioning(from = other, to = content)
+ }
+
+ /**
+ * Force this transition to finish and animate to an [Idle] state.
+ *
+ * Important: Once this is called, the effective state of the transition should remain
+ * unchanged. For instance, in the case of a [TransitionState.Transition], its
+ * [currentScene][TransitionState.Transition.currentScene] should never change once [finish]
+ * is called.
+ *
+ * @return the [Job] that animates to the idle state. It can be used to wait until the
+ * animation is complete or cancel it to snap the animation. Calling [finish] multiple
+ * times will return the same [Job].
+ */
+ internal abstract fun finish(): Job
+
+ internal fun updateOverscrollSpecs(
+ fromSpec: OverscrollSpecImpl?,
+ toSpec: OverscrollSpecImpl?,
+ ) {
+ fromOverscrollSpec = fromSpec
+ toOverscrollSpec = toSpec
+ }
+
+ /** Returns if the [progress] value of this transition can go beyond range `[0; 1]` */
+ internal fun isWithinProgressRange(progress: Float): Boolean {
+ // If the properties are missing we assume that every [Transition] can overscroll
+ if (this !is HasOverscrollProperties) return true
+ // [OverscrollSpec] for the current scene, even if it hasn't started overscrolling yet.
+ val specForCurrentScene =
+ when {
+ progress <= 0f -> fromOverscrollSpec
+ progress >= 1f -> toOverscrollSpec
+ else -> null
+ } ?: return true
+
+ return specForCurrentScene.transformationSpec.transformations.isNotEmpty()
+ }
+
+ internal open fun interruptionProgress(
+ layoutImpl: SceneTransitionLayoutImpl,
+ ): Float {
+ if (!layoutImpl.state.enableInterruptions) {
+ return 0f
+ }
+
+ if (replacedTransition != null) {
+ return replacedTransition.interruptionProgress(layoutImpl)
+ }
+
+ fun create(): Animatable<Float, AnimationVector1D> {
+ val animatable = Animatable(1f, visibilityThreshold = ProgressVisibilityThreshold)
+ layoutImpl.coroutineScope.launch {
+ val swipeSpec = layoutImpl.state.transitions.defaultSwipeSpec
+ val progressSpec =
+ spring(
+ stiffness = swipeSpec.stiffness,
+ dampingRatio = swipeSpec.dampingRatio,
+ visibilityThreshold = ProgressVisibilityThreshold,
+ )
+ animatable.animateTo(0f, progressSpec)
+ }
+
+ return animatable
+ }
+
+ val animatable = interruptionDecay ?: create().also { interruptionDecay = it }
+ return animatable.value
+ }
+ }
+
+ interface HasOverscrollProperties {
+ /**
+ * The position of the [Transition.toContent].
+ *
+ * Used to understand the direction of the overscroll.
+ */
+ val isUpOrLeft: Boolean
+
+ /**
+ * The relative orientation between [Transition.fromContent] and [Transition.toContent].
+ *
+ * Used to understand the orientation of the overscroll.
+ */
+ val orientation: Orientation
+
+ /**
+ * Scope which can be used in the Overscroll DSL to define a transformation based on the
+ * distance between [Transition.fromContent] and [Transition.toContent].
+ */
+ val overscrollScope: OverscrollScope
+
+ /**
+ * The content (scene or overlay) around which the transition is currently bouncing. When
+ * not `null`, this transition is currently oscillating around this content and will soon
+ * settle to that content.
+ */
+ val bouncingContent: ContentKey?
+
+ companion object {
+ const val DistanceUnspecified = 0f
+ }
+ }
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt
index 538ce79..c5a3067c 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredSize.kt
@@ -22,7 +22,7 @@
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
/** Anchor the size of an element to the size of another element. */
internal class AnchoredSize(
@@ -36,7 +36,7 @@
content: ContentKey,
element: Element,
stateInContent: Element.State,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
value: IntSize,
): IntSize {
fun anchorSizeIn(content: ContentKey): IntSize {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt
index 258f541..05878c2 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/AnchoredTranslate.kt
@@ -23,7 +23,7 @@
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
/** Anchor the translation of an element to another element. */
internal class AnchoredTranslate(
@@ -35,7 +35,7 @@
content: ContentKey,
element: Element,
stateInContent: Element.State,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
value: Offset,
): Offset {
fun throwException(content: ContentKey?): Nothing {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt
index be8dac21..7f86479 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/DrawScale.kt
@@ -22,7 +22,7 @@
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.Scale
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
/**
* Scales the draw size of an element. Note this will only scale the draw inside of an element,
@@ -40,7 +40,7 @@
content: ContentKey,
element: Element,
stateInContent: Element.State,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
value: Scale,
): Scale {
return Scale(scaleX, scaleY, pivot)
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt
index d72e43a..a32c7dd 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/EdgeTranslate.kt
@@ -22,7 +22,7 @@
import com.android.compose.animation.scene.Element
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
/** Translate an element from an edge of the layout. */
internal class EdgeTranslate(
@@ -35,7 +35,7 @@
content: ContentKey,
element: Element,
stateInContent: Element.State,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
value: Offset
): Offset {
val sceneSize = layoutImpl.content(content).targetSize
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt
index 92ae30f8..4528eef 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Fade.kt
@@ -20,7 +20,7 @@
import com.android.compose.animation.scene.Element
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
/** Fade an element in or out. */
internal class Fade(
@@ -31,7 +31,7 @@
content: ContentKey,
element: Element,
stateInContent: Element.State,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
value: Float
): Float {
// Return the alpha value of [element] either when it starts fading in or when it finished
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt
index e8515dc..5f3fdaf 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/ScaleSize.kt
@@ -21,7 +21,7 @@
import com.android.compose.animation.scene.Element
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
import kotlin.math.roundToInt
/**
@@ -38,7 +38,7 @@
content: ContentKey,
element: Element,
stateInContent: Element.State,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
value: IntSize,
): IntSize {
return IntSize(
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
index eda8ede..505ad04 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt
@@ -25,7 +25,7 @@
import com.android.compose.animation.scene.Element
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
/** A transformation applied to one or more elements during a transition. */
sealed interface Transformation {
@@ -66,7 +66,7 @@
content: ContentKey,
element: Element,
stateInContent: Element.State,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
value: T,
): T
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt
index fab4ced..59bca50 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Translate.kt
@@ -24,7 +24,7 @@
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.OverscrollScope
import com.android.compose.animation.scene.SceneTransitionLayoutImpl
-import com.android.compose.animation.scene.content.state.ContentState
+import com.android.compose.animation.scene.content.state.TransitionState
internal class Translate(
override val matcher: ElementMatcher,
@@ -36,7 +36,7 @@
content: ContentKey,
element: Element,
stateInContent: Element.State,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
value: Offset,
): Offset {
return with(layoutImpl.density) {
@@ -58,13 +58,13 @@
content: ContentKey,
element: Element,
stateInContent: Element.State,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
value: Offset,
): Offset {
// As this object is created by OverscrollBuilderImpl and we retrieve the current
// OverscrollSpec only when the transition implements HasOverscrollProperties, we can assume
// that this method was invoked after performing this check.
- val overscrollProperties = transition as ContentState.HasOverscrollProperties
+ val overscrollProperties = transition as TransitionState.HasOverscrollProperties
return Offset(
x = value.x + overscrollProperties.overscrollScope.x(),
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt
index 23bcf10..89b0040 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/LinkedTransition.kt
@@ -23,11 +23,11 @@
/** A linked transition which is driven by a [originalTransition]. */
internal class LinkedTransition(
- private val originalTransition: TransitionState.Transition,
+ private val originalTransition: TransitionState.Transition.ChangeCurrentScene,
fromScene: SceneKey,
toScene: SceneKey,
override val key: TransitionKey? = null,
-) : TransitionState.Transition(fromScene, toScene) {
+) : TransitionState.Transition.ChangeCurrentScene(fromScene, toScene) {
override val currentScene: SceneKey
get() {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/StateLink.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/StateLink.kt
index c0c40dd..c29bf21 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/StateLink.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transition/link/StateLink.kt
@@ -49,7 +49,9 @@
error("From and To can't be the same")
}
- internal fun isMatchingLink(transition: TransitionState.Transition): Boolean {
+ internal fun isMatchingLink(
+ transition: TransitionState.Transition.ChangeCurrentScene,
+ ): Boolean {
return (sourceFrom == null || sourceFrom == transition.fromScene) &&
(sourceTo == null || sourceTo == transition.toScene)
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index 6360f85..72a16b7 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -182,7 +182,7 @@
progress: Float? = null,
isUserInputOngoing: Boolean? = null
): Transition {
- val transition = assertThat(transitionState).isTransition()
+ val transition = assertThat(transitionState).isSceneTransition()
currentScene?.let { assertThat(transition).hasCurrentScene(it) }
fromScene?.let { assertThat(transition).hasFromScene(it) }
toScene?.let { assertThat(transition).hasToScene(it) }
@@ -1075,7 +1075,7 @@
val middle = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f)
val dragController = onDragStarted(startedPosition = middle, overSlop = up(0.5f))
- val transition = assertThat(transitionState).isTransition()
+ val transition = assertThat(transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
assertThat(transition).hasProgress(0.5f)
@@ -1101,7 +1101,7 @@
val middle = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f)
val dragController = onDragStarted(startedPosition = middle, overSlop = down(0.5f))
- val transition = assertThat(transitionState).isTransition()
+ val transition = assertThat(transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneC)
assertThat(transition).hasProgress(0.5f)
@@ -1127,7 +1127,7 @@
val middle = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f)
val dragController = onDragStarted(startedPosition = middle, overSlop = up(1.5f))
- val transition = assertThat(transitionState).isTransition()
+ val transition = assertThat(transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
assertThat(transition).hasProgress(1.5f)
@@ -1154,7 +1154,7 @@
val middle = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f)
val dragController = onDragStarted(startedPosition = middle, overSlop = down(1.5f))
- val transition = assertThat(transitionState).isTransition()
+ val transition = assertThat(transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneC)
assertThat(transition).hasProgress(1.5f)
@@ -1182,7 +1182,7 @@
val middle = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f)
val dragController = onDragStarted(startedPosition = middle, overSlop = down(1f))
- val transition = assertThat(transitionState).isTransition()
+ val transition = assertThat(transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
assertThat(transition).hasProgress(-1f)
@@ -1210,7 +1210,7 @@
val middle = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f)
val dragController = onDragStarted(startedPosition = middle, overSlop = up(1f))
- val transition = assertThat(transitionState).isTransition()
+ val transition = assertThat(transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneC)
assertThat(transition).hasProgress(-1f)
@@ -1267,12 +1267,12 @@
@Test
fun interceptingTransitionReplacesCurrentTransition() = runGestureTest {
val controller = onDragStarted(overSlop = up(fractionOfScreen = 0.5f))
- val transition = assertThat(layoutState.transitionState).isTransition()
+ val transition = assertThat(layoutState.transitionState).isSceneTransition()
controller.onDragStopped(velocity = 0f)
// Intercept the transition.
onDragStartedImmediately()
- val newTransition = assertThat(layoutState.transitionState).isTransition()
+ val newTransition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(newTransition).isNotSameInstanceAs(transition)
assertThat(newTransition.replacedTransition).isSameInstanceAs(transition)
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
index 20b9b49..682fe95 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt
@@ -735,7 +735,7 @@
val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
fooElement.assertTopPositionInRootIsEqualTo(0.dp)
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).isNotNull()
assertThat(transition).hasProgress(0.5f)
assertThat(animatedFloat).isEqualTo(50f)
@@ -822,7 +822,7 @@
moveBy(Offset(0f, touchSlop + layoutHeight.toPx() * 0.5f), delayMillis = 1_000)
}
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasOverscrollSpec()
assertThat(transition).hasProgress(-0.5f)
fooElement.assertTopPositionInRootIsEqualTo(overscrollTranslateY * 0.5f)
@@ -905,7 +905,7 @@
}
}
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasProgress(0.5f)
fooElement.assertTopPositionInRootIsEqualTo(translateY * 0.5f)
}
@@ -939,7 +939,7 @@
moveBy(Offset(0f, layoutHeight.toPx() * 0.5f), delayMillis = 1_000)
}
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(animatedFloat).isEqualTo(100f)
// Scroll 150% (100% scroll + 50% overscroll)
@@ -992,7 +992,7 @@
moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000)
}
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(animatedFloat).isEqualTo(100f)
// Scroll 200% (100% scroll + 100% overscroll)
@@ -1039,7 +1039,7 @@
moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000)
}
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(animatedFloat).isEqualTo(100f)
// Scroll 200% (100% scroll + 100% overscroll)
@@ -1083,7 +1083,7 @@
moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000)
}
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(animatedFloat).isEqualTo(100f)
// Scroll 200% (100% scroll + 100% overscroll)
@@ -1143,7 +1143,7 @@
moveBy(Offset(0f, layoutHeight.toPx() * 0.5f), delayMillis = 1_000)
}
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
// Scroll 150% (100% scroll + 50% overscroll)
assertThat(transition).hasProgress(1.5f)
@@ -1160,7 +1160,7 @@
assertThat(transition.progress).isLessThan(1f)
assertThat(transition).hasOverscrollSpec()
- assertThat(transition).hasBouncingScene(transition.toScene)
+ assertThat(transition).hasBouncingContent(transition.toContent)
assertThat(animatedFloat).isEqualTo(100f)
}
@@ -1243,13 +1243,15 @@
val transitions = state.currentTransitions
assertThat(transitions).hasSize(2)
- assertThat(transitions[0]).hasFromScene(SceneA)
- assertThat(transitions[0]).hasToScene(SceneB)
- assertThat(transitions[0]).hasProgress(0f)
+ val firstTransition = assertThat(transitions[0]).isSceneTransition()
+ assertThat(firstTransition).hasFromScene(SceneA)
+ assertThat(firstTransition).hasToScene(SceneB)
+ assertThat(firstTransition).hasProgress(0f)
- assertThat(transitions[1]).hasFromScene(SceneB)
- assertThat(transitions[1]).hasToScene(SceneC)
- assertThat(transitions[1]).hasProgress(0f)
+ val secondTransition = assertThat(transitions[1]).isSceneTransition()
+ assertThat(secondTransition).hasFromScene(SceneB)
+ assertThat(secondTransition).hasToScene(SceneC)
+ assertThat(secondTransition).hasProgress(0f)
// First frame: both are at x = 0dp. For the whole transition, Foo is at y = 0dp and Bar is
// at y = layoutSize - elementSoze = 100dp.
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt
index ca72181..f4e60a2 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/InterruptionHandlerTest.kt
@@ -69,7 +69,7 @@
interruptionHandler =
object : InterruptionHandler {
override fun onInterruption(
- interrupted: TransitionState.Transition,
+ interrupted: TransitionState.Transition.ChangeCurrentScene,
newTargetScene: SceneKey
): InterruptionResult {
return InterruptionResult(
@@ -104,7 +104,7 @@
interruptionHandler =
object : InterruptionHandler {
override fun onInterruption(
- interrupted: TransitionState.Transition,
+ interrupted: TransitionState.Transition.ChangeCurrentScene,
newTargetScene: SceneKey
): InterruptionResult {
return InterruptionResult(
@@ -198,7 +198,7 @@
companion object {
val FromToCurrentTriple =
Correspondence.transforming(
- { transition: TransitionState.Transition? ->
+ { transition: TransitionState.Transition.ChangeCurrentScene? ->
Triple(transition?.fromScene, transition?.toScene, transition?.currentScene)
},
"(from, to, current) triple"
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
index 520e759..b7f50fd 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
@@ -45,7 +45,6 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
-import com.android.compose.animation.scene.content.state.ContentState
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.test.assertSizeIsEqualTo
@@ -160,11 +159,11 @@
override fun contentDuringTransition(
element: ElementKey,
- transition: ContentState.Transition<*>,
+ transition: TransitionState.Transition,
fromContentZIndex: Float,
toContentZIndex: Float
): ContentKey {
- transition as TransitionState.Transition
+ transition as TransitionState.Transition.ChangeCurrentScene
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
assertThat(fromContentZIndex).isEqualTo(0)
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt
index ccefe3d..d58a0a3 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/NestedScrollToSceneTest.kt
@@ -125,7 +125,7 @@
scrollUp(percent = 0.5f)
// STL will start a transition with the remaining scroll
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasProgress(0.5f)
scrollUp(percent = 1f)
@@ -156,7 +156,7 @@
// Start a new gesture
pointerDownAndScrollTouchSlop()
scrollUp(percent = 0.5f)
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasProgress(0.5f)
pointerUp()
@@ -181,7 +181,7 @@
// Reach the end of the scrollable element
canScroll = false
scrollUp(percent = 0.5f)
- val transition1 = assertThat(state.transitionState).isTransition()
+ val transition1 = assertThat(state.transitionState).isSceneTransition()
assertThat(transition1).hasProgress(0.5f)
pointerUp()
@@ -192,7 +192,7 @@
// Start a new gesture
pointerDownAndScrollTouchSlop()
scrollUp(percent = 0.5f)
- val transition2 = assertThat(state.transitionState).isTransition()
+ val transition2 = assertThat(state.transitionState).isSceneTransition()
assertThat(transition2).hasProgress(0.5f)
pointerUp()
@@ -215,7 +215,7 @@
// Reach the end of the scrollable element
canScroll = false
scrollUp(percent = 0.5f)
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasProgress(0.5f)
pointerUp()
@@ -244,7 +244,7 @@
scrollUp(percent = 0.5f)
// EdgeAlways always consume the remaining scroll, EdgeNoPreview does not.
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasProgress(0.5f)
}
@@ -278,7 +278,7 @@
scrollUp(percent = 0.2f)
// STL can only start the transition if it has reset the amount of scroll consumed.
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasProgress(0.2f)
}
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/PredictiveBackHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/PredictiveBackHandlerTest.kt
index 0eaecb0..00c7588 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/PredictiveBackHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/PredictiveBackHandlerTest.kt
@@ -76,7 +76,7 @@
dispatcher.dispatchOnBackProgressed(backEvent(progress = 0.4f))
}
- val transition = assertThat(layoutState.transitionState).isTransition()
+ val transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
assertThat(transition).hasProgress(0.4f)
@@ -124,7 +124,7 @@
dispatcher.dispatchOnBackProgressed(backEvent(progress = 0.4f))
}
- val transition = assertThat(layoutState.transitionState).isTransition()
+ val transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
assertThat(transition).hasPreviewProgress(0.4f)
@@ -178,13 +178,13 @@
val dispatcher = rule.activity.onBackPressedDispatcher
rule.runOnUiThread { dispatcher.dispatchOnBackStarted(backEvent()) }
- val predictiveTransition = assertThat(layoutState.transitionState).isTransition()
+ val predictiveTransition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(predictiveTransition).hasFromScene(SceneA)
assertThat(predictiveTransition).hasToScene(SceneB)
// Start a new transition to C.
rule.runOnUiThread { layoutState.setTargetScene(SceneC, coroutineScope) }
- val newTransition = assertThat(layoutState.transitionState).isTransition()
+ val newTransition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(newTransition).hasFromScene(SceneA)
assertThat(newTransition).hasToScene(SceneC)
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
index c8ac580..3422a8e 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
@@ -478,7 +478,7 @@
overscroll(SceneB, Orientation.Vertical) { fade(TestElements.Foo) }
}
)
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasNoOverscrollSpec()
// overscroll for SceneA is NOT defined
@@ -510,7 +510,7 @@
}
)
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasNoOverscrollSpec()
// overscroll for SceneA is defined
@@ -539,7 +539,7 @@
sceneTransitions = transitions {}
)
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasNoOverscrollSpec()
// overscroll for SceneA is NOT defined
@@ -642,7 +642,7 @@
// Transition to B.
state.setTargetScene(SceneB, coroutineScope = this)
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasCurrentScene(SceneB)
// Snap to C.
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
index 84bcc28f..e97c27e 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutTest.kt
@@ -179,7 +179,7 @@
// Change the current scene.
currentScene = SceneB
- val transition = assertThat(layoutState.transitionState).isTransition()
+ val transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
assertThat(transition).hasProgress(0f)
@@ -241,7 +241,7 @@
// 100.dp. We pause at the middle of the transition, so it should now be 75.dp given that we
// use a linear interpolator. Foo was at (x = layoutSize - 50dp, y = 0) in SceneA and is
// going to (x = 0, y = 0), so the offset should now be half what it was.
- var transition = assertThat(layoutState.transitionState).isTransition()
+ var transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasProgress(0.5f)
sharedFoo.assertWidthIsEqualTo(75.dp)
sharedFoo.assertHeightIsEqualTo(75.dp)
@@ -269,7 +269,7 @@
val expectedSize = 100.dp + (150.dp - 100.dp) * interpolatedProgress
sharedFoo = rule.onNode(isElement(TestElements.Foo, SceneC))
- transition = assertThat(layoutState.transitionState).isTransition()
+ transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasProgress(interpolatedProgress)
sharedFoo.assertWidthIsEqualTo(expectedSize)
sharedFoo.assertHeightIsEqualTo(expectedSize)
@@ -399,7 +399,7 @@
rule.mainClock.advanceTimeBy(duration / 2)
rule.waitForIdle()
- var transition = assertThat(state.transitionState).isTransition()
+ var transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasProgress(0.5f)
// A and B are composed.
@@ -412,7 +412,7 @@
rule.mainClock.advanceTimeByFrame()
rule.waitForIdle()
- transition = assertThat(state.transitionState).isTransition()
+ transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasProgress(0f)
// A, B and C are composed.
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
index 04a9380..06799bc 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
@@ -155,7 +155,7 @@
// We should be at a progress = 55dp / LayoutWidth given that we use the layout size in
// the gesture axis as swipe distance.
- var transition = assertThat(layoutState.transitionState).isTransition()
+ var transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
assertThat(transition).hasCurrentScene(SceneA)
@@ -165,7 +165,7 @@
// Release the finger. We should now be animating back to A (currentScene = SceneA) given
// that 55dp < positional threshold.
rule.onRoot().performTouchInput { up() }
- transition = assertThat(layoutState.transitionState).isTransition()
+ transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
assertThat(transition).hasCurrentScene(SceneA)
@@ -185,7 +185,7 @@
}
// Drag is in progress, so currentScene = SceneA and progress = 56dp / LayoutHeight
- transition = assertThat(layoutState.transitionState).isTransition()
+ transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(TestScenes.SceneC)
assertThat(transition).hasCurrentScene(SceneA)
@@ -195,7 +195,7 @@
// Release the finger. We should now be animating to C (currentScene = SceneC) given
// that 56dp >= positional threshold.
rule.onRoot().performTouchInput { up() }
- transition = assertThat(layoutState.transitionState).isTransition()
+ transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(TestScenes.SceneC)
assertThat(transition).hasCurrentScene(TestScenes.SceneC)
@@ -236,7 +236,7 @@
// We should be animating back to A (currentScene = SceneA) given that 124 dp/s < velocity
// threshold.
- var transition = assertThat(layoutState.transitionState).isTransition()
+ var transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
assertThat(transition).hasCurrentScene(SceneA)
@@ -260,7 +260,7 @@
}
// We should be animating to C (currentScene = SceneC).
- transition = assertThat(layoutState.transitionState).isTransition()
+ transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(TestScenes.SceneC)
assertThat(transition).hasCurrentScene(TestScenes.SceneC)
@@ -297,7 +297,7 @@
}
// We are transitioning to B because we used 2 fingers.
- val transition = assertThat(layoutState.transitionState).isTransition()
+ val transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(TestScenes.SceneC)
assertThat(transition).hasToScene(SceneB)
@@ -332,7 +332,7 @@
}
// We are transitioning to B (and not A) because we started from the top edge.
- var transition = assertThat(layoutState.transitionState).isTransition()
+ var transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(TestScenes.SceneC)
assertThat(transition).hasToScene(SceneB)
@@ -350,7 +350,7 @@
}
// We are transitioning to B (and not A) because we started from the left edge.
- transition = assertThat(layoutState.transitionState).isTransition()
+ transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(TestScenes.SceneC)
assertThat(transition).hasToScene(SceneB)
@@ -406,7 +406,7 @@
}
// We should be at 50%
- val transition = assertThat(layoutState.transitionState).isTransition()
+ val transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).isNotNull()
assertThat(transition).hasProgress(0.5f)
}
@@ -427,7 +427,7 @@
}
// We should still correctly compute that we are swiping down to scene C.
- var transition = assertThat(layoutState.transitionState).isTransition()
+ var transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasToScene(TestScenes.SceneC)
// Release the finger, animating back to scene A.
@@ -443,7 +443,7 @@
}
// We should still correctly compute that we are swiping up to scene B.
- transition = assertThat(layoutState.transitionState).isTransition()
+ transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasToScene(SceneB)
// Release the finger, animating back to scene A.
@@ -459,7 +459,7 @@
}
// We should still correctly compute that we are swiping down to scene B.
- transition = assertThat(layoutState.transitionState).isTransition()
+ transition = assertThat(layoutState.transitionState).isSceneTransition()
assertThat(transition).hasToScene(SceneB)
}
@@ -597,7 +597,7 @@
}
rule.waitForIdle()
- val transition = assertThat(state.transitionState).isTransition()
+ val transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
assertThat(transition).hasProgress(0.5f, tolerance = 0.01f)
@@ -686,7 +686,7 @@
}
// Scene B should come from the right (end) edge.
- var transition = assertThat(state.transitionState).isTransition()
+ var transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
rule
@@ -707,7 +707,7 @@
}
// Scene C should come from the left (start) edge.
- transition = assertThat(state.transitionState).isTransition()
+ transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneC)
rule
@@ -761,7 +761,7 @@
}
// Scene C should come from the right (start) edge.
- var transition = assertThat(state.transitionState).isTransition()
+ var transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneC)
rule
@@ -782,7 +782,7 @@
}
// Scene C should come from the left (end) edge.
- transition = assertThat(state.transitionState).isTransition()
+ transition = assertThat(state.transitionState).isSceneTransition()
assertThat(transition).hasFromScene(SceneA)
assertThat(transition).hasToScene(SceneB)
rule
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt
index e4e4108..1f7fe37 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/Transition.kt
@@ -17,7 +17,6 @@
package com.android.compose.animation.scene
import androidx.compose.foundation.gestures.Orientation
-import com.android.compose.animation.scene.content.state.ContentState
import com.android.compose.animation.scene.content.state.TransitionState
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
@@ -43,10 +42,10 @@
orientation: Orientation = Orientation.Horizontal,
onFinish: ((TransitionState.Transition) -> Job)? = null,
replacedTransition: TransitionState.Transition? = null,
-): TransitionState.Transition {
+): TransitionState.Transition.ChangeCurrentScene {
return object :
- TransitionState.Transition(from, to, replacedTransition),
- ContentState.HasOverscrollProperties {
+ TransitionState.Transition.ChangeCurrentScene(from, to, replacedTransition),
+ TransitionState.HasOverscrollProperties {
override val currentScene: SceneKey
get() = current()
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt
index a12ab78..a98bd76 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/subjects/TransitionStateSubject.kt
@@ -16,9 +16,9 @@
package com.android.compose.animation.scene.subjects
+import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.OverscrollSpec
import com.android.compose.animation.scene.SceneKey
-import com.android.compose.animation.scene.content.state.ContentState
import com.android.compose.animation.scene.content.state.TransitionState
import com.google.common.truth.Fact.simpleFact
import com.google.common.truth.FailureMetadata
@@ -31,9 +31,9 @@
return Truth.assertAbout(TransitionStateSubject.transitionStates()).that(state)
}
-/** Assert on a [TransitionState.Transition]. */
-fun assertThat(transitions: TransitionState.Transition): TransitionSubject {
- return Truth.assertAbout(TransitionSubject.transitions()).that(transitions)
+/** Assert on a [TransitionState.Transition.ChangeCurrentScene]. */
+fun assertThat(transition: TransitionState.Transition.ChangeCurrentScene): SceneTransitionSubject {
+ return Truth.assertAbout(SceneTransitionSubject.transitions()).that(transition)
}
class TransitionStateSubject
@@ -53,12 +53,14 @@
return actual as TransitionState.Idle
}
- fun isTransition(): TransitionState.Transition {
- if (actual !is TransitionState.Transition) {
- failWithActual(simpleFact("expected to be TransitionState.Transition"))
+ fun isSceneTransition(): TransitionState.Transition.ChangeCurrentScene {
+ if (actual !is TransitionState.Transition.ChangeCurrentScene) {
+ failWithActual(
+ simpleFact("expected to be TransitionState.Transition.ChangeCurrentScene")
+ )
}
- return actual as TransitionState.Transition
+ return actual as TransitionState.Transition.ChangeCurrentScene
}
companion object {
@@ -68,10 +70,10 @@
}
}
-class TransitionSubject
+class SceneTransitionSubject
private constructor(
metadata: FailureMetadata,
- private val actual: TransitionState.Transition,
+ private val actual: TransitionState.Transition.ChangeCurrentScene,
) : Subject(metadata, actual) {
fun hasCurrentScene(sceneKey: SceneKey) {
check("currentScene").that(actual.currentScene).isEqualTo(sceneKey)
@@ -132,19 +134,21 @@
check("currentOverscrollSpec").that(actual.currentOverscrollSpec).isNull()
}
- fun hasBouncingScene(scene: SceneKey) {
- if (actual !is ContentState.HasOverscrollProperties) {
+ fun hasBouncingContent(content: ContentKey) {
+ val actual = actual
+ if (actual !is TransitionState.HasOverscrollProperties) {
failWithActual(simpleFact("expected to be ContentState.HasOverscrollProperties"))
}
check("bouncingContent")
- .that((actual as ContentState.HasOverscrollProperties).bouncingContent)
- .isEqualTo(scene)
+ .that((actual as TransitionState.HasOverscrollProperties).bouncingContent)
+ .isEqualTo(content)
}
companion object {
- fun transitions() = Factory { metadata, actual: TransitionState.Transition ->
- TransitionSubject(metadata, actual)
- }
+ fun transitions() =
+ Factory { metadata, actual: TransitionState.Transition.ChangeCurrentScene ->
+ SceneTransitionSubject(metadata, actual)
+ }
}
}