From 566ea76db138c7fcc2f9c1942e5bf8953d271535 Mon Sep 17 00:00:00 2001 From: wcaokaze Date: Sun, 11 Sep 2022 05:29:46 +0900 Subject: [PATCH 1/2] make Pager able to scroll by flinging a nested scroll child --- .../java/com/google/accompanist/pager/Pager.kt | 15 ++++++++++++--- .../com/google/accompanist/pager/PagerState.kt | 2 +- .../pager/HorizontalPagerScrollingContentTest.kt | 11 +++++++++++ .../pager/VerticalPagerScrollingContentTest.kt | 11 +++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/pager/src/main/java/com/google/accompanist/pager/Pager.kt b/pager/src/main/java/com/google/accompanist/pager/Pager.kt index 0dac998dc..112bac5a6 100644 --- a/pager/src/main/java/com/google/accompanist/pager/Pager.kt +++ b/pager/src/main/java/com/google/accompanist/pager/Pager.kt @@ -385,6 +385,7 @@ internal fun Pager( ConsumeFlingNestedScrollConnection( consumeHorizontal = !isVertical, consumeVertical = isVertical, + pagerState = state, ) } @@ -449,9 +450,11 @@ internal fun Pager( } } +@OptIn(ExperimentalPagerApi::class) private class ConsumeFlingNestedScrollConnection( private val consumeHorizontal: Boolean, private val consumeVertical: Boolean, + private val pagerState: PagerState, ) : NestedScrollConnection { override fun onPostScroll( consumed: Offset, @@ -465,9 +468,15 @@ private class ConsumeFlingNestedScrollConnection( } override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity { - // We can consume all post fling velocity on the main-axis - // so that it doesn't propagate up to the Pager - return available.consume(consumeHorizontal, consumeVertical) + return if (pagerState.currentPageLayoutInfo?.offset != 0) { + // The Pager is already scrolling. This means that a nested scroll child was + // scrolled to end, and the Pager can use this fling + Velocity.Zero + } else { + // A nested scroll child is still scrolling. We can consume all post fling + // velocity on the main-axis so that it doesn't propagate up to the Pager + available.consume(consumeHorizontal, consumeVertical) + } } } diff --git a/pager/src/main/java/com/google/accompanist/pager/PagerState.kt b/pager/src/main/java/com/google/accompanist/pager/PagerState.kt index 89c6fee2c..3215447ed 100644 --- a/pager/src/main/java/com/google/accompanist/pager/PagerState.kt +++ b/pager/src/main/java/com/google/accompanist/pager/PagerState.kt @@ -92,7 +92,7 @@ class PagerState( internal var afterContentPadding = 0 - private val currentPageLayoutInfo: LazyListItemInfo? + internal val currentPageLayoutInfo: LazyListItemInfo? get() = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull { it.index == currentPage } diff --git a/pager/src/sharedTest/kotlin/com/google/accompanist/pager/HorizontalPagerScrollingContentTest.kt b/pager/src/sharedTest/kotlin/com/google/accompanist/pager/HorizontalPagerScrollingContentTest.kt index 4cea9e9b8..97779915c 100644 --- a/pager/src/sharedTest/kotlin/com/google/accompanist/pager/HorizontalPagerScrollingContentTest.kt +++ b/pager/src/sharedTest/kotlin/com/google/accompanist/pager/HorizontalPagerScrollingContentTest.kt @@ -89,6 +89,17 @@ class HorizontalPagerScrollingContentTest { // Assert that we're still on page 0 assertThat(pagerState.currentPage).isEqualTo(0) assertThat(pagerState.currentPageOffset).isWithin(0.01f).of(0f) + + // Perform a scroll in the same direction again + rule.onNodeWithTag(TestTag) + .swipeAcrossCenterWithVelocity(velocityPerSec = 2_000.dp, distancePercentageX = -0.5f) + + // Wait for the flings to end + rule.waitForIdle() + + // Assert that we're now on page 1 + assertThat(pagerState.currentPage).isEqualTo(1) + assertThat(pagerState.currentPageOffset).isWithin(0.01f).of(0f) } companion object { diff --git a/pager/src/sharedTest/kotlin/com/google/accompanist/pager/VerticalPagerScrollingContentTest.kt b/pager/src/sharedTest/kotlin/com/google/accompanist/pager/VerticalPagerScrollingContentTest.kt index f482fb85e..0328f3cf3 100644 --- a/pager/src/sharedTest/kotlin/com/google/accompanist/pager/VerticalPagerScrollingContentTest.kt +++ b/pager/src/sharedTest/kotlin/com/google/accompanist/pager/VerticalPagerScrollingContentTest.kt @@ -88,6 +88,17 @@ class VerticalPagerScrollingContentTest { // Assert that we're still on page 0 assertThat(pagerState.currentPage).isEqualTo(0) assertThat(pagerState.currentPageOffset).isWithin(0.01f).of(0f) + + // Perform a scroll in the same direction again + rule.onNodeWithTag(TestTag) + .swipeAcrossCenterWithVelocity(velocityPerSec = 2_000.dp, distancePercentageY = -0.5f) + + // Wait for the flings to end + rule.waitForIdle() + + // Assert that we're now on page 1 + assertThat(pagerState.currentPage).isEqualTo(1) + assertThat(pagerState.currentPageOffset).isWithin(0.01f).of(0f) } companion object { From 54fe52ad84e16015e01d31284e0173471d9b6a11 Mon Sep 17 00:00:00 2001 From: wcaokaze Date: Wed, 21 Sep 2022 12:46:52 +0900 Subject: [PATCH 2/2] use currentPageOffset instead of currentPageLayoutInfo.offset, and make PagerState.currentPageLayoutInfo private again --- pager/src/main/java/com/google/accompanist/pager/Pager.kt | 2 +- pager/src/main/java/com/google/accompanist/pager/PagerState.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pager/src/main/java/com/google/accompanist/pager/Pager.kt b/pager/src/main/java/com/google/accompanist/pager/Pager.kt index 112bac5a6..7b283cef8 100644 --- a/pager/src/main/java/com/google/accompanist/pager/Pager.kt +++ b/pager/src/main/java/com/google/accompanist/pager/Pager.kt @@ -468,7 +468,7 @@ private class ConsumeFlingNestedScrollConnection( } override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity { - return if (pagerState.currentPageLayoutInfo?.offset != 0) { + return if (pagerState.currentPageOffset != 0f) { // The Pager is already scrolling. This means that a nested scroll child was // scrolled to end, and the Pager can use this fling Velocity.Zero diff --git a/pager/src/main/java/com/google/accompanist/pager/PagerState.kt b/pager/src/main/java/com/google/accompanist/pager/PagerState.kt index 3215447ed..89c6fee2c 100644 --- a/pager/src/main/java/com/google/accompanist/pager/PagerState.kt +++ b/pager/src/main/java/com/google/accompanist/pager/PagerState.kt @@ -92,7 +92,7 @@ class PagerState( internal var afterContentPadding = 0 - internal val currentPageLayoutInfo: LazyListItemInfo? + private val currentPageLayoutInfo: LazyListItemInfo? get() = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull { it.index == currentPage }