Loading packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedScrollController.kt +11 −1 Original line number Diff line number Diff line Loading @@ -134,6 +134,7 @@ private class NestedScrollControllerNode( private var bounds: NestedScrollableBound, ) : DelegatingNode(), NestedScrollConnection { private var childrenConsumedAnyScroll = false private var availableOnPreScroll = Offset.Zero init { delegate(nestedScrollModifierNode(this, dispatcher = null)) Loading @@ -153,12 +154,21 @@ private class NestedScrollControllerNode( this.bounds = bounds } override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { availableOnPreScroll = available return Offset.Zero } override fun onPostScroll( consumed: Offset, available: Offset, source: NestedScrollSource, ): Offset { if (hasConsumedScrollInBounds(consumed.x) || hasConsumedScrollInBounds(consumed.y)) { val consumedIncludingPreScroll = availableOnPreScroll - available if ( hasConsumedScrollInBounds(consumedIncludingPreScroll.x) || hasConsumedScrollInBounds(consumedIncludingPreScroll.y) ) { childrenConsumedAnyScroll = true } Loading packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedScrollControllerTest.kt +35 −0 Original line number Diff line number Diff line Loading @@ -23,9 +23,13 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset 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.test.junit4.createComposeRule import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performTouchInput Loading Loading @@ -103,4 +107,35 @@ class NestedScrollControllerTest { rule.waitForIdle() assertThat(state.isOuterScrollAllowed).isTrue() } @Test fun supportsPreScrolls() { val state = NestedScrollControlState() rule.setContent { Box( Modifier.fillMaxSize() .nestedScrollController(state) .nestedScroll( remember { object : NestedScrollConnection { override fun onPreScroll( available: Offset, source: NestedScrollSource, ): Offset = available } } ) .scrollable(rememberScrollableState { 0f }, Orientation.Vertical) ) } rule.onRoot().performTouchInput { down(topLeft) moveBy(Offset(0f, bottom)) } assertThat(state.isOuterScrollAllowed).isFalse() rule.onRoot().performTouchInput { up() } assertThat(state.isOuterScrollAllowed).isTrue() } } Loading
packages/SystemUI/compose/core/src/com/android/compose/gesture/NestedScrollController.kt +11 −1 Original line number Diff line number Diff line Loading @@ -134,6 +134,7 @@ private class NestedScrollControllerNode( private var bounds: NestedScrollableBound, ) : DelegatingNode(), NestedScrollConnection { private var childrenConsumedAnyScroll = false private var availableOnPreScroll = Offset.Zero init { delegate(nestedScrollModifierNode(this, dispatcher = null)) Loading @@ -153,12 +154,21 @@ private class NestedScrollControllerNode( this.bounds = bounds } override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { availableOnPreScroll = available return Offset.Zero } override fun onPostScroll( consumed: Offset, available: Offset, source: NestedScrollSource, ): Offset { if (hasConsumedScrollInBounds(consumed.x) || hasConsumedScrollInBounds(consumed.y)) { val consumedIncludingPreScroll = availableOnPreScroll - available if ( hasConsumedScrollInBounds(consumedIncludingPreScroll.x) || hasConsumedScrollInBounds(consumedIncludingPreScroll.y) ) { childrenConsumedAnyScroll = true } Loading
packages/SystemUI/compose/core/tests/src/com/android/compose/gesture/NestedScrollControllerTest.kt +35 −0 Original line number Diff line number Diff line Loading @@ -23,9 +23,13 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset 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.test.junit4.createComposeRule import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performTouchInput Loading Loading @@ -103,4 +107,35 @@ class NestedScrollControllerTest { rule.waitForIdle() assertThat(state.isOuterScrollAllowed).isTrue() } @Test fun supportsPreScrolls() { val state = NestedScrollControlState() rule.setContent { Box( Modifier.fillMaxSize() .nestedScrollController(state) .nestedScroll( remember { object : NestedScrollConnection { override fun onPreScroll( available: Offset, source: NestedScrollSource, ): Offset = available } } ) .scrollable(rememberScrollableState { 0f }, Orientation.Vertical) ) } rule.onRoot().performTouchInput { down(topLeft) moveBy(Offset(0f, bottom)) } assertThat(state.isOuterScrollAllowed).isFalse() rule.onRoot().performTouchInput { up() } assertThat(state.isOuterScrollAllowed).isTrue() } }