diff options
7 files changed, 31 insertions, 84 deletions
| diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationScrimNestedScrollConnection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationScrimNestedScrollConnection.kt index 94c18cdbef5a..cb87f0e7cf1c 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationScrimNestedScrollConnection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationScrimNestedScrollConnection.kt @@ -62,7 +62,6 @@ fun NotificationScrimNestedScrollConnection(          canStartPostScroll = { offsetAvailable, _, _ ->              offsetAvailable > 0 && (scrimOffset() < maxScrimOffset || isCurrentGestureOverscroll())          }, -        canStartPostFling = { false },          onStart = { firstScroll ->              onStart(firstScroll)              object : ScrollController { diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt index d8abfd7a4b94..e1ee59ba0626 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationStackNestedScrollConnection.kt @@ -25,11 +25,13 @@ import androidx.compose.foundation.layout.offset  import androidx.compose.runtime.Composable  import androidx.compose.runtime.remember  import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.NestedScrollConnection  import androidx.compose.ui.input.nestedscroll.NestedScrollSource  import androidx.compose.ui.input.nestedscroll.nestedScroll  import androidx.compose.ui.platform.LocalConfiguration  import androidx.compose.ui.platform.LocalDensity  import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.Velocity  import androidx.compose.ui.unit.dp  import androidx.compose.ui.util.fastCoerceAtLeast  import com.android.compose.nestedscroll.OnStopScope @@ -80,9 +82,29 @@ fun Modifier.stackVerticalOverscroll(          }      return this.then( -        Modifier.nestedScroll(stackNestedScrollConnection).offset { -            IntOffset(x = 0, y = overscrollOffset.value.roundToInt()) -        } +        Modifier.nestedScroll( +                remember { +                    object : NestedScrollConnection { +                        override suspend fun onPostFling( +                            consumed: Velocity, +                            available: Velocity, +                        ): Velocity { +                            return if (available.y < 0f && !canScrollForward()) { +                                overscrollOffset.animateTo( +                                    targetValue = 0f, +                                    initialVelocity = available.y, +                                    animationSpec = tween(), +                                ) +                                available +                            } else { +                                Velocity.Zero +                            } +                        } +                    } +                } +            ) +            .nestedScroll(stackNestedScrollConnection) +            .offset { IntOffset(x = 0, y = overscrollOffset.value.roundToInt()) }      )  } @@ -100,7 +122,6 @@ fun NotificationStackNestedScrollConnection(          canStartPostScroll = { offsetAvailable, offsetBeforeStart, _ ->              offsetAvailable < 0f && offsetBeforeStart < 0f && !canScrollForward()          }, -        canStartPostFling = { velocityAvailable -> velocityAvailable < 0f && !canScrollForward() },          onStart = { firstScroll ->              onStart(firstScroll)              object : ScrollController { 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 2d589f37f3cb..737a89630a8f 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 @@ -536,31 +536,6 @@ internal class NestedScrollHandlerImpl(                      }                  }              }, -            canStartPostFling = { velocityAvailable -> -                val behavior: NestedScrollBehavior = -                    when { -                        velocityAvailable > 0f -> topOrLeftBehavior -                        velocityAvailable < 0f -> bottomOrRightBehavior -                        else -> return@PriorityNestedScrollConnection false -                    } - -                // We could start an overscroll animation -                canChangeScene = false - -                val pointersDown: PointersInfo.PointersDown? = -                    when (val info = pointersInfoOwner.pointersInfo()) { -                        PointersInfo.MouseWheel -> { -                            // Do not support mouse wheel interactions -                            return@PriorityNestedScrollConnection false -                        } - -                        is PointersInfo.PointersDown -> info -                        null -> null -                    } -                lastPointersDown = pointersDown - -                behavior.canStartOnPostFling && shouldEnableSwipes() -            },              onStart = { firstScroll ->                  scrollController(                      dragController = diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt index 955be603efaf..9622fc151bb7 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/NestedScrollToScene.kt @@ -32,7 +32,7 @@ import androidx.compose.ui.platform.InspectorInfo   * not consumed by the [SceneTransitionLayout] unless specifically requested via   * [nestedScrollToScene].   */ -enum class NestedScrollBehavior(val canStartOnPostFling: Boolean) { +enum class NestedScrollBehavior {      /**       * Overscroll will only be used by the [SceneTransitionLayout] to move to the next scene if the       * gesture begins at the edge of the scrollable component (so that a scroll in that direction @@ -42,7 +42,7 @@ enum class NestedScrollBehavior(val canStartOnPostFling: Boolean) {       * In addition, during scene transitions, scroll events are consumed by the       * [SceneTransitionLayout] instead of the scrollable component.       */ -    EdgeNoPreview(canStartOnPostFling = false), +    EdgeNoPreview,      /**       * Overscroll will only be used by the [SceneTransitionLayout] to move to the next scene if the @@ -52,7 +52,7 @@ enum class NestedScrollBehavior(val canStartOnPostFling: Boolean) {       * In addition, during scene transitions, scroll events are consumed by the       * [SceneTransitionLayout] instead of the scrollable component.       */ -    EdgeWithPreview(canStartOnPostFling = true), +    @Deprecated("This will be removed, see b/378470603") EdgeWithPreview,      /**       * Any overscroll will be used by the [SceneTransitionLayout] to move to the next scene. @@ -60,7 +60,7 @@ enum class NestedScrollBehavior(val canStartOnPostFling: Boolean) {       * In addition, during scene transitions, scroll events are consumed by the       * [SceneTransitionLayout] instead of the scrollable component.       */ -    EdgeAlways(canStartOnPostFling = true); +    EdgeAlways;      companion object {          val Default = EdgeNoPreview diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnection.kt b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnection.kt index 98a00173f1d7..b26bf55c85ec 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnection.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/LargeTopAppBarNestedScrollConnection.kt @@ -56,7 +56,6 @@ fun LargeTopAppBarNestedScrollConnection(          canStartPostScroll = { offsetAvailable, _, _ ->              offsetAvailable > 0 && height() < maxHeight()          }, -        canStartPostFling = { false },          onStart = {              LargeTopAppBarScrollController(                  height = height, diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt index 3f182363e20c..3d0f182fffee 100644 --- a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt +++ b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt @@ -24,7 +24,6 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection  import androidx.compose.ui.input.nestedscroll.NestedScrollSource  import androidx.compose.ui.unit.Velocity  import com.android.compose.ui.util.SpaceVectorConverter -import kotlin.math.sign  import kotlinx.coroutines.Deferred  import kotlinx.coroutines.async  import kotlinx.coroutines.coroutineScope @@ -102,8 +101,8 @@ interface OnStopScope {   * over the default nested scrolling logic.   *   * When started, this connection intercepts scroll events *before* they reach child composables. - * This "priority mode" is activated activated when either [canStartPreScroll], [canStartPostScroll] - * or [canStartPostFling] returns `true`. + * This "priority mode" is activated when either [canStartPreScroll] or [canStartPostScroll] returns + * `true`.   *   * Once started, the [onStart] lambda provides a [ScrollController] to manage the scrolling. This   * controller allows you to directly manipulate the scroll state and define how scroll events are @@ -123,8 +122,6 @@ interface OnStopScope {   * @param canStartPostScroll A lambda that returns `true` if the connection should enter priority   *   mode during the post-scroll phase. This is called after child connections have consumed the   *   scroll. - * @param canStartPostFling A lambda that returns `true` if the connection should enter priority - *   mode during the post-fling phase. This is called after a fling gesture has been initiated.   * @param onStart A lambda that is called when the connection enters priority mode. It should return   *   a [ScrollController] that will be used to control the scroll.   * @sample LargeTopAppBarNestedScrollConnection @@ -136,7 +133,6 @@ class PriorityNestedScrollConnection(          (offsetAvailable: Float, offsetBeforeStart: Float, source: NestedScrollSource) -> Boolean,      private val canStartPostScroll:          (offsetAvailable: Float, offsetBeforeStart: Float, source: NestedScrollSource) -> Boolean, -    private val canStartPostFling: (velocityAvailable: Float) -> Boolean,      private val onStart: (firstScroll: Float) -> ScrollController,  ) : NestedScrollConnection, SpaceVectorConverter by SpaceVectorConverter(orientation) { @@ -233,17 +229,6 @@ class PriorityNestedScrollConnection(              return stop(velocity = availableFloat)          } -        // Check if post-fling condition is met, and start priority mode if necessary. -        // TODO(b/291053278): Remove canStartPostFling() and instead make it possible to define the -        // overscroll behavior on the Scene level. -        if (canStartPostFling(availableFloat)) { -            // The offset passed to onPriorityStart() must be != 0f, so we create a small offset of -            // 1px given the available velocity. -            val smallOffset = availableFloat.sign -            start(availableOffset = smallOffset) -            return stop(availableFloat) -        } -          // Reset offset tracking after the fling gesture is finished.          resetOffsetTracker()          return Velocity.Zero diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt index 28ea2d239b54..51483a894e1e 100644 --- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt +++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/nestedscroll/PriorityNestedScrollConnectionTest.kt @@ -39,7 +39,6 @@ import org.junit.runner.RunWith  class PriorityNestedScrollConnectionTest {      private var canStartPreScroll = false      private var canStartPostScroll = false -    private var canStartPostFling = false      private var canStopOnPreFling = true      private var isStarted = false      private var lastScroll: Float? = null @@ -63,7 +62,6 @@ class PriorityNestedScrollConnectionTest {              orientation = Orientation.Vertical,              canStartPreScroll = { _, _, _ -> canStartPreScroll },              canStartPostScroll = { _, _, _ -> canStartPostScroll }, -            canStartPostFling = { canStartPostFling },              onStart = { _ ->                  isStarted = true                  object : ScrollController { @@ -239,36 +237,6 @@ class PriorityNestedScrollConnectionTest {      }      @Test -    fun receive_onPostFling() = runTest { -        canStartPostFling = true - -        scrollConnection.onPostFling(consumed = Velocity(1f, 1f), available = Velocity(2f, 2f)) - -        assertThat(lastStop).isEqualTo(2f) -    } - -    @Test -    fun step1_priorityModeShouldStartOnlyOnPostFling() = runTest { -        canStartPostFling = true - -        scrollConnection.onPreScroll(available = Offset.Zero, source = UserInput) -        assertThat(isStarted).isEqualTo(false) - -        scrollConnection.onPostScroll( -            consumed = Offset.Zero, -            available = Offset.Zero, -            source = UserInput, -        ) -        assertThat(isStarted).isEqualTo(false) - -        scrollConnection.onPreFling(available = Velocity.Zero) -        assertThat(isStarted).isEqualTo(false) - -        scrollConnection.onPostFling(consumed = Velocity.Zero, available = Velocity.Zero) -        assertThat(isStarted).isEqualTo(true) -    } - -    @Test      fun handleMultipleOnPreFlingCalls() = runTest {          startPriorityModePostScroll() |