summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt1
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt34
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PunchHole.kt75
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt7
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt13
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt6
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt6
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDsl.kt15
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt5
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/transformation/Transformation.kt14
10 files changed, 74 insertions, 102 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt
index fadbdce80cbf..22dc0aee45b4 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt
@@ -10,7 +10,6 @@ import com.android.systemui.shade.ui.composable.Shade
fun TransitionBuilder.lockscreenToShadeTransition() {
spec = tween(durationMillis = 500)
- punchHole(Shade.Elements.QuickSettings, bounds = Shade.Elements.Scrim, Shade.Shapes.Scrim)
translate(Shade.Elements.Scrim, Edge.Top, startsOutsideLayoutBounds = false)
fractionRange(end = 0.5f) {
fade(Shade.Elements.ScrimBackground)
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 3b999e304491..cf4aa625628a 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
@@ -161,7 +161,6 @@ internal fun Modifier.element(
}
}
}
- .modifierTransformations(layoutImpl, scene, element, sceneValues)
.intermediateLayout { measurable, constraints ->
val placeable =
measure(layoutImpl, scene, element, sceneValues, measurable, constraints)
@@ -332,39 +331,6 @@ internal fun sharedElementTransformation(
}
/**
- * Chain the [com.android.compose.animation.scene.transformation.ModifierTransformation] applied
- * throughout the current transition, if any.
- */
-private fun Modifier.modifierTransformations(
- layoutImpl: SceneTransitionLayoutImpl,
- scene: Scene,
- element: Element,
- sceneValues: Element.TargetValues,
-): Modifier {
- when (val state = layoutImpl.state.transitionState) {
- is TransitionState.Idle -> return this
- is TransitionState.Transition -> {
- val fromScene = state.fromScene
- val toScene = state.toScene
- if (fromScene == toScene) {
- // Same as idle.
- return this
- }
-
- return layoutImpl.transitions
- .transitionSpec(fromScene, state.toScene)
- .transformations(element.key, scene.key)
- .modifier
- .fold(this) { modifier, transformation ->
- with(transformation) {
- modifier.transform(layoutImpl, scene, element, sceneValues)
- }
- }
- }
- }
-}
-
-/**
* Whether the element is opaque or not.
*
* Important: The logic here should closely match the logic in [elementAlpha]. Note that we don't
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PunchHole.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PunchHole.kt
index a8d364060e88..560e92becba5 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PunchHole.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/PunchHole.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2023 The Android Open Source Project
+ * Copyright (C) 2023 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.
@@ -17,7 +17,6 @@
package com.android.compose.animation.scene
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.geometry.toRect
@@ -28,48 +27,68 @@ import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.drawOutline
+import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.withSaveLayer
+import androidx.compose.ui.node.DrawModifierNode
+import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.toSize
-import com.android.compose.animation.scene.transformation.ModifierTransformation
-/** Punch a hole in an element using the bounds of another element and a given [shape]. */
-internal class PunchHole(
- override val matcher: ElementMatcher,
+internal fun Modifier.punchHole(
+ layoutImpl: SceneTransitionLayoutImpl,
+ element: ElementKey,
+ bounds: ElementKey,
+ shape: Shape,
+): Modifier = this.then(PunchHoleElement(layoutImpl, element, bounds, shape))
+
+private data class PunchHoleElement(
+ private val layoutImpl: SceneTransitionLayoutImpl,
+ private val element: ElementKey,
private val bounds: ElementKey,
private val shape: Shape,
-) : ModifierTransformation {
+) : ModifierNodeElement<PunchHoleNode>() {
+ override fun create(): PunchHoleNode = PunchHoleNode(layoutImpl, element, bounds, shape)
+ override fun update(node: PunchHoleNode) {
+ node.layoutImpl = layoutImpl
+ node.element = element
+ node.bounds = bounds
+ node.shape = shape
+ }
+}
+
+private class PunchHoleNode(
+ var layoutImpl: SceneTransitionLayoutImpl,
+ var element: ElementKey,
+ var bounds: ElementKey,
+ var shape: Shape,
+) : Modifier.Node(), DrawModifierNode {
private var lastSize: Size = Size.Unspecified
private var lastLayoutDirection: LayoutDirection = LayoutDirection.Ltr
private var lastOutline: Outline? = null
- override fun Modifier.transform(
- layoutImpl: SceneTransitionLayoutImpl,
- scene: Scene,
- element: Element,
- sceneValues: Element.TargetValues,
- ): Modifier {
- return drawWithContent {
- val bounds = layoutImpl.elements[bounds]
- if (
- bounds == null ||
- bounds.lastSharedValues.size == Element.SizeUnspecified ||
- bounds.lastSharedValues.offset == Offset.Unspecified
- ) {
+ override fun ContentDrawScope.draw() {
+ val bounds = layoutImpl.elements[bounds]
+
+ if (
+ bounds == null ||
+ bounds.lastSharedValues.size == Element.SizeUnspecified ||
+ bounds.lastSharedValues.offset == Offset.Unspecified
+ ) {
+ drawContent()
+ return
+ }
+
+ val element = layoutImpl.elements.getValue(element)
+ drawIntoCanvas { canvas ->
+ canvas.withSaveLayer(size.toRect(), Paint()) {
drawContent()
- return@drawWithContent
- }
- drawIntoCanvas { canvas ->
- canvas.withSaveLayer(size.toRect(), Paint()) {
- drawContent()
- val offset = bounds.lastSharedValues.offset - element.lastSharedValues.offset
- translate(offset.x, offset.y) { drawHole(bounds) }
- }
+ val offset = bounds.lastSharedValues.offset - element.lastSharedValues.offset
+ translate(offset.x, offset.y) { drawHole(bounds) }
}
}
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
index 857a596a1404..f5b271019748 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
@@ -27,6 +27,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.layout.intermediateLayout
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.IntSize
@@ -130,4 +131,10 @@ private class SceneScopeImpl(
) {
MovableElement(layoutImpl, scene, key, modifier, content)
}
+
+ override fun Modifier.punchHole(
+ element: ElementKey,
+ bounds: ElementKey,
+ shape: Shape
+ ): Modifier = punchHole(layoutImpl, element, bounds, shape)
}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index 30d13dfa3f70..1f698ff00141 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -23,6 +23,7 @@ import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.platform.LocalDensity
@@ -177,6 +178,18 @@ interface SceneScope {
lerp: (start: T, stop: T, fraction: Float) -> T,
canOverflow: Boolean,
): State<T>
+
+ /**
+ * Punch a hole in this [element] using the bounds of [bounds] in [scene] and the given [shape].
+ *
+ * Punching a hole in an element will "remove" any pixel drawn by that element in the hole area.
+ * This can be used to make content drawn below an opaque element visible. For example, if we
+ * have [this lockscreen scene](http://shortn/_VYySFnJDhN) drawn below
+ * [this shade scene](http://shortn/_fpxGUk0Rg7) and punch a hole in the latter using the big
+ * clock time bounds and a RoundedCornerShape(10dp), [this](http://shortn/_qt80IvORFj) would be
+ * the result.
+ */
+ fun Modifier.punchHole(element: ElementKey, bounds: ElementKey, shape: Shape): Modifier
}
// TODO(b/291053742): Add animateSharedValueAsState(targetValue) without any ValueKey and ElementKey
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 64c9775a386e..6a87662135de 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
@@ -46,6 +46,12 @@ class SceneTransitionLayoutState(initialScene: SceneKey) {
return (from == null || transition.fromScene == from) &&
(to == null || transition.toScene == to)
}
+
+ /** Whether we are transitioning from [scene] to [other], or from [other] to [scene]. */
+ fun isTransitioningBetween(scene: SceneKey, other: SceneKey): Boolean {
+ return isTransitioning(from = scene, to = other) ||
+ isTransitioning(from = other, to = scene)
+ }
}
sealed interface TransitionState {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
index 2172ed300a33..828dff27637b 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
@@ -27,7 +27,6 @@ import com.android.compose.animation.scene.transformation.AnchoredTranslate
import com.android.compose.animation.scene.transformation.DrawScale
import com.android.compose.animation.scene.transformation.EdgeTranslate
import com.android.compose.animation.scene.transformation.Fade
-import com.android.compose.animation.scene.transformation.ModifierTransformation
import com.android.compose.animation.scene.transformation.PropertyTransformation
import com.android.compose.animation.scene.transformation.RangedPropertyTransformation
import com.android.compose.animation.scene.transformation.ScaleSize
@@ -122,7 +121,6 @@ data class TransitionSpec(
scene: SceneKey,
): ElementTransformations {
var shared: SharedElementTransformation? = null
- val modifier = mutableListOf<ModifierTransformation>()
var offset: PropertyTransformation<Offset>? = null
var size: PropertyTransformation<IntSize>? = null
var drawScale: PropertyTransformation<Scale>? = null
@@ -166,12 +164,11 @@ data class TransitionSpec(
throwIfNotNull(shared, element, name = "shared")
shared = transformation
}
- is ModifierTransformation -> modifier.add(transformation)
is PropertyTransformation<*> -> onPropertyTransformation(transformation)
}
}
- return ElementTransformations(shared, modifier, offset, size, drawScale, alpha)
+ return ElementTransformations(shared, offset, size, drawScale, alpha)
}
private fun throwIfNotNull(
@@ -188,7 +185,6 @@ data class TransitionSpec(
/** The transformations of an element during a transition. */
internal class ElementTransformations(
val shared: SharedElementTransformation?,
- val modifier: List<ModifierTransformation>,
val offset: PropertyTransformation<Offset>?,
val size: PropertyTransformation<IntSize>?,
val drawScale: PropertyTransformation<Scale>?,
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 ca66dff5e231..f820074ec3d1 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
@@ -18,8 +18,6 @@ package com.android.compose.animation.scene
import androidx.compose.animation.core.AnimationSpec
import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.RectangleShape
-import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
@@ -131,19 +129,6 @@ interface TransitionBuilder : PropertyTransformationBuilder {
)
/**
- * Punch a hole in the element(s) matching [matcher] that has the same bounds as [bounds] and
- * using the given [shape].
- *
- * Punching a hole in an element will "remove" any pixel drawn by that element in the hole area.
- * This can be used to make content drawn below an opaque element visible. For example, if we
- * have [this lockscreen scene](http://shortn/_VYySFnJDhN) drawn below
- * [this shade scene](http://shortn/_fpxGUk0Rg7) and punch a hole in the latter using the big
- * clock time bounds and a RoundedCornerShape(10dp), [this](http://shortn/_qt80IvORFj) would be
- * the result.
- */
- fun punchHole(matcher: ElementMatcher, bounds: ElementKey, shape: Shape = RectangleShape)
-
- /**
* Adds the transformations in [builder] but in reversed order. This allows you to partially
* reuse the definition of the transition from scene `Foo` to scene `Bar` inside the definition
* of the transition from scene `Bar` to scene `Foo`.
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
index bcb20913e554..8c0a5a394331 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt
@@ -22,7 +22,6 @@ import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.VectorConverter
import androidx.compose.animation.core.spring
import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.Dp
import com.android.compose.animation.scene.transformation.AnchoredSize
import com.android.compose.animation.scene.transformation.AnchoredTranslate
@@ -92,10 +91,6 @@ internal class TransitionBuilderImpl : TransitionBuilder {
spec.vectorize(Float.VectorConverter).durationMillis
}
- override fun punchHole(matcher: ElementMatcher, bounds: ElementKey, shape: Shape) {
- transformations.add(PunchHole(matcher, bounds, shape))
- }
-
override fun reversed(builder: TransitionBuilder.() -> Unit) {
reversed = true
builder()
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 0db8469466ef..206935558179 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
@@ -16,7 +16,6 @@
package com.android.compose.animation.scene.transformation
-import androidx.compose.ui.Modifier
import com.android.compose.animation.scene.Element
import com.android.compose.animation.scene.ElementMatcher
import com.android.compose.animation.scene.Scene
@@ -52,19 +51,6 @@ internal class SharedElementTransformation(
internal val scenePicker: SharedElementScenePicker,
) : Transformation
-/** A transformation that is applied on the element during the whole transition. */
-internal interface ModifierTransformation : Transformation {
- /** Apply the transformation to [element]. */
- // TODO(b/290184746): Figure out a public API for custom transformations that don't have access
- // to these internal classes.
- fun Modifier.transform(
- layoutImpl: SceneTransitionLayoutImpl,
- scene: Scene,
- element: Element,
- sceneValues: Element.TargetValues,
- ): Modifier
-}
-
/** A transformation that changes the value of an element property, like its size or offset. */
internal sealed interface PropertyTransformation<T> : Transformation {
/**