summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2024-08-21 10:50:56 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-08-21 10:50:56 +0000
commit9170c9391f73b2e2215dcbf11ca31d0875e2177a (patch)
treea244787868ff500b5c413d154266d97c784d8f4d
parent6fd37ffbc95711c5a942b31c20d3074d815c37c6 (diff)
parent2307093dc1aef8490efb8bf5b582a67dfe4b9c70 (diff)
Merge "STL: Add defaultOverscrollProgressConverter in SceneTransitions [1/2]" into main
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt5
-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.kt8
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/TransitionDslImpl.kt4
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/ElementTest.kt91
5 files changed, 109 insertions, 5 deletions
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 c5c3a62608b5..e6198148d265 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
@@ -1106,7 +1106,10 @@ private inline fun <T> computeValue(
val directionSign = if (transition.isUpOrLeft) -1 else 1
val isToContent = overscroll.scene == transition.toContent
val linearProgress = transition.progress.let { if (isToContent) it - 1f else it }
- val progress = directionSign * overscroll.progressConverter.convert(linearProgress)
+ val progressConverter =
+ overscroll.progressConverter
+ ?: layoutImpl.state.transitions.defaultProgressConverter
+ val progress = directionSign * progressConverter.convert(linearProgress)
val rangeProgress = propertySpec.range?.progress(progress) ?: progress
// Interpolate between the value at rest and the over scrolled value.
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 a063438bb911..d35d95685d22 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
@@ -45,6 +45,7 @@ internal constructor(
internal val transitionSpecs: List<TransitionSpecImpl>,
internal val overscrollSpecs: List<OverscrollSpecImpl>,
internal val interruptionHandler: InterruptionHandler,
+ internal val defaultProgressConverter: ProgressConverter,
) {
private val transitionCache =
mutableMapOf<
@@ -147,6 +148,7 @@ internal constructor(
transitionSpecs = emptyList(),
overscrollSpecs = emptyList(),
interruptionHandler = DefaultInterruptionHandler,
+ defaultProgressConverter = ProgressConverter.Default,
)
}
}
@@ -282,14 +284,14 @@ interface OverscrollSpec {
* - 1, the user overscrolled by exactly the [OverscrollBuilder.distance].
* - Greater than 1, the user overscrolled more than the [OverscrollBuilder.distance].
*/
- val progressConverter: ProgressConverter
+ val progressConverter: ProgressConverter?
}
internal class OverscrollSpecImpl(
override val scene: SceneKey,
override val orientation: Orientation,
override val transformationSpec: TransformationSpecImpl,
- override val progressConverter: ProgressConverter,
+ override val progressConverter: ProgressConverter?,
) : OverscrollSpec
/**
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 ad1fd96c0b47..e38c849182d8 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
@@ -50,6 +50,12 @@ interface SceneTransitionsBuilder {
var interruptionHandler: InterruptionHandler
/**
+ * Default [ProgressConverter] used during overscroll. It lets you change a linear progress into
+ * a function of your choice. Defaults to [ProgressConverter.Default].
+ */
+ var defaultOverscrollProgressConverter: ProgressConverter
+
+ /**
* Define the default animation to be played when transitioning [to] the specified content, from
* any content. For the animation specification to apply only when transitioning between two
* specific contents, use [from] instead.
@@ -217,7 +223,7 @@ interface OverscrollBuilder : BaseTransitionBuilder {
* - 1, the user overscrolled by exactly the [distance].
* - Greater than 1, the user overscrolled more than the [distance].
*/
- var progressConverter: ProgressConverter
+ var progressConverter: ProgressConverter?
/** Translate the element(s) matching [matcher] by ([x], [y]) pixels. */
fun translate(
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 771d1dd45e02..523e5bdd7203 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
@@ -50,12 +50,14 @@ internal fun transitionsImpl(
impl.transitionSpecs,
impl.transitionOverscrollSpecs,
impl.interruptionHandler,
+ impl.defaultOverscrollProgressConverter,
)
}
private class SceneTransitionsBuilderImpl : SceneTransitionsBuilder {
override var defaultSwipeSpec: SpringSpec<Float> = SceneTransitions.DefaultSwipeSpec
override var interruptionHandler: InterruptionHandler = DefaultInterruptionHandler
+ override var defaultOverscrollProgressConverter: ProgressConverter = ProgressConverter.Default
val transitionSpecs = mutableListOf<TransitionSpecImpl>()
val transitionOverscrollSpecs = mutableListOf<OverscrollSpecImpl>()
@@ -271,7 +273,7 @@ internal class TransitionBuilderImpl : BaseTransitionBuilderImpl(), TransitionBu
}
internal open class OverscrollBuilderImpl : BaseTransitionBuilderImpl(), OverscrollBuilder {
- override var progressConverter: ProgressConverter = ProgressConverter.Default
+ override var progressConverter: ProgressConverter? = null
override fun translate(
matcher: ElementMatcher,
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 34e609095e90..20b9b49c21d7 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
@@ -961,6 +961,97 @@ class ElementTest {
}
@Test
+ fun elementTransitionWithDistanceDuringOverscrollWithDefaultProgressConverter() {
+ val layoutWidth = 200.dp
+ val layoutHeight = 400.dp
+ var animatedFloat = 0f
+ val state =
+ setupOverscrollScenario(
+ layoutWidth = layoutWidth,
+ layoutHeight = layoutHeight,
+ sceneTransitions = {
+ // Overscroll progress will be halved
+ defaultOverscrollProgressConverter = ProgressConverter { it / 2f }
+
+ overscroll(SceneB, Orientation.Vertical) {
+ // On overscroll 100% -> Foo should translate by layoutHeight
+ translate(TestElements.Foo, y = { absoluteDistance })
+ }
+ },
+ firstScroll = 1f, // 100% scroll
+ animatedFloatRange = 0f..100f,
+ onAnimatedFloat = { animatedFloat = it },
+ )
+
+ val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
+ fooElement.assertTopPositionInRootIsEqualTo(0.dp)
+ assertThat(animatedFloat).isEqualTo(100f)
+
+ rule.onRoot().performTouchInput {
+ // Scroll another 100%
+ moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000)
+ }
+
+ val transition = assertThat(state.transitionState).isTransition()
+ assertThat(animatedFloat).isEqualTo(100f)
+
+ // Scroll 200% (100% scroll + 100% overscroll)
+ assertThat(transition).hasProgress(2f)
+ assertThat(transition).hasOverscrollSpec()
+
+ // Overscroll progress is halved, we are at 50% of the overscroll progress.
+ fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * 0.5f)
+ assertThat(animatedFloat).isEqualTo(100f)
+ }
+
+ @Test
+ fun elementTransitionWithDistanceDuringOverscrollWithOverrideDefaultProgressConverter() {
+ val layoutWidth = 200.dp
+ val layoutHeight = 400.dp
+ var animatedFloat = 0f
+ val state =
+ setupOverscrollScenario(
+ layoutWidth = layoutWidth,
+ layoutHeight = layoutHeight,
+ sceneTransitions = {
+ // Overscroll progress will be linear (by default)
+ defaultOverscrollProgressConverter = ProgressConverter { it }
+
+ overscroll(SceneB, Orientation.Vertical) {
+ // This override the defaultOverscrollProgressConverter
+ // Overscroll progress will be halved
+ progressConverter = ProgressConverter { it / 2f }
+ // On overscroll 100% -> Foo should translate by layoutHeight
+ translate(TestElements.Foo, y = { absoluteDistance })
+ }
+ },
+ firstScroll = 1f, // 100% scroll
+ animatedFloatRange = 0f..100f,
+ onAnimatedFloat = { animatedFloat = it },
+ )
+
+ val fooElement = rule.onNodeWithTag(TestElements.Foo.testTag)
+ fooElement.assertTopPositionInRootIsEqualTo(0.dp)
+ assertThat(animatedFloat).isEqualTo(100f)
+
+ rule.onRoot().performTouchInput {
+ // Scroll another 100%
+ moveBy(Offset(0f, layoutHeight.toPx()), delayMillis = 1_000)
+ }
+
+ val transition = assertThat(state.transitionState).isTransition()
+ assertThat(animatedFloat).isEqualTo(100f)
+
+ // Scroll 200% (100% scroll + 100% overscroll)
+ assertThat(transition).hasProgress(2f)
+ assertThat(transition).hasOverscrollSpec()
+
+ // Overscroll progress is halved, we are at 50% of the overscroll progress.
+ fooElement.assertTopPositionInRootIsEqualTo(layoutHeight * 0.5f)
+ assertThat(animatedFloat).isEqualTo(100f)
+ }
+
+ @Test
fun elementTransitionWithDistanceDuringOverscrollWithProgressConverter() {
val layoutWidth = 200.dp
val layoutHeight = 400.dp