Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2ca8bb2e authored by Jordan Demeulenaere's avatar Jordan Demeulenaere Committed by Android (Google) Code Review
Browse files

Merge "Add NestedDraggable.Controller.autoStopNestedDrags" into main

parents 4f7b6c24 f4a86dd4
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -111,6 +111,14 @@ interface NestedDraggable {
    fun shouldConsumeNestedPreScroll(sign: Float): Boolean = false

    interface Controller {
        /**
         * Whether drags that were started from nested scrolls should be automatically
         * [stopped][onDragStopped] as soon as they don't consume the entire `delta` passed to
         * [onDrag].
         */
        val autoStopNestedDrags: Boolean
            get() = false

        /**
         * Drag by [delta] pixels.
         *
@@ -609,8 +617,15 @@ private class NestedDraggableNode(
    }

    private fun scrollWithOverscroll(controller: NestedScrollController, offset: Offset): Offset {
        return scrollWithOverscroll(offset) {
            controller.controller.onDrag(it.toFloat()).toOffset()
        return scrollWithOverscroll(offset) { delta ->
            val available = delta.toFloat()
            val consumed = controller.controller.onDrag(available)
            if (controller.controller.autoStopNestedDrags && consumed != available) {
                controller.ensureOnDragStoppedIsCalled()
                this.nestedScrollController = null
            }

            consumed.toOffset()
        }
    }

+36 −0
Original line number Diff line number Diff line
@@ -1000,6 +1000,39 @@ class NestedDraggableTest(override val orientation: Orientation) : OrientationAw
        assertThat(draggable.onDragStartedCalled).isTrue()
    }

    @Test
    fun autoStopNestedDrags() {
        var consumeScrolls by mutableStateOf(true)
        val draggable =
            TestDraggable(autoStopNestedDrags = true, onDrag = { if (consumeScrolls) it else 0f })

        val touchSlop =
            rule.setContentWithTouchSlop {
                Box(
                    Modifier.fillMaxSize()
                        .nestedDraggable(draggable, orientation)
                        .scrollable(rememberScrollableState { 0f }, orientation)
                )
            }

        rule.onRoot().performTouchInput {
            down(center)
            moveBy((touchSlop + 1f).toOffset())
        }

        assertThat(draggable.onDragStartedCalled).isTrue()
        assertThat(draggable.onDragStoppedCalled).isFalse()

        rule.onRoot().performTouchInput { moveBy(50f.toOffset()) }

        assertThat(draggable.onDragStoppedCalled).isFalse()

        consumeScrolls = false
        rule.onRoot().performTouchInput { moveBy(1f.toOffset()) }

        assertThat(draggable.onDragStoppedCalled).isTrue()
    }

    private fun ComposeContentTestRule.setContentWithTouchSlop(
        content: @Composable () -> Unit
    ): Float {
@@ -1027,6 +1060,7 @@ class NestedDraggableTest(override val orientation: Orientation) : OrientationAw
            },
        private val shouldConsumeNestedPostScroll: (Float) -> Boolean = { true },
        private val shouldConsumeNestedPreScroll: (Float) -> Boolean = { false },
        private val autoStopNestedDrags: Boolean = false,
    ) : NestedDraggable {
        var shouldStartDrag = true
        var onDragStartedCalled = false
@@ -1056,6 +1090,8 @@ class NestedDraggableTest(override val orientation: Orientation) : OrientationAw

            onDragStarted.invoke(position, sign)
            return object : NestedDraggable.Controller {
                override val autoStopNestedDrags: Boolean = this@TestDraggable.autoStopNestedDrags

                override fun onDrag(delta: Float): Float {
                    onDragCalled = true
                    onDragDelta += delta