diff options
| author | 2024-12-30 08:48:02 -0800 | |
|---|---|---|
| committer | 2024-12-30 08:48:02 -0800 | |
| commit | f637fe86824d1ce010da542a4e65db5343819230 (patch) | |
| tree | f4d9415d71f7455e68570d7ba02bca0a803c6503 | |
| parent | 1ac357ab95c82b4ce20c496213210578493cc60c (diff) | |
| parent | d77e28850f34cb5f0215ca920cdf48b93fada455 (diff) | |
Merge changes from topic "stl-move-offset-effect" into main
* changes:
Move OffsetOverscrollEffect and others to PlatformComposeCore (1/2)
Extract internal GestureEffect out of ContentOverscrollEffect
10 files changed, 115 insertions, 95 deletions
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/effect/ContentOverscrollEffect.kt b/packages/SystemUI/compose/core/src/com/android/compose/gesture/effect/ContentOverscrollEffect.kt index 2233debde277..4ee6db3d516c 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/effect/ContentOverscrollEffect.kt +++ b/packages/SystemUI/compose/core/src/com/android/compose/gesture/effect/ContentOverscrollEffect.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.compose.animation.scene.effect +package com.android.compose.gesture.effect import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.AnimationSpec @@ -118,56 +118,3 @@ open class BaseContentOverscrollEffect( } } } - -/** An overscroll effect that ensures only a single fling animation is triggered. */ -internal class GestureEffect(private val delegate: ContentOverscrollEffect) : - ContentOverscrollEffect by delegate { - private var shouldFling = false - - override fun applyToScroll( - delta: Offset, - source: NestedScrollSource, - performScroll: (Offset) -> Offset, - ): Offset { - shouldFling = true - return delegate.applyToScroll(delta, source, performScroll) - } - - override suspend fun applyToFling( - velocity: Velocity, - performFling: suspend (Velocity) -> Velocity, - ) { - if (!shouldFling) { - performFling(velocity) - return - } - shouldFling = false - delegate.applyToFling(velocity, performFling) - } - - suspend fun ensureApplyToFlingIsCalled() { - applyToFling(Velocity.Zero) { Velocity.Zero } - } -} - -/** - * An overscroll effect that only applies visual effects and does not interfere with the actual - * scrolling or flinging behavior. - */ -internal class VisualEffect(private val delegate: ContentOverscrollEffect) : - ContentOverscrollEffect by delegate { - override fun applyToScroll( - delta: Offset, - source: NestedScrollSource, - performScroll: (Offset) -> Offset, - ): Offset { - return performScroll(delta) - } - - override suspend fun applyToFling( - velocity: Velocity, - performFling: suspend (Velocity) -> Velocity, - ) { - performFling(velocity) - } -} diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/effect/OffsetOverscrollEffect.kt b/packages/SystemUI/compose/core/src/com/android/compose/gesture/effect/OffsetOverscrollEffect.kt index f459c46d3e6f..d9924038d8ef 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/effect/OffsetOverscrollEffect.kt +++ b/packages/SystemUI/compose/core/src/com/android/compose/gesture/effect/OffsetOverscrollEffect.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.compose.animation.scene.effect +package com.android.compose.gesture.effect import androidx.annotation.VisibleForTesting import androidx.compose.animation.core.AnimationSpec @@ -34,7 +34,6 @@ import androidx.compose.ui.node.LayoutModifierNode import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.dp -import com.android.compose.animation.scene.ProgressConverter import kotlin.math.roundToInt import kotlinx.coroutines.CoroutineScope @@ -80,7 +79,7 @@ class OffsetOverscrollEffect( ) @VisibleForTesting - internal fun computeOffset(density: Density, overscrollDistance: Float): Int { + fun computeOffset(density: Density, overscrollDistance: Float): Int { val maxDistancePx = with(density) { MaxDistance.toPx() } val progress = ProgressConverter.Default.convert(overscrollDistance / maxDistancePx) return (progress * maxDistancePx).roundToInt() @@ -98,3 +97,35 @@ fun rememberOffsetOverscrollEffect( OffsetOverscrollEffect(orientation, animationScope, animationSpec) } } + +/** This converter lets you change a linear progress into a function of your choice. */ +fun interface ProgressConverter { + fun convert(progress: Float): Float + + companion object { + /** Starts linearly with some resistance and slowly approaches to 0.2f */ + val Default = tanh(maxProgress = 0.2f, tilt = 3f) + + /** + * The scroll stays linear, with [factor] you can control how much resistance there is. + * + * @param factor If you choose a value between 0f and 1f, the progress will grow more + * slowly, like there's resistance. A value of 1f means there's no resistance. + */ + fun linear(factor: Float = 1f) = ProgressConverter { it * factor } + + /** + * This function starts linear and slowly approaches [maxProgress]. + * + * See a [visual representation](https://www.desmos.com/calculator/usgvvf0z1u) of this + * function. + * + * @param maxProgress is the maximum progress value. + * @param tilt behaves similarly to the factor in the [linear] function, and allows you to + * control how quickly you get to the [maxProgress]. + */ + fun tanh(maxProgress: Float, tilt: Float = 1f) = ProgressConverter { + maxProgress * kotlin.math.tanh(x = it / (maxProgress * tilt)) + } + } +} diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/ui/util/SpaceVectorConverter.kt b/packages/SystemUI/compose/core/src/com/android/compose/ui/util/SpaceVectorConverter.kt index ca50e778d131..ca50e778d131 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/ui/util/SpaceVectorConverter.kt +++ b/packages/SystemUI/compose/core/src/com/android/compose/ui/util/SpaceVectorConverter.kt diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/effect/OffsetOverscrollEffectTest.kt b/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/effect/OffsetOverscrollEffectTest.kt index da8fe3094448..5a3f240deb44 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/effect/OffsetOverscrollEffectTest.kt +++ b/packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/effect/OffsetOverscrollEffectTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.compose.animation.scene.effect +package com.android.compose.gesture.effect import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.rememberScrollableState diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt index cfbe6671db02..ffdf509174d5 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/OverlayShade.kt @@ -58,7 +58,7 @@ import androidx.compose.ui.unit.dp import com.android.compose.animation.scene.ContentScope import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.LowestZIndexContentPicker -import com.android.compose.animation.scene.effect.rememberOffsetOverscrollEffect +import com.android.compose.gesture.effect.rememberOffsetOverscrollEffect import com.android.compose.windowsizeclass.LocalWindowSizeClass import com.android.systemui.res.R 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 7b30a2a475e3..c704a3e96467 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 @@ -35,7 +35,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.LayoutDirection -import com.android.compose.animation.scene.effect.ContentOverscrollEffect +import com.android.compose.gesture.effect.ContentOverscrollEffect /** * [SceneTransitionLayout] is a container that automatically animates its content whenever its state 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 8794df0cf884..fda6fab6229a 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,6 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.android.compose.animation.scene.content.state.TransitionState import com.android.compose.animation.scene.transformation.Transformation -import kotlin.math.tanh /** Define the [transitions][SceneTransitions] to be used with a [SceneTransitionLayout]. */ fun transitions(builder: SceneTransitionsBuilder.() -> Unit): SceneTransitions { @@ -476,35 +475,3 @@ interface PropertyTransformationBuilder { /** Apply a [transformation] to the element(s) matching [matcher]. */ fun transformation(matcher: ElementMatcher, transformation: Transformation.Factory) } - -/** This converter lets you change a linear progress into a function of your choice. */ -fun interface ProgressConverter { - fun convert(progress: Float): Float - - companion object { - /** Starts linearly with some resistance and slowly approaches to 0.2f */ - val Default = tanh(maxProgress = 0.2f, tilt = 3f) - - /** - * The scroll stays linear, with [factor] you can control how much resistance there is. - * - * @param factor If you choose a value between 0f and 1f, the progress will grow more - * slowly, like there's resistance. A value of 1f means there's no resistance. - */ - fun linear(factor: Float = 1f) = ProgressConverter { it * factor } - - /** - * This function starts linear and slowly approaches [maxProgress]. - * - * See a [visual representation](https://www.desmos.com/calculator/usgvvf0z1u) of this - * function. - * - * @param maxProgress is the maximum progress value. - * @param tilt behaves similarly to the factor in the [linear] function, and allows you to - * control how quickly you get to the [maxProgress]. - */ - fun tanh(maxProgress: Float, tilt: Float = 1f) = ProgressConverter { - maxProgress * tanh(x = it / (maxProgress * tilt)) - } - } -} diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt index 8c5a72738a41..4c15f7a4534f 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/Content.kt @@ -53,10 +53,10 @@ import com.android.compose.animation.scene.UserActionResult import com.android.compose.animation.scene.ValueKey import com.android.compose.animation.scene.animateSharedValueAsState import com.android.compose.animation.scene.effect.GestureEffect -import com.android.compose.animation.scene.effect.OffsetOverscrollEffect import com.android.compose.animation.scene.effect.VisualEffect import com.android.compose.animation.scene.element import com.android.compose.animation.scene.modifiers.noResizeDuringTransitions +import com.android.compose.gesture.effect.OffsetOverscrollEffect import com.android.compose.modifiers.thenIf import com.android.compose.ui.graphics.ContainerState import com.android.compose.ui.graphics.container diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/effect/GestureEffect.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/effect/GestureEffect.kt new file mode 100644 index 000000000000..2db45aa3dd58 --- /dev/null +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/effect/GestureEffect.kt @@ -0,0 +1,75 @@ +/* + * 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.effect + +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.input.nestedscroll.NestedScrollSource +import androidx.compose.ui.unit.Velocity +import com.android.compose.gesture.effect.ContentOverscrollEffect + +/** An overscroll effect that ensures only a single fling animation is triggered. */ +internal class GestureEffect(private val delegate: ContentOverscrollEffect) : + ContentOverscrollEffect by delegate { + private var shouldFling = false + + override fun applyToScroll( + delta: Offset, + source: NestedScrollSource, + performScroll: (Offset) -> Offset, + ): Offset { + shouldFling = true + return delegate.applyToScroll(delta, source, performScroll) + } + + override suspend fun applyToFling( + velocity: Velocity, + performFling: suspend (Velocity) -> Velocity, + ) { + if (!shouldFling) { + performFling(velocity) + return + } + shouldFling = false + delegate.applyToFling(velocity, performFling) + } + + suspend fun ensureApplyToFlingIsCalled() { + applyToFling(Velocity.Zero) { Velocity.Zero } + } +} + +/** + * An overscroll effect that only applies visual effects and does not interfere with the actual + * scrolling or flinging behavior. + */ +internal class VisualEffect(private val delegate: ContentOverscrollEffect) : + ContentOverscrollEffect by delegate { + override fun applyToScroll( + delta: Offset, + source: NestedScrollSource, + performScroll: (Offset) -> Offset, + ): Offset { + return performScroll(delta) + } + + override suspend fun applyToFling( + velocity: Velocity, + performFling: suspend (Velocity) -> Velocity, + ) { + performFling(velocity) + } +} 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 676903274b38..53495be7b02a 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 @@ -70,8 +70,8 @@ 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.TestScenes.SceneC -import com.android.compose.animation.scene.effect.OffsetOverscrollEffect import com.android.compose.animation.scene.subjects.assertThat +import com.android.compose.gesture.effect.OffsetOverscrollEffect import com.android.compose.test.assertSizeIsEqualTo import com.android.compose.test.setContentAndCreateMainScope import com.android.compose.test.transition |