Revert "Update pageCount use and application in Pager"
This reverts commit a9fe9fa615abc65c607ff14f7e638a4afbb8e8cb.
Reason for revert: broke the build
https://android-build.googleplex.com/builds/submitted/9936023/androidx_compose_multiplatform/latest/view/logs/build_error.log
Change-Id: Id49741e76acfbbb6e48bc4446045244d5b6da024
diff --git a/compose/foundation/foundation/api/public_plus_experimental_current.txt b/compose/foundation/foundation/api/public_plus_experimental_current.txt
index 650146d..8717a03 100644
--- a/compose/foundation/foundation/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation/api/public_plus_experimental_current.txt
@@ -981,10 +981,8 @@
}
public final class PagerKt {
- method @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void HorizontalPager(androidx.compose.foundation.pager.PagerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> pageContent);
- method @Deprecated @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void HorizontalPager(int pageCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.pager.PagerState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> pageContent);
- method @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void VerticalPager(androidx.compose.foundation.pager.PagerState state, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> pageContent);
- method @Deprecated @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void VerticalPager(int pageCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.pager.PagerState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> pageContent);
+ method @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void HorizontalPager(int pageCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.pager.PagerState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Vertical verticalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> pageContent);
+ method @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static void VerticalPager(int pageCount, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.foundation.pager.PagerState state, optional androidx.compose.foundation.layout.PaddingValues contentPadding, optional androidx.compose.foundation.pager.PageSize pageSize, optional int beyondBoundsPageCount, optional float pageSpacing, optional androidx.compose.ui.Alignment.Horizontal horizontalAlignment, optional androidx.compose.foundation.gestures.snapping.SnapFlingBehavior flingBehavior, optional boolean userScrollEnabled, optional boolean reverseLayout, optional kotlin.jvm.functions.Function1<? super java.lang.Integer,?>? key, optional androidx.compose.ui.input.nestedscroll.NestedScrollConnection pageNestedScrollConnection, kotlin.jvm.functions.Function1<? super java.lang.Integer,kotlin.Unit> pageContent);
}
@androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public interface PagerSnapDistance {
@@ -996,39 +994,40 @@
method public androidx.compose.foundation.pager.PagerSnapDistance atMost(int pages);
}
- @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public abstract class PagerState implements androidx.compose.foundation.gestures.ScrollableState {
+ @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public final class PagerState implements androidx.compose.foundation.gestures.ScrollableState {
ctor public PagerState(optional int initialPage, optional float initialPageOffsetFraction);
- method public final suspend Object? animateScrollToPage(int page, optional float pageOffsetFraction, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ method public suspend Object? animateScrollToPage(int page, optional float pageOffsetFraction, optional androidx.compose.animation.core.AnimationSpec<java.lang.Float> animationSpec, optional kotlin.coroutines.Continuation<? super kotlin.Unit>);
method public float dispatchRawDelta(float delta);
- method public final boolean getCanScrollBackward();
- method public final boolean getCanScrollForward();
- method public final int getCurrentPage();
- method public final float getCurrentPageOffsetFraction();
- method public final int getInitialPage();
- method public final float getInitialPageOffsetFraction();
- method public final androidx.compose.foundation.interaction.InteractionSource getInteractionSource();
- method public abstract int getPageCount();
- method public final int getSettledPage();
- method public final int getTargetPage();
+ method public int getCurrentPage();
+ method public float getCurrentPageOffsetFraction();
+ method public int getInitialPage();
+ method public float getInitialPageOffsetFraction();
+ method public androidx.compose.foundation.interaction.InteractionSource getInteractionSource();
+ method public int getSettledPage();
+ method public int getTargetPage();
method public boolean isScrollInProgress();
method public suspend Object? scroll(androidx.compose.foundation.MutatePriority scrollPriority, kotlin.jvm.functions.Function2<? super androidx.compose.foundation.gestures.ScrollScope,? super kotlin.coroutines.Continuation<? super kotlin.Unit>,?> block, kotlin.coroutines.Continuation<? super kotlin.Unit>);
- method public final suspend Object? scrollToPage(int page, optional float pageOffsetFraction, optional kotlin.coroutines.Continuation<? super kotlin.Unit>);
- property public final boolean canScrollBackward;
- property public final boolean canScrollForward;
+ method public suspend Object? scrollToPage(int page, optional float pageOffsetFraction, optional kotlin.coroutines.Continuation<? super kotlin.Unit>);
+ property public boolean canScrollBackward;
+ property public boolean canScrollForward;
property public final int currentPage;
property public final float currentPageOffsetFraction;
property public final int initialPage;
property public final float initialPageOffsetFraction;
property public final androidx.compose.foundation.interaction.InteractionSource interactionSource;
property public boolean isScrollInProgress;
- property public abstract int pageCount;
property public final int settledPage;
property public final int targetPage;
+ field public static final androidx.compose.foundation.pager.PagerState.Companion Companion;
+ }
+
+ public static final class PagerState.Companion {
+ method public androidx.compose.runtime.saveable.Saver<androidx.compose.foundation.pager.PagerState,?> getSaver();
+ property public final androidx.compose.runtime.saveable.Saver<androidx.compose.foundation.pager.PagerState,?> Saver;
}
public final class PagerStateKt {
- method @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static androidx.compose.foundation.pager.PagerState rememberPagerState(optional int initialPage, optional float initialPageOffsetFraction, kotlin.jvm.functions.Function0<java.lang.Integer> pageCount);
- method @Deprecated @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static androidx.compose.foundation.pager.PagerState rememberPagerState(optional int initialPage, optional float initialPageOffsetFraction);
+ method @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Composable public static androidx.compose.foundation.pager.PagerState rememberPagerState(optional int initialPage, optional float initialPageOffsetFraction);
}
}
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/pager/PagerCarrouselDemos.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/pager/PagerCarrouselDemos.kt
index 5b43150..a55b0aa 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/pager/PagerCarrouselDemos.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/pager/PagerCarrouselDemos.kt
@@ -55,12 +55,13 @@
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun HorizontalCarrouselDemo() {
- val pagerState = rememberPagerState { PagesCount }
+ val pagerState = rememberPagerState()
Column(modifier = Modifier.fillMaxSize()) {
HorizontalPager(
modifier = Modifier,
state = pagerState,
+ pageCount = PagesCount,
pageSize = PageSize.Fixed(200.dp)
) {
CarrouselItem(it, Orientation.Vertical)
@@ -72,12 +73,13 @@
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun VerticalCarrouselDemo() {
- val pagerState = rememberPagerState { PagesCount }
+ val pagerState = rememberPagerState()
Column(modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally) {
VerticalPager(
modifier = Modifier.weight(0.9f),
state = pagerState,
+ pageCount = PagesCount,
pageSize = PageSize.Fixed(200.dp)
) {
CarrouselItem(it, Orientation.Horizontal)
@@ -89,12 +91,13 @@
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun HorizontalCustomPageSizeDemo() {
- val pagerState = rememberPagerState { PagesCount }
+ val pagerState = rememberPagerState()
Column(modifier = Modifier.fillMaxSize()) {
HorizontalPager(
modifier = Modifier,
state = pagerState,
+ pageCount = PagesCount,
pageSize = ThreePagesPerViewport,
pageSpacing = 8.dp
) {
@@ -107,12 +110,13 @@
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun HorizontalCustomPageSizeWithCustomMaxScrollDemo() {
- val pagerState = rememberPagerState { PagesCount }
+ val pagerState = rememberPagerState()
Column(modifier = Modifier.fillMaxSize()) {
HorizontalPager(
modifier = Modifier,
state = pagerState,
+ pageCount = PagesCount,
pageSize = ThreePagesPerViewport,
pageSpacing = 8.dp,
flingBehavior = PagerDefaults.flingBehavior(
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/pager/PagerDemos.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/pager/PagerDemos.kt
index 45a08b6..49473eb 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/pager/PagerDemos.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/pager/PagerDemos.kt
@@ -72,10 +72,11 @@
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun VerticalPagerDemo() {
- val pagerState = rememberPagerState { PagesCount }
+ val pagerState = rememberPagerState()
VerticalPager(
modifier = Modifier.fillMaxSize(),
state = pagerState,
+ pageCount = PagesCount
) {
PagerItem(it)
}
@@ -84,11 +85,12 @@
@OptIn(ExperimentalFoundationApi::class)
@Composable
internal fun HorizontalPagerDemo() {
- val pagerState = rememberPagerState { PagesCount }
+ val pagerState = rememberPagerState()
HorizontalPager(
modifier = Modifier.fillMaxSize(),
state = pagerState,
+ pageCount = PagesCount
) {
PagerItem(it)
}
diff --git a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/pager/PagerStateInteractionsDemos.kt b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/pager/PagerStateInteractionsDemos.kt
index 5922b08..48202c2 100644
--- a/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/pager/PagerStateInteractionsDemos.kt
+++ b/compose/foundation/foundation/integration-tests/foundation-demos/src/main/java/androidx/compose/foundation/demos/pager/PagerStateInteractionsDemos.kt
@@ -46,12 +46,13 @@
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun StateDrivenPage() {
- val pagerState = rememberPagerState { PagesCount }
+ val pagerState = rememberPagerState()
Column(modifier = Modifier.fillMaxSize()) {
HorizontalPager(
modifier = Modifier.weight(0.9f),
- state = pagerState
+ state = pagerState,
+ pageCount = PagesCount
) {
PagerItem(it)
}
@@ -62,12 +63,13 @@
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun StateDrivenPageWithMonitor() {
- val pagerState = rememberPagerState { PagesCount }
+ val pagerState = rememberPagerState()
Column(modifier = Modifier.fillMaxSize()) {
HorizontalPager(
modifier = Modifier.weight(0.8f),
- state = pagerState
+ state = pagerState,
+ pageCount = PagesCount
) {
PagerItem(it)
}
@@ -79,11 +81,12 @@
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun StateMonitoringPager() {
- val pagerState = rememberPagerState { PagesCount }
+ val pagerState = rememberPagerState()
Column(modifier = Modifier.fillMaxSize()) {
HorizontalPager(
modifier = Modifier.weight(0.9f),
- state = pagerState
+ state = pagerState,
+ pageCount = PagesCount
) {
PagerItem(it)
}
@@ -104,7 +107,7 @@
@OptIn(ExperimentalFoundationApi::class)
@Composable
private fun StateMonitoringCustomPageSize() {
- val pagerState = rememberPagerState { PagesCount }
+ val pagerState = rememberPagerState()
val fling = PagerDefaults.flingBehavior(
state = pagerState, PagerSnapDistance.atMost(3)
@@ -114,6 +117,7 @@
HorizontalPager(
modifier = Modifier.weight(0.9f),
state = pagerState,
+ pageCount = PagesCount,
pageSize = PageSize.Fixed(96.dp),
flingBehavior = fling
) {
diff --git a/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/PagerSamples.kt b/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/PagerSamples.kt
index b95aeb5..bed4f40 100644
--- a/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/PagerSamples.kt
+++ b/compose/foundation/foundation/samples/src/main/java/androidx/compose/foundation/samples/PagerSamples.kt
@@ -30,8 +30,8 @@
import androidx.compose.foundation.pager.PageSize
import androidx.compose.foundation.pager.VerticalPager
import androidx.compose.foundation.pager.rememberPagerState
-import androidx.compose.material.Button
import androidx.compose.material.Text
+import androidx.compose.material.Button
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
@@ -47,10 +47,9 @@
@Composable
fun SimpleHorizontalPagerSample() {
// Creates a 1-pager/viewport horizontal pager with single page snapping
- val state = rememberPagerState { 10 }
HorizontalPager(
- state = state,
modifier = Modifier.fillMaxSize(),
+ pageCount = 10
) { page ->
Box(
modifier = Modifier
@@ -70,10 +69,9 @@
@Composable
fun SimpleVerticalPagerSample() {
// Creates a 1-pager/viewport vertical pager with single page snapping
- val state = rememberPagerState { 10 }
VerticalPager(
- state = state,
- modifier = Modifier.fillMaxSize()
+ modifier = Modifier.fillMaxSize(),
+ pageCount = 10
) { page ->
Box(
modifier = Modifier
@@ -93,10 +91,11 @@
@Composable
fun PagerWithStateSample() {
// You can use PagerState to define an initial page
- val state = rememberPagerState(initialPage = 5) { 10 }
+ val state = rememberPagerState(initialPage = 5)
HorizontalPager(
modifier = Modifier.fillMaxSize(),
- state = state
+ state = state,
+ pageCount = 10
) { page ->
Box(
modifier = Modifier
@@ -130,10 +129,9 @@
}
}
- val state = rememberPagerState { 10 }
HorizontalPager(
- state = state,
modifier = Modifier.fillMaxSize(),
+ pageCount = 10,
pageSize = CustomPageSize
) { page ->
Box(
@@ -153,11 +151,12 @@
@Sampled
@Composable
fun ObservingStateChangesInPagerStateSample() {
- val pagerState = rememberPagerState { 10 }
+ val pagerState = rememberPagerState()
Column(modifier = Modifier.fillMaxSize()) {
HorizontalPager(
modifier = Modifier.weight(0.9f),
- state = pagerState
+ state = pagerState,
+ pageCount = 10
) { page ->
Box(
modifier = Modifier
@@ -170,11 +169,9 @@
Text(text = page.toString(), fontSize = 32.sp)
}
}
- Column(
- modifier = Modifier
- .weight(0.1f)
- .fillMaxWidth()
- ) {
+ Column(modifier = Modifier
+ .weight(0.1f)
+ .fillMaxWidth()) {
Text(text = "Current Page: ${pagerState.currentPage}")
Text(text = "Target Page: ${pagerState.targetPage}")
Text(text = "Settled Page Offset: ${pagerState.settledPage}")
@@ -186,12 +183,13 @@
@Sampled
@Composable
fun AnimateScrollPageSample() {
- val state = rememberPagerState { 10 }
+ val state = rememberPagerState()
val animationScope = rememberCoroutineScope()
Column {
HorizontalPager(
modifier = Modifier.weight(0.7f),
- state = state
+ state = state,
+ pageCount = 10
) { page ->
Box(
modifier = Modifier
@@ -205,11 +203,7 @@
}
}
- Box(
- modifier = Modifier
- .weight(0.3f)
- .fillMaxWidth(), contentAlignment = Alignment.Center
- ) {
+ Box(modifier = Modifier.weight(0.3f).fillMaxWidth(), contentAlignment = Alignment.Center) {
Button(onClick = {
animationScope.launch {
state.animateScrollToPage(state.currentPage + 1)
@@ -225,12 +219,13 @@
@Sampled
@Composable
fun ScrollToPageSample() {
- val state = rememberPagerState { 10 }
+ val state = rememberPagerState()
val scrollScope = rememberCoroutineScope()
Column {
HorizontalPager(
modifier = Modifier.height(400.dp),
- state = state
+ state = state,
+ pageCount = 10
) { page ->
Box(
modifier = Modifier
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/BasePagerTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/BasePagerTest.kt
index 1ac3fd3..514a0b9 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/BasePagerTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/BasePagerTest.kt
@@ -69,7 +69,6 @@
lateinit var focusManager: FocusManager
lateinit var firstItemFocusRequester: FocusRequester
var composeView: View? = null
- lateinit var pagerState: PagerState
fun TouchInjectionScope.swipeWithVelocityAcrossMainAxis(velocity: Float, delta: Float? = null) {
val end = if (delta == null) {
@@ -108,10 +107,9 @@
}
internal fun createPager(
- initialPage: Int = 0,
- initialPageOffsetFraction: Float = 0f,
- pageCount: () -> Int = { DefaultPageCount },
+ state: PagerState,
modifier: Modifier = Modifier,
+ pageCount: () -> Int = { DefaultPageCount },
offscreenPageLimit: Int = config.beyondBoundsPageCount,
pageSize: () -> PageSize = { PageSize.Fill },
userScrollEnabled: Boolean = true,
@@ -126,9 +124,6 @@
) {
rule.setContent {
- val state = rememberPagerState(initialPage, initialPageOffsetFraction, pageCount).also {
- pagerState = it
- }
composeView = LocalView.current
focusManager = LocalFocusManager.current
val flingBehavior =
@@ -147,6 +142,7 @@
.nestedScroll(nestedScrollConnection)
) {
HorizontalOrVerticalPager(
+ pageCount = pageCount(),
state = state,
beyondBoundsPageCount = offscreenPageLimit,
modifier = modifier
@@ -263,7 +259,8 @@
@OptIn(ExperimentalFoundationApi::class)
@Composable
internal fun HorizontalOrVerticalPager(
- state: PagerState = rememberPagerState(pageCount = { DefaultPageCount }),
+ pageCount: Int,
+ state: PagerState = rememberPagerState(),
modifier: Modifier = Modifier,
userScrollEnabled: Boolean = true,
reverseLayout: Boolean = false,
@@ -277,6 +274,7 @@
) {
if (vertical) {
VerticalPager(
+ pageCount = pageCount,
state = state,
modifier = modifier,
userScrollEnabled = userScrollEnabled,
@@ -291,6 +289,7 @@
)
} else {
HorizontalPager(
+ pageCount = pageCount,
state = state,
modifier = modifier,
userScrollEnabled = userScrollEnabled,
@@ -371,3 +370,7 @@
PaddingValues(start = 16.dp),
PaddingValues(end = 16.dp)
)
+
+open class SingleOrientationPagerTest(
+ orientation: Orientation
+) : BasePagerTest(ParamConfig(orientation))
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/EmptyPagerTests.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/EmptyPagerTests.kt
index 3527b40..1680009 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/EmptyPagerTests.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/EmptyPagerTests.kt
@@ -33,8 +33,10 @@
@Test
fun checkNoPagesArePlaced() {
// Arrange
+ val state = PagerState()
+
// Act
- createPager(pageCount = { 0 }, modifier = Modifier.fillMaxSize())
+ createPager(state = state, modifier = Modifier.fillMaxSize(), pageCount = { 0 })
// Assert
rule.onNodeWithTag("0").assertDoesNotExist()
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PageLayoutPositionOnScrollingTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PageLayoutPositionOnScrollingTest.kt
index 6531eba..bd96983 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PageLayoutPositionOnScrollingTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PageLayoutPositionOnScrollingTest.kt
@@ -38,7 +38,8 @@
@Test
fun swipeForwardAndBackward_verifyPagesAreLaidOutCorrectly() {
// Arrange
- createPager(modifier = Modifier.fillMaxSize())
+ val state = PagerState()
+ createPager(state = state, modifier = Modifier.fillMaxSize())
val delta = pagerSize * 0.4f * scrollForwardSign
// Act and Assert - forward
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PageSizeTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PageSizeTest.kt
index 988a695..eebddc6 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PageSizeTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PageSizeTest.kt
@@ -36,9 +36,10 @@
@Test
fun pageSizeFill_onlySnappedItemIsDisplayed() {
// Arrange
+ val state = PagerState(5)
// Act
- createPager(initialPage = 5, modifier = Modifier.fillMaxSize())
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// Assert
rule.onNodeWithTag("4").assertDoesNotExist()
@@ -50,6 +51,7 @@
@Test
fun pagerSizeCustom_visibleItemsAreWithinViewport() {
// Arrange
+ val state = PagerState(5)
val pagerMode = object : PageSize {
override fun Density.calculateMainAxisPageSize(
availableSpace: Int,
@@ -61,7 +63,7 @@
// Act
createPager(
- initialPage = 5,
+ state = state,
modifier = Modifier.crossAxisSize(200.dp),
offscreenPageLimit = 0,
pageSize = { pagerMode }
@@ -69,14 +71,14 @@
// Assert
rule.runOnIdle {
- val visibleItems = pagerState.layoutInfo.visiblePagesInfo.size
+ val visibleItems = state.layoutInfo.visiblePagesInfo.size
val pageCount = with(rule.density) {
(pagerSize / (pageSize + config.pageSpacing.roundToPx()))
} + 1
Truth.assertThat(visibleItems).isEqualTo(pageCount)
}
- for (pageIndex in 5 until pagerState.layoutInfo.visiblePagesInfo.size + 4) {
+ for (pageIndex in 5 until state.layoutInfo.visiblePagesInfo.size + 4) {
confirmPageIsInCorrectPosition(5, pageIndex)
}
}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerAccessibilityTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerAccessibilityTest.kt
index 06cd075..ff8f42c 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerAccessibilityTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerAccessibilityTest.kt
@@ -52,22 +52,24 @@
@Test
fun accessibilityScroll_scrollToPage() {
- createPager(offscreenPageLimit = 1)
+ val state = PagerState()
+ createPager(state, offscreenPageLimit = 1)
- rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(0) }
+ rule.runOnIdle { assertThat(state.currentPage).isEqualTo(0) }
rule.onNodeWithTag("1").assertExists()
rule.onNodeWithTag("1").performScrollTo()
- rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(1) }
- rule.runOnIdle { assertThat(pagerState.currentPageOffsetFraction).isEqualTo(0.0f) }
+ rule.runOnIdle { assertThat(state.currentPage).isEqualTo(1) }
+ rule.runOnIdle { assertThat(state.currentPageOffsetFraction).isEqualTo(0.0f) }
}
@Test
fun accessibilityPaging_animateScrollToPage() {
- createPager(initialPage = 5, pageCount = { DefaultPageCount })
+ val state = PagerState(initialPage = 5)
+ createPager(state)
- rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(5) }
+ rule.runOnIdle { assertThat(state.currentPage).isEqualTo(5) }
val actionBackward = if (vertical) {
android.R.id.accessibilityActionPageUp
@@ -84,8 +86,8 @@
}
// Go to the previous page
- rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(4) }
- rule.runOnIdle { assertThat(pagerState.currentPageOffsetFraction).isEqualTo(0.0f) }
+ rule.runOnIdle { assertThat(state.currentPage).isEqualTo(4) }
+ rule.runOnIdle { assertThat(state.currentPageOffsetFraction).isEqualTo(0.0f) }
val actionForward = if (vertical) {
android.R.id.accessibilityActionPageDown
@@ -102,15 +104,16 @@
}
// Go to the next page
- rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(5) }
- rule.runOnIdle { assertThat(pagerState.currentPageOffsetFraction).isEqualTo(0.0f) }
+ rule.runOnIdle { assertThat(state.currentPage).isEqualTo(5) }
+ rule.runOnIdle { assertThat(state.currentPageOffsetFraction).isEqualTo(0.0f) }
}
@Test
fun userScrollEnabledIsOff_shouldNotAllowPageAccessibilityActions() {
// Arrange
+ val state = PagerState()
createPager(
- pageCount = { DefaultPageCount },
+ state = state,
userScrollEnabled = false,
modifier = Modifier.fillMaxSize()
)
@@ -126,22 +129,23 @@
@Test
fun focusScroll_forwardAndBackward_shouldGoToPage_pageShouldBeCorrectlyPlaced() {
// Arrange
- createPager(pageCount = { DefaultPageCount })
+ val state = PagerState()
+ createPager(state)
rule.runOnIdle { firstItemFocusRequester.requestFocus() }
// Act: move forward
rule.runOnIdle { focusManager.moveFocus(FocusDirection.Next) }
// Assert
- rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(1) }
- rule.runOnIdle { assertThat(pagerState.currentPageOffsetFraction).isEqualTo(0.0f) }
+ rule.runOnIdle { assertThat(state.currentPage).isEqualTo(1) }
+ rule.runOnIdle { assertThat(state.currentPageOffsetFraction).isEqualTo(0.0f) }
// Act: move backward
rule.runOnIdle { focusManager.moveFocus(FocusDirection.Previous) }
// Assert
- rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(0) }
- rule.runOnIdle { assertThat(pagerState.currentPageOffsetFraction).isEqualTo(0.0f) }
+ rule.runOnIdle { assertThat(state.currentPage).isEqualTo(0) }
+ rule.runOnIdle { assertThat(state.currentPageOffsetFraction).isEqualTo(0.0f) }
}
private fun <T> SemanticsNodeInteraction.withSemanticsNode(block: SemanticsNode.() -> T): T {
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerContentPaddingTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerContentPaddingTest.kt
index 3ca1e45..66adc7b 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerContentPaddingTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerContentPaddingTest.kt
@@ -74,10 +74,12 @@
@Test
fun contentPaddingIsApplied() {
+ val state = PagerState()
val containerSize = pageTotalSize * 2
val largePaddingSize = pageTotalSize
createPager(
+ state = state,
modifier = Modifier
.requiredSize(containerSize)
.testTag(PagerTag),
@@ -102,7 +104,7 @@
.assertCrossAxisSizeIsEqualTo(containerSize - smallPaddingSize * 2)
.assertMainAxisSizeIsEqualTo(pageTotalSize)
- pagerState.scrollBy(largePaddingSize)
+ state.scrollBy(largePaddingSize)
rule.onNodeWithTag(PageTag)
.assertStartPositionInRootIsEqualTo(0.dp)
@@ -111,7 +113,10 @@
@Test
fun contentPaddingIsNotAffectingScrollPosition() {
+ val state = PagerState()
+
createPager(
+ state = state,
modifier = Modifier
.requiredSize(pageTotalSize * 2)
.testTag(PagerTag),
@@ -127,17 +132,19 @@
)
}
- pagerState.assertScrollPosition(0, 0.dp)
+ state.assertScrollPosition(0, 0.dp)
- pagerState.scrollBy(pageTotalSize)
+ state.scrollBy(pageTotalSize)
- pagerState.assertScrollPosition(0, pageTotalSize)
+ state.assertScrollPosition(0, pageTotalSize)
}
@Test
fun scrollForwardItemWithinStartPaddingDisplayed() {
+ val state = PagerState()
val padding = pageTotalSize * 1.5f
createPager(
+ state = state,
modifier = Modifier
.requiredSize(padding * 2 + pageTotalSize)
.testTag(PagerTag),
@@ -159,9 +166,9 @@
rule.onNodeWithTag("2")
.assertStartPositionInRootIsEqualTo(pageTotalSize * 2 + padding)
- pagerState.scrollBy(padding)
+ state.scrollBy(padding)
- pagerState.assertScrollPosition(1, padding - pageTotalSize)
+ state.assertScrollPosition(1, padding - pageTotalSize)
rule.onNodeWithTag("0")
.assertStartPositionInRootIsEqualTo(0.dp)
@@ -175,8 +182,10 @@
@Test
fun scrollBackwardItemWithinStartPaddingDisplayed() {
+ val state = PagerState()
val padding = pageTotalSize * 1.5f
createPager(
+ state = state,
modifier = Modifier
.requiredSize(padding * 2 + pageTotalSize)
.testTag(PagerTag),
@@ -191,10 +200,10 @@
)
}
- pagerState.scrollBy(pageTotalSize * 3)
- pagerState.scrollBy(-pageTotalSize * 1.5f)
+ state.scrollBy(pageTotalSize * 3)
+ state.scrollBy(-pageTotalSize * 1.5f)
- pagerState.assertScrollPosition(1, pageTotalSize * 0.5f)
+ state.assertScrollPosition(1, pageTotalSize * 0.5f)
rule.onNodeWithTag("0")
.assertStartPositionInRootIsEqualTo(pageTotalSize * 1.5f - padding)
@@ -208,8 +217,10 @@
@Test
fun scrollForwardTillTheEnd() {
+ val state = PagerState()
val padding = pageTotalSize * 1.5f
createPager(
+ state = state,
modifier = Modifier
.requiredSize(padding * 2 + pageTotalSize)
.testTag(PagerTag),
@@ -224,9 +235,9 @@
)
}
- pagerState.scrollBy(pageTotalSize * 3)
+ state.scrollBy(pageTotalSize * 3)
- pagerState.assertScrollPosition(3, 0.dp)
+ state.assertScrollPosition(3, 0.dp)
rule.onNodeWithTag("1")
.assertStartPositionInRootIsEqualTo(pageTotalSize - padding)
@@ -236,9 +247,9 @@
.assertStartPositionInRootIsEqualTo(pageTotalSize * 3 - padding)
// there are no space to scroll anymore, so it should change nothing
- pagerState.scrollBy(10.dp)
+ state.scrollBy(10.dp)
- pagerState.assertScrollPosition(3, 0.dp)
+ state.assertScrollPosition(3, 0.dp)
rule.onNodeWithTag("1")
.assertStartPositionInRootIsEqualTo(pageTotalSize - padding)
@@ -250,8 +261,10 @@
@Test
fun scrollForwardTillTheEndAndABitBack() {
+ val state = PagerState()
val padding = pageTotalSize * 1.5f
createPager(
+ state = state,
modifier = Modifier
.requiredSize(padding * 2 + pageTotalSize)
.testTag(PagerTag),
@@ -266,10 +279,10 @@
)
}
- pagerState.scrollBy(pageTotalSize * 3)
- pagerState.scrollBy(-pageTotalSize / 2)
+ state.scrollBy(pageTotalSize * 3)
+ state.scrollBy(-pageTotalSize / 2)
- pagerState.assertScrollPosition(2, pageTotalSize / 2)
+ state.assertScrollPosition(2, pageTotalSize / 2)
rule.onNodeWithTag("1")
.assertStartPositionInRootIsEqualTo(pageTotalSize * 1.5f - padding)
@@ -282,16 +295,15 @@
@Test
fun contentPaddingAndWrapContent() {
rule.setContent {
- val state = rememberPagerState { 1 }
Box(modifier = Modifier.testTag(ContainerTag)) {
HorizontalOrVerticalPager(
- state = state,
contentPadding = PaddingValues(
beforeContentCrossAxis = 2.dp,
beforeContent = 4.dp,
afterContentCrossAxis = 6.dp,
afterContent = 8.dp
),
+ pageCount = 1,
pageSize = PageSize.Fixed(pageTotalSize)
) {
Spacer(
@@ -319,16 +331,15 @@
@Test
fun contentPaddingAndNoContent() {
rule.setContent {
- val state = rememberPagerState { 0 }
Box(modifier = Modifier.testTag(ContainerTag)) {
HorizontalOrVerticalPager(
- state = state,
contentPadding = PaddingValues(
beforeContentCrossAxis = 2.dp,
beforeContent = 4.dp,
afterContentCrossAxis = 6.dp,
afterContent = 8.dp
),
+ pageCount = 0,
pageSize = PageSize.Fixed(pageTotalSize)
) { }
}
@@ -344,16 +355,15 @@
@Test
fun contentPaddingAndZeroSizedItem() {
rule.setContent {
- val state = rememberPagerState { 1 }
Box(modifier = Modifier.testTag(ContainerTag)) {
HorizontalOrVerticalPager(
- state = state,
contentPadding = PaddingValues(
beforeContentCrossAxis = 2.dp,
beforeContent = 4.dp,
afterContentCrossAxis = 6.dp,
afterContent = 8.dp
),
+ pageCount = 1,
pageSize = PageSize.Fixed(0.dp)
) {
Box { }
@@ -373,8 +383,10 @@
val topPadding = pageTotalSize * 2
val bottomPadding = pageTotalSize / 2
val listSize = pageTotalSize * 3
+ val state = PagerState()
createPager(
reverseLayout = true,
+ state = state,
modifier = Modifier.requiredSize(listSize),
contentPadding = PaddingValues(
beforeContent = topPadding,
@@ -399,7 +411,7 @@
.assertStartPositionInRootIsEqualTo(-pageTotalSize / 2)
// Scroll to the top.
- pagerState.scrollBy(pageTotalSize * 2.5f)
+ state.scrollBy(pageTotalSize * 2.5f)
rule.onNodeWithTag("2").assertStartPositionInRootIsEqualTo(topPadding)
// Shouldn't be visible
@@ -412,8 +424,10 @@
val topPadding = pageTotalSize * 2
val bottomPadding = pageTotalSize * 2
val listSize = pageTotalSize * 3
+ val state = PagerState()
createPager(
reverseLayout = true,
+ state = state,
modifier = Modifier.requiredSize(listSize),
contentPadding = PaddingValues(
beforeContent = topPadding,
@@ -435,7 +449,7 @@
rule.onNodeWithTag("1").assertDoesNotExist()
// Scroll to the top.
- pagerState.scrollBy(pageTotalSize * 5f)
+ state.scrollBy(pageTotalSize * 5f)
rule.onNodeWithTag("2").assertStartPositionInRootIsEqualTo(topPadding)
// Shouldn't be visible
@@ -447,7 +461,7 @@
fun overscrollWithContentPadding() {
lateinit var state: PagerState
rule.setContent {
- state = rememberPagerState { 2 }
+ state = rememberPagerState()
Box(
modifier = Modifier
.testTag(ContainerTag)
@@ -456,6 +470,7 @@
HorizontalOrVerticalPager(
state = state,
contentPadding = PaddingValues(mainAxis = smallPaddingSize),
+ pageCount = 2,
pageSize = PageSize.Fixed(pageTotalSize)
) {
Box(
@@ -497,7 +512,7 @@
fun totalPaddingLargerParentSize_initialState() {
lateinit var state: PagerState
rule.setContent {
- state = rememberPagerState() { 4 }
+ state = rememberPagerState()
Box(
modifier = Modifier
.testTag(ContainerTag)
@@ -506,6 +521,7 @@
HorizontalOrVerticalPager(
state = state,
contentPadding = PaddingValues(mainAxis = pageTotalSize),
+ pageCount = 4,
pageSize = PageSize.Fixed(pageTotalSize)
) {
Box(
@@ -534,7 +550,7 @@
fun totalPaddingLargerParentSize_scrollByPadding() {
lateinit var state: PagerState
rule.setContent {
- state = rememberPagerState { 4 }
+ state = rememberPagerState()
Box(
modifier = Modifier
.testTag(ContainerTag)
@@ -543,6 +559,7 @@
HorizontalOrVerticalPager(
state = state,
contentPadding = PaddingValues(mainAxis = pageTotalSize),
+ pageCount = 4,
pageSize = PageSize.Fixed(pageTotalSize)
) {
Box(
@@ -575,7 +592,7 @@
fun totalPaddingLargerParentSize_scrollToLastItem() {
lateinit var state: PagerState
rule.setContent {
- state = rememberPagerState { 4 }
+ state = rememberPagerState()
Box(
modifier = Modifier
.testTag(ContainerTag)
@@ -584,6 +601,7 @@
HorizontalOrVerticalPager(
state = state,
contentPadding = PaddingValues(mainAxis = pageTotalSize),
+ pageCount = 4,
pageSize = PageSize.Fixed(pageTotalSize)
) {
Box(
@@ -616,7 +634,7 @@
fun totalPaddingLargerParentSize_scrollToLastItemByDelta() {
lateinit var state: PagerState
rule.setContent {
- state = rememberPagerState { 4 }
+ state = rememberPagerState()
Box(
modifier = Modifier
.testTag(ContainerTag)
@@ -626,6 +644,7 @@
state = state,
contentPadding = PaddingValues(mainAxis = pageTotalSize),
pageSize = PageSize.Fixed(pageTotalSize),
+ pageCount = 4
) {
Box(
Modifier
@@ -658,7 +677,7 @@
// the whole end content padding is displayed
lateinit var state: PagerState
rule.setContent {
- state = rememberPagerState { 4 }
+ state = rememberPagerState()
Box(
modifier = Modifier
.testTag(ContainerTag)
@@ -667,7 +686,8 @@
HorizontalOrVerticalPager(
state = state,
contentPadding = PaddingValues(mainAxis = pageTotalSize),
- pageSize = PageSize.Fixed(pageTotalSize)
+ pageSize = PageSize.Fixed(pageTotalSize),
+ pageCount = 4
) {
Box(
Modifier
@@ -696,7 +716,7 @@
fun eachPaddingLargerParentSize_initialState() {
lateinit var state: PagerState
rule.setContent {
- state = rememberPagerState { 4 }
+ state = rememberPagerState()
Box(
modifier = Modifier
.testTag(ContainerTag)
@@ -705,7 +725,8 @@
HorizontalOrVerticalPager(
state = state,
contentPadding = PaddingValues(mainAxis = pageTotalSize * 2),
- pageSize = PageSize.Fixed(pageTotalSize)
+ pageSize = PageSize.Fixed(pageTotalSize),
+ pageCount = 4
) {
Box(
Modifier
@@ -730,7 +751,7 @@
fun eachPaddingLargerParentSize_scrollByPadding() {
lateinit var state: PagerState
rule.setContent {
- state = rememberPagerState { 4 }
+ state = rememberPagerState()
Box(
modifier = Modifier
.testTag(ContainerTag)
@@ -739,7 +760,8 @@
HorizontalOrVerticalPager(
state = state,
contentPadding = PaddingValues(mainAxis = pageTotalSize * 2),
- pageSize = PageSize.Fixed(pageTotalSize)
+ pageSize = PageSize.Fixed(pageTotalSize),
+ pageCount = 4
) {
Box(
Modifier
@@ -771,7 +793,7 @@
fun eachPaddingLargerParentSize_scrollToLastItem() {
lateinit var state: PagerState
rule.setContent {
- state = rememberPagerState { 4 }
+ state = rememberPagerState()
Box(
modifier = Modifier
.testTag(ContainerTag)
@@ -780,7 +802,8 @@
HorizontalOrVerticalPager(
state = state,
contentPadding = PaddingValues(mainAxis = pageTotalSize * 2),
- pageSize = PageSize.Fixed(pageTotalSize)
+ pageSize = PageSize.Fixed(pageTotalSize),
+ pageCount = 4
) {
Box(
Modifier
@@ -815,7 +838,7 @@
fun eachPaddingLargerParentSize_scrollToLastItemByDelta() {
lateinit var state: PagerState
rule.setContent {
- state = rememberPagerState { 4 }
+ state = rememberPagerState()
Box(
modifier = Modifier
.testTag(ContainerTag)
@@ -824,7 +847,8 @@
HorizontalOrVerticalPager(
state = state,
contentPadding = PaddingValues(mainAxis = pageTotalSize * 2),
- pageSize = PageSize.Fixed(pageTotalSize)
+ pageSize = PageSize.Fixed(pageTotalSize),
+ pageCount = 4
) {
Box(
Modifier
@@ -860,7 +884,7 @@
// only the end content padding is displayed
lateinit var state: PagerState
rule.setContent {
- state = rememberPagerState { 4 }
+ state = rememberPagerState()
Box(
modifier = Modifier
.testTag(ContainerTag)
@@ -869,7 +893,8 @@
HorizontalOrVerticalPager(
state = state,
contentPadding = PaddingValues(mainAxis = pageTotalSize * 2),
- pageSize = PageSize.Fixed(pageTotalSize)
+ pageSize = PageSize.Fixed(pageTotalSize),
+ pageCount = 4
) {
Box(
Modifier
@@ -900,7 +925,7 @@
val padding = PaddingValues(start = 20.dp, end = 8.dp)
lateinit var state: PagerState
rule.setContent {
- state = rememberPagerState { 4 }
+ state = rememberPagerState()
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
HorizontalOrVerticalPager(
modifier = Modifier
@@ -908,6 +933,7 @@
.mainAxisSize(pageTotalSize * 2),
state = state,
contentPadding = padding,
+ pageCount = 4,
pageSize = PageSize.Fixed(pageTotalSize)
) {
Box(
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerContentTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerContentTest.kt
index 4f02a20..2c60da4 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerContentTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerContentTest.kt
@@ -16,10 +16,10 @@
package androidx.compose.foundation.pager
-import android.os.Build
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
@@ -30,39 +30,31 @@
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
-import androidx.compose.testutils.assertPixels
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.drawBehind
-import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.testTag
-import androidx.compose.ui.test.captureToImage
-import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performTouchInput
import androidx.compose.ui.test.swipe
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
-import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth
+import kotlin.test.assertContentEquals
import kotlin.test.assertTrue
-import org.junit.Rule
import org.junit.Test
-class PagerContentTest {
-
- @get:Rule
- val rule = createComposeRule()
+class PagerContentTest : SingleOrientationPagerTest(Orientation.Horizontal) {
@OptIn(ExperimentalFoundationApi::class)
@Test
fun pageContent_makeSureContainerOwnsOutsideModifiers() {
// Arrange
- lateinit var state: PagerState
+ val state = PagerState()
rule.setContent {
- HorizontalPager(
- state = rememberPagerState { 10 }.also { state = it },
+ HorizontalOrVerticalPager(
+ pageCount = 10,
+ state = state,
contentPadding = PaddingValues(horizontal = 32.dp),
pageSpacing = 4.dp,
modifier = Modifier
@@ -90,51 +82,45 @@
@OptIn(ExperimentalFoundationApi::class)
@Test
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
fun pageContent_makeSureInnerModifiersAreAppliedToPages() {
// Arrange
- val colors = listOf(Color.Blue, Color.Green, Color.Red)
+ val state = PagerState()
+ val drawingList = mutableListOf<Int>()
rule.setContent {
- HorizontalPager(
- state = rememberPagerState { colors.size },
+ HorizontalOrVerticalPager(
+ pageCount = 10,
+ state = state,
modifier = Modifier
- .width(6.dp)
- .testTag(PagerTestTag),
- pageSize = PageSize.Fixed(2.dp)
+ .width(100.dp)
+ .testTag("pager"),
+ pageSize = PageSize.Fixed(10.dp)
) { page ->
- val color = colors[page]
Box(
modifier = Modifier
- .testTag(page.toString())
- .width(2.dp)
- .height(6.dp)
- .zIndex(if (color == Color.Green) 1f else 0f)
- .drawBehind {
- drawRect(
- color,
- topLeft = Offset(-10.dp.toPx(), -10.dp.toPx()),
- size = Size(20.dp.toPx(), 20.dp.toPx())
- )
+ .background(Color.Black)
+ .size(100.dp)
+ .zIndex(if (page % 2 == 0) 100f else 50f)
+ .drawWithContent {
+ drawingList.add(page)
}
+ .testTag(page.toString())
)
}
}
- rule.onNodeWithTag(PagerTestTag)
- .captureToImage()
- .assertPixels { Color.Green }
+ rule.runOnIdle {
+ assertContentEquals(drawingList, listOf(1, 3, 5, 7, 9, 0, 2, 4, 6, 8))
+ }
}
@OptIn(ExperimentalFoundationApi::class)
@Test
fun scrollableState_isScrollableWhenChangingPages() {
val states = mutableMapOf<Int, ScrollState>()
- val pagerState = PagerStateImpl(
- initialPage = 0,
- initialPageOffsetFraction = 0.0f,
- updatedPageCount = { 2 })
+ val pagerState = PagerState()
rule.setContent {
HorizontalPager(
+ pageCount = 2,
state = pagerState,
modifier = Modifier
.testTag("pager")
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerCrossAxisTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerCrossAxisTest.kt
index e9c8ddf..33cc710 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerCrossAxisTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerCrossAxisTest.kt
@@ -54,7 +54,8 @@
rule.setContent {
InfiniteAxisRootComposable {
HorizontalOrVerticalPager(
- state = rememberPagerState(pageCount = { DefaultPageCount }),
+ pageCount = DefaultPageCount,
+ state = rememberPagerState(),
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerLayoutInfoTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerLayoutInfoTest.kt
index b9975e5..a2b44b83 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerLayoutInfoTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerLayoutInfoTest.kt
@@ -57,7 +57,10 @@
@Test
fun visiblePagesAreCorrect() {
+ val state = PagerState()
+
createPager(
+ state,
modifier = Modifier.requiredSize(pageSizeDp * 3.5f),
pageCount = { 5 },
pageSize = { PageSize.Fixed(pageSizeDp) }
@@ -65,13 +68,16 @@
Box(Modifier.requiredSize(pageSizeDp))
}
rule.runOnIdle {
- pagerState.layoutInfo.assertVisiblePages(count = 4)
+ state.layoutInfo.assertVisiblePages(count = 4)
}
}
@Test
fun visiblePagesAreCorrectAfterScroll() {
+ val state = PagerState()
+
createPager(
+ state,
modifier = Modifier.requiredSize(pageSizeDp * 3.5f),
pageCount = { 5 },
pageSize = { PageSize.Fixed(pageSizeDp) }
@@ -81,11 +87,11 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollToPage(1)
- pagerState.scrollBy(10f)
+ state.scrollToPage(1)
+ state.scrollBy(10f)
}
- pagerState.layoutInfo.assertVisiblePages(
+ state.layoutInfo.assertVisiblePages(
count = 4,
startIndex = 1,
startOffset = -10
@@ -95,7 +101,10 @@
@Test
fun visiblePagesAreCorrectWithSpacing() {
+ val state = PagerState()
+
createPager(
+ state,
modifier = Modifier.requiredSize(pageSizeDp * 3.5f),
pageCount = { 5 },
pageSpacing = pageSizeDp,
@@ -105,20 +114,22 @@
}
rule.runOnIdle {
- pagerState.layoutInfo.assertVisiblePages(count = 2, spacing = pageSizePx)
+ state.layoutInfo.assertVisiblePages(count = 2, spacing = pageSizePx)
}
}
@Test
fun visiblePagesAreObservableWhenWeScroll() {
+ val state = PagerState()
val currentInfo = StableRef<PagerLayoutInfo?>(null)
createPager(
+ state,
modifier = Modifier.requiredSize(pageSizeDp * 3.5f),
pageCount = { 5 },
pageSize = { PageSize.Fixed(pageSizeDp) },
additionalContent = {
- LaunchedEffect(key1 = pagerState) {
- snapshotFlow { pagerState.layoutInfo }.collect {
+ LaunchedEffect(key1 = state) {
+ snapshotFlow { state.layoutInfo }.collect {
currentInfo.value = it
}
}
@@ -131,7 +142,7 @@
// empty it here and scrolling should invoke observingFun again
currentInfo.value = null
runBlocking {
- pagerState.scrollToPage(1)
+ state.scrollToPage(1)
}
}
@@ -143,15 +154,17 @@
@Test
fun visiblePagesAreObservableWhenResize() {
+ val state = PagerState()
var pageSize by mutableStateOf(PageSize.Fixed(pageSizeDp * 2))
var currentInfo: PagerLayoutInfo? = null
@Composable
fun observingFun() {
- currentInfo = pagerState.layoutInfo
+ currentInfo = state.layoutInfo
}
createPager(
+ state,
pageCount = { 1 },
pageSize = { pageSize },
additionalContent = { observingFun() }
@@ -177,7 +190,10 @@
@Test
fun totalCountIsCorrect() {
var count by mutableStateOf(10)
+ val state = PagerState()
+
createPager(
+ state,
pageCount = { count },
pageSize = { PageSize.Fixed(10.dp) }
) {
@@ -185,12 +201,12 @@
}
rule.runOnIdle {
- assertThat(pagerState.layoutInfo.pagesCount).isEqualTo(10)
+ assertThat(state.layoutInfo.pagesCount).isEqualTo(10)
count = 20
}
rule.runOnIdle {
- assertThat(pagerState.layoutInfo.pagesCount).isEqualTo(20)
+ assertThat(state.layoutInfo.pagesCount).isEqualTo(20)
}
}
@@ -198,7 +214,10 @@
fun viewportOffsetsAndSizeAreCorrect() {
val sizePx = 45
val sizeDp = with(rule.density) { sizePx.toDp() }
+ val state = PagerState()
+
createPager(
+ state,
modifier = Modifier
.mainAxisSize(sizeDp)
.crossAxisSize(sizeDp * 2),
@@ -209,9 +228,9 @@
}
rule.runOnIdle {
- assertThat(pagerState.layoutInfo.viewportStartOffset).isEqualTo(0)
- assertThat(pagerState.layoutInfo.viewportEndOffset).isEqualTo(sizePx)
- assertThat(pagerState.layoutInfo.viewportSize).isEqualTo(
+ assertThat(state.layoutInfo.viewportStartOffset).isEqualTo(0)
+ assertThat(state.layoutInfo.viewportEndOffset).isEqualTo(sizePx)
+ assertThat(state.layoutInfo.viewportSize).isEqualTo(
if (vertical) IntSize(sizePx * 2, sizePx) else IntSize(sizePx, sizePx * 2)
)
}
@@ -230,8 +249,10 @@
val afterContentPaddingDp = with(rule.density) {
if (!reverseLayout) endPaddingPx.toDp() else startPaddingPx.toDp()
}
+ val state = PagerState()
createPager(
+ state,
modifier = Modifier
.mainAxisSize(sizeDp)
.crossAxisSize(sizeDp * 2),
@@ -248,10 +269,10 @@
}
rule.runOnIdle {
- assertThat(pagerState.layoutInfo.viewportStartOffset).isEqualTo(-startPaddingPx)
- assertThat(pagerState.layoutInfo.viewportEndOffset).isEqualTo(sizePx - startPaddingPx)
- assertThat(pagerState.layoutInfo.afterContentPadding).isEqualTo(endPaddingPx)
- assertThat(pagerState.layoutInfo.viewportSize).isEqualTo(
+ assertThat(state.layoutInfo.viewportStartOffset).isEqualTo(-startPaddingPx)
+ assertThat(state.layoutInfo.viewportEndOffset).isEqualTo(sizePx - startPaddingPx)
+ assertThat(state.layoutInfo.afterContentPadding).isEqualTo(endPaddingPx)
+ assertThat(state.layoutInfo.viewportSize).isEqualTo(
if (vertical) IntSize(sizePx * 2, sizePx) else IntSize(sizePx, sizePx * 2)
)
}
@@ -259,7 +280,10 @@
@Test
fun emptyPagesInVisiblePagesInfo() {
+ val state = PagerState()
+
createPager(
+ state,
pageCount = { 2 },
pageSize = { PageSize.Fixed(pageSizeDp) }
) {
@@ -267,9 +291,9 @@
}
rule.runOnIdle {
- assertThat(pagerState.layoutInfo.visiblePagesInfo.size).isEqualTo(2)
- assertThat(pagerState.layoutInfo.visiblePagesInfo.first().index).isEqualTo(0)
- assertThat(pagerState.layoutInfo.visiblePagesInfo.last().index).isEqualTo(1)
+ assertThat(state.layoutInfo.visiblePagesInfo.size).isEqualTo(2)
+ assertThat(state.layoutInfo.visiblePagesInfo.first().index).isEqualTo(0)
+ assertThat(state.layoutInfo.visiblePagesInfo.last().index).isEqualTo(1)
}
}
@@ -286,8 +310,10 @@
val afterContentPaddingDp = with(rule.density) {
if (!reverseLayout) endPaddingPx.toDp() else startPaddingPx.toDp()
}
+ val state = PagerState()
createPager(
+ state,
modifier = Modifier
.mainAxisSize(sizeDp)
.crossAxisSize(sizeDp * 2),
@@ -302,11 +328,11 @@
) {}
rule.runOnIdle {
- assertThat(pagerState.layoutInfo.viewportStartOffset).isEqualTo(-startPaddingPx)
- assertThat(pagerState.layoutInfo.viewportEndOffset).isEqualTo(sizePx - startPaddingPx)
- assertThat(pagerState.layoutInfo.beforeContentPadding).isEqualTo(startPaddingPx)
- assertThat(pagerState.layoutInfo.afterContentPadding).isEqualTo(endPaddingPx)
- assertThat(pagerState.layoutInfo.viewportSize).isEqualTo(
+ assertThat(state.layoutInfo.viewportStartOffset).isEqualTo(-startPaddingPx)
+ assertThat(state.layoutInfo.viewportEndOffset).isEqualTo(sizePx - startPaddingPx)
+ assertThat(state.layoutInfo.beforeContentPadding).isEqualTo(startPaddingPx)
+ assertThat(state.layoutInfo.afterContentPadding).isEqualTo(endPaddingPx)
+ assertThat(state.layoutInfo.viewportSize).isEqualTo(
if (vertical) IntSize(sizePx * 2, sizePx) else IntSize(sizePx, sizePx * 2)
)
}
@@ -325,8 +351,10 @@
val afterContentPaddingDp = with(rule.density) {
if (!reverseLayout) endPaddingPx.toDp() else startPaddingPx.toDp()
}
+ val state = PagerState()
createPager(
+ state,
modifier = Modifier
.mainAxisSize(sizeDp)
.crossAxisSize(sizeDp * 2),
@@ -343,11 +371,11 @@
}
rule.runOnIdle {
- assertThat(pagerState.layoutInfo.viewportStartOffset).isEqualTo(-startPaddingPx)
- assertThat(pagerState.layoutInfo.viewportEndOffset).isEqualTo(sizePx - startPaddingPx)
- assertThat(pagerState.layoutInfo.beforeContentPadding).isEqualTo(startPaddingPx)
- assertThat(pagerState.layoutInfo.afterContentPadding).isEqualTo(endPaddingPx)
- assertThat(pagerState.layoutInfo.viewportSize).isEqualTo(
+ assertThat(state.layoutInfo.viewportStartOffset).isEqualTo(-startPaddingPx)
+ assertThat(state.layoutInfo.viewportEndOffset).isEqualTo(sizePx - startPaddingPx)
+ assertThat(state.layoutInfo.beforeContentPadding).isEqualTo(startPaddingPx)
+ assertThat(state.layoutInfo.afterContentPadding).isEqualTo(endPaddingPx)
+ assertThat(state.layoutInfo.viewportSize).isEqualTo(
if (vertical) IntSize(sizePx * 2, sizePx) else IntSize(sizePx, sizePx * 2)
)
}
@@ -355,7 +383,10 @@
@Test
fun reverseLayoutIsCorrect() {
+ val state = PagerState()
+
createPager(
+ state,
modifier = Modifier.requiredSize(pageSizeDp * 3.5f),
pageCount = { 5 },
pageSize = { PageSize.Fixed(pageSizeDp) }
@@ -364,13 +395,17 @@
}
rule.runOnIdle {
- assertThat(pagerState.layoutInfo.reverseLayout).isEqualTo(param.reverseLayout)
+ assertThat(state.layoutInfo.reverseLayout).isEqualTo(param.reverseLayout)
}
}
@Test
fun orientationIsCorrect() {
+
+ val state = PagerState()
+
createPager(
+ state,
modifier = Modifier.requiredSize(pageSizeDp * 3.5f),
pageCount = { 5 },
pageSize = { PageSize.Fixed(pageSizeDp) }
@@ -379,7 +414,7 @@
}
rule.runOnIdle {
- assertThat(pagerState.layoutInfo.orientation)
+ assertThat(state.layoutInfo.orientation)
.isEqualTo(if (vertical) Orientation.Vertical else Orientation.Horizontal)
}
}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerNestedScrollContentTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerNestedScrollContentTest.kt
index 78b2758..ffa4aed 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerNestedScrollContentTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerNestedScrollContentTest.kt
@@ -20,6 +20,7 @@
import androidx.compose.foundation.gestures.ScrollableDefaults
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyList
@@ -34,10 +35,10 @@
import androidx.compose.ui.unit.Velocity
import androidx.compose.ui.unit.dp
import androidx.test.filters.LargeTest
+import org.junit.Assert.assertEquals
import com.google.common.truth.Truth.assertThat
import kotlin.math.absoluteValue
import kotlinx.coroutines.runBlocking
-import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -53,7 +54,8 @@
@Test
fun nestedScrollContent_shouldNotPropagateUnconsumedFlings() {
// Arrange
- createPager(pageCount = { DefaultPageCount }) {
+ val pagerState = PagerState()
+ createPager(pagerState) {
LazyList(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(0.dp),
@@ -91,6 +93,7 @@
@Test
fun nestedScrollContent_shouldPropagateCrossAxisUnconsumedFlings() {
// Arrange
+ val pagerState = PagerState()
var postFlingVelocity = Velocity.Zero
val dataCapturingConnection = object : NestedScrollConnection {
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
@@ -98,10 +101,7 @@
return Velocity.Zero
}
}
- createPager(
- pageCount = { DefaultPageCount },
- nestedScrollConnection = dataCapturingConnection
- ) {
+ createPager(pagerState, nestedScrollConnection = dataCapturingConnection) {
LazyList(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(0.dp),
@@ -141,8 +141,9 @@
@Test
fun nestedScrollContent_shouldPropagateScrollCorrectly() {
// Arrange
+ val pagerState = PagerState()
val lazyListState = LazyListState(9)
- createPager(pageCount = { DefaultPageCount }) {
+ createPager(pagerState) {
LazyList(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(0.dp),
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerOffscreenPageLimitPlacingTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerOffscreenPageLimitPlacingTest.kt
index aaf1a6f..4e93b07 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerOffscreenPageLimitPlacingTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerOffscreenPageLimitPlacingTest.kt
@@ -36,11 +36,8 @@
@Test
fun offscreenPageLimitIsUsed_shouldPlaceMoreItemsThanVisibleOnesAsWeScroll() {
// Arrange
- createPager(
- pageCount = { DefaultPageCount },
- modifier = Modifier.fillMaxSize(),
- offscreenPageLimit = 1
- )
+ val state = PagerState()
+ createPager(state = state, modifier = Modifier.fillMaxSize(), offscreenPageLimit = 1)
val delta = pagerSize * 1.4f * scrollForwardSign
repeat(DefaultAnimationRepetition) {
@@ -53,29 +50,25 @@
// Next page was placed
rule.runOnIdle {
Truth.assertThat(placed).contains(
- (pagerState.currentPage + 1)
+ (state.currentPage + 1)
.coerceAtMost(DefaultPageCount - 1)
)
}
}
rule.waitForIdle()
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ confirmPageIsInCorrectPosition(state.currentPage)
}
@Test
fun offscreenPageLimitIsUsed_shouldPlaceMoreItemsThanVisibleOnes() {
// Arrange
val initialIndex = 5
+ val state = PagerState(initialIndex)
// Act
- createPager(
- initialPage = initialIndex,
- pageCount = { DefaultPageCount },
- modifier = Modifier.fillMaxSize(),
- offscreenPageLimit = 2
- )
- val firstVisible = pagerState.layoutInfo.visiblePagesInfo.first().index
- val lastVisible = pagerState.layoutInfo.visiblePagesInfo.last().index
+ createPager(state = state, modifier = Modifier.fillMaxSize(), offscreenPageLimit = 2)
+ val firstVisible = state.layoutInfo.visiblePagesInfo.first().index
+ val lastVisible = state.layoutInfo.visiblePagesInfo.last().index
// Assert
rule.runOnIdle {
Truth.assertThat(placed).contains(firstVisible - 2)
@@ -92,19 +85,15 @@
@Test
fun offscreenPageLimitIsNotUsed_shouldNotPlaceMoreItemsThanVisibleOnes() {
// Arrange
+ val state = PagerState(5)
// Act
- createPager(
- initialPage = 5,
- pageCount = { DefaultPageCount },
- modifier = Modifier.fillMaxSize(),
- offscreenPageLimit = 0
- )
+ createPager(state = state, modifier = Modifier.fillMaxSize(), offscreenPageLimit = 0)
// Assert
rule.waitForIdle()
- val firstVisible = pagerState.layoutInfo.visiblePagesInfo.first().index
- val lastVisible = pagerState.layoutInfo.visiblePagesInfo.last().index
+ val firstVisible = state.layoutInfo.visiblePagesInfo.first().index
+ val lastVisible = state.layoutInfo.visiblePagesInfo.last().index
Truth.assertThat(placed).doesNotContain(firstVisible - 1)
Truth.assertThat(placed).contains(5)
Truth.assertThat(placed).doesNotContain(lastVisible + 1)
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerPinnableContainerTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerPinnableContainerTest.kt
index abd50db..a56661e 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerPinnableContainerTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerPinnableContainerTest.kt
@@ -18,10 +18,10 @@
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
+import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.list.assertIsNotPlaced
import androidx.compose.foundation.lazy.list.assertIsPlaced
import androidx.compose.runtime.Composable
@@ -37,7 +37,6 @@
import androidx.compose.ui.layout.PinnableContainer.PinnedHandle
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.assertIsNotDisplayed
-import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
@@ -45,22 +44,18 @@
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.runBlocking
import org.junit.Before
-import org.junit.Rule
import org.junit.Test
@OptIn(ExperimentalFoundationApi::class)
@MediumTest
-class PagerPinnableContainerTest {
-
- @get:Rule
- val rule = createComposeRule()
+class PagerPinnableContainerTest :
+ SingleOrientationPagerTest(orientation = Orientation.Horizontal) {
private var pinnableContainer: PinnableContainer? = null
private var pageSizeDp = Dp.Unspecified
private val composed = mutableSetOf<Int>()
- private lateinit var pagerState: PagerState
@Before
fun setup() {
@@ -86,11 +81,13 @@
@Test
fun pinnedPageIsComposedAndPlacedWhenScrolledOut() {
+ val state = PagerState()
// Arrange.
rule.setContent {
- HorizontalPager(
- state = rememberPagerState { 100 }.also { pagerState = it },
+ HorizontalOrVerticalPager(
+ state = state,
modifier = Modifier.size(pageSizeDp * 2),
+ pageCount = 100,
pageSize = PageSize.Fixed(pageSizeDp)
) { page ->
if (page == 1) {
@@ -107,7 +104,7 @@
rule.runOnIdle {
assertThat(composed).contains(1)
runBlocking {
- pagerState.scrollToPage(3)
+ state.scrollToPage(3)
}
}
@@ -129,11 +126,13 @@
@Test
fun pagesBetweenPinnedAndCurrentVisibleAreNotComposed() {
+ val state = PagerState()
// Arrange.
rule.setContent {
- HorizontalPager(
- state = rememberPagerState { 100 }.also { pagerState = it },
+ HorizontalOrVerticalPager(
+ state = state,
modifier = Modifier.size(pageSizeDp * 2),
+ pageCount = 100,
pageSize = PageSize.Fixed(pageSizeDp)
) { page ->
if (page == 1) {
@@ -149,7 +148,7 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollToPage(4)
+ state.scrollToPage(4)
}
}
@@ -169,11 +168,13 @@
@Test
fun pinnedPageAfterVisibleOnesIsComposedAndPlacedWhenScrolledOut() {
+ val state = PagerState()
// Arrange.
rule.setContent {
- HorizontalPager(
- state = rememberPagerState { 100 }.also { pagerState = it },
+ HorizontalOrVerticalPager(
+ state = state,
modifier = Modifier.size(pageSizeDp * 2),
+ pageCount = 100,
pageSize = PageSize.Fixed(pageSizeDp)
) { page ->
if (page == 4) {
@@ -185,7 +186,7 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollToPage(4)
+ state.scrollToPage(4)
}
}
@@ -201,7 +202,7 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollToPage(0)
+ state.scrollToPage(0)
}
}
@@ -222,11 +223,13 @@
@Test
fun pinnedPageCanBeUnpinned() {
+ val state = PagerState()
// Arrange.
rule.setContent {
- HorizontalPager(
- state = rememberPagerState { 100 }.also { pagerState = it },
+ HorizontalOrVerticalPager(
+ state = state,
modifier = Modifier.size(pageSizeDp * 2),
+ pageCount = 100,
pageSize = PageSize.Fixed(pageSizeDp)
) { page ->
if (page == 1) {
@@ -242,7 +245,7 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollToPage(3)
+ state.scrollToPage(3)
}
}
@@ -266,10 +269,11 @@
@Test
fun pinnedPageIsStillPinnedWhenReorderedAndNotVisibleAnymore() {
+ val state = PagerState()
var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
// Arrange.
rule.setContent {
- Pager(list, 2, 3)
+ Pager(state, list, 2, 3)
}
rule.runOnIdle {
@@ -295,10 +299,11 @@
}
@Composable
- fun Pager(dataset: List<Int>, pinnedPage: Int, visiblePages: Int) {
- HorizontalPager(
- state = rememberPagerState { dataset.size },
- modifier = Modifier.width(pageSizeDp * visiblePages),
+ fun Pager(state: PagerState, dataset: List<Int>, pinnedPage: Int, visiblePages: Int) {
+ HorizontalOrVerticalPager(
+ state = state,
+ modifier = Modifier.mainAxisSize(pageSizeDp * visiblePages),
+ pageCount = dataset.size,
pageSize = PageSize.Fixed(pageSizeDp),
key = { dataset[it] }
) { page ->
@@ -311,17 +316,13 @@
@Test
fun unpinnedWhenPagerStateChanges() {
- var state by mutableStateOf(
- PagerStateImpl(
- initialPage = 2,
- initialPageOffsetFraction = 0f,
- updatedPageCount = { 100 })
- )
+ var state by mutableStateOf(PagerState(initialPage = 2))
// Arrange.
rule.setContent {
- HorizontalPager(
+ HorizontalOrVerticalPager(
state = state,
modifier = Modifier.size(pageSizeDp * 2),
+ pageCount = 100,
pageSize = PageSize.Fixed(pageSizeDp)
) { page ->
if (page == 2) {
@@ -349,10 +350,7 @@
rule.runOnIdle {
assertThat(composed).contains(2)
- state = PagerStateImpl(
- initialPage = 0,
- initialPageOffsetFraction = 0f,
- updatedPageCount = { 100 })
+ state = PagerState()
}
rule.waitUntil {
@@ -366,17 +364,13 @@
@Test
fun pinAfterPagerStateChange() {
- var state by mutableStateOf(
- PagerStateImpl(
- initialPage = 0,
- initialPageOffsetFraction = 0f,
- updatedPageCount = { 100 })
- )
+ var state by mutableStateOf(PagerState())
// Arrange.
rule.setContent {
- HorizontalPager(
+ HorizontalOrVerticalPager(
state = state,
modifier = Modifier.size(pageSizeDp * 2),
+ pageCount = 100,
pageSize = PageSize.Fixed(pageSizeDp)
) { page ->
if (page == 0) {
@@ -387,10 +381,7 @@
}
rule.runOnIdle {
- state = PagerStateImpl(
- initialPage = 0,
- initialPageOffsetFraction = 0f,
- updatedPageCount = { 100 })
+ state = PagerState()
}
rule.runOnIdle {
@@ -416,12 +407,13 @@
@Test
fun pagesArePinnedBasedOnGlobalIndexes() {
+ val state = PagerState(initialPage = 3)
// Arrange.
- lateinit var state: PagerState
rule.setContent {
- HorizontalPager(
- state = rememberPagerState(initialPage = 3) { 100 }.also { state = it },
+ HorizontalOrVerticalPager(
+ state = state,
modifier = Modifier.size(pageSizeDp * 2),
+ pageCount = 100,
pageSize = PageSize.Fixed(pageSizeDp)
) { page ->
if (page == 3) {
@@ -459,13 +451,14 @@
@Test
fun pinnedPageIsRemovedWhenNotVisible() {
- lateinit var state: PagerState
+ val state = PagerState(initialPage = 3)
var pageCount by mutableStateOf(10)
// Arrange.
rule.setContent {
- HorizontalPager(
- state = rememberPagerState(initialPage = 3) { pageCount }.also { state = it },
+ HorizontalOrVerticalPager(
+ state = state,
modifier = Modifier.size(pageSizeDp * 2),
+ pageCount = pageCount,
pageSize = PageSize.Fixed(pageSizeDp)
) { page ->
if (page == 3) {
@@ -503,10 +496,11 @@
@Test
fun pinnedPageIsRemovedWhenVisible() {
+ val state = PagerState()
var pages by mutableStateOf(listOf(0, 1, 2))
// Arrange.
rule.setContent {
- Pager(dataset = pages, pinnedPage = 1, visiblePages = 2)
+ Pager(state = state, dataset = pages, pinnedPage = 1, visiblePages = 2)
}
rule.runOnIdle {
@@ -528,11 +522,13 @@
@Test
fun pinnedMultipleTimes() {
+ val state = PagerState(0)
// Arrange.
rule.setContent {
- HorizontalPager(
- state = rememberPagerState { 100 }.also { pagerState = it },
+ HorizontalOrVerticalPager(
+ state = state,
modifier = Modifier.size(pageSizeDp * 2),
+ pageCount = 100,
pageSize = PageSize.Fixed(pageSizeDp)
) { page ->
if (page == 1) {
@@ -553,7 +549,7 @@
handles.add(requireNotNull(pinnableContainer).pin())
assertThat(composed).contains(0)
runBlocking {
- pagerState.scrollToPage(3)
+ state.scrollToPage(3)
}
}
@@ -587,8 +583,8 @@
// Arrange.
rule.setContent {
CompositionLocalProvider(LocalPinnableContainer provides parentContainer) {
- HorizontalPager(
- state = rememberPagerState { 1 },
+ HorizontalOrVerticalPager(
+ pageCount = 1,
pageSize = PageSize.Fixed(pageSizeDp)
) {
pinnableContainer = LocalPinnableContainer.current
@@ -631,8 +627,8 @@
// Arrange.
rule.setContent {
CompositionLocalProvider(LocalPinnableContainer provides parentContainer) {
- HorizontalPager(
- state = rememberPagerState { 1 },
+ HorizontalOrVerticalPager(
+ pageCount = 1,
pageSize = PageSize.Fixed(pageSizeDp)
) {
pinnableContainer = LocalPinnableContainer.current
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerPrefetcherTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerPrefetcherTest.kt
index 18ab68b..cedcfd6 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerPrefetcherTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerPrefetcherTest.kt
@@ -52,6 +52,7 @@
var pageSizePx = 30
val pageSizeDp = with(rule.density) { pageSizePx.toDp() }
+ lateinit var state: PagerState
@Test
fun notPrefetchingForwardInitially() {
@@ -75,7 +76,7 @@
val preFetchIndex = 2
rule.runOnIdle {
runBlocking {
- pagerState.scrollBy(5f)
+ state.scrollBy(5f)
}
}
@@ -93,7 +94,7 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollBy(-5f)
+ state.scrollBy(-5f)
}
}
@@ -112,7 +113,7 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollBy(5f)
+ state.scrollBy(5f)
}
}
var prefetchIndex = initialIndex + 2
@@ -125,8 +126,8 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollBy(-2f)
- pagerState.scrollBy(-1f)
+ state.scrollBy(-2f)
+ state.scrollBy(-1f)
}
}
@@ -145,7 +146,7 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollBy(5f)
+ state.scrollBy(5f)
}
}
@@ -153,8 +154,8 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollBy(pageSizePx / 2f)
- pagerState.scrollBy(pageSizePx / 2f)
+ state.scrollBy(pageSizePx / 2f)
+ state.scrollBy(pageSizePx / 2f)
}
}
@@ -176,7 +177,7 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollBy(-5f)
+ state.scrollBy(-5f)
}
}
@@ -184,8 +185,8 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollBy(-pageSizePx / 2f)
- pagerState.scrollBy(-pageSizePx / 2f)
+ state.scrollBy(-pageSizePx / 2f)
+ state.scrollBy(-pageSizePx / 2f)
}
}
@@ -206,7 +207,7 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollBy(5f)
+ state.scrollBy(5f)
}
}
@@ -221,8 +222,8 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollBy(-2f)
- pagerState.scrollBy(-1f)
+ state.scrollBy(-2f)
+ state.scrollBy(-1f)
}
}
@@ -258,7 +259,7 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollBy(5f)
+ state.scrollBy(5f)
}
}
@@ -272,7 +273,7 @@
rule.runOnIdle {
runBlocking {
- pagerState.scrollBy(-2f)
+ state.scrollBy(-2f)
}
}
@@ -297,10 +298,11 @@
) { constraints ->
val placeable = if (emit) {
subcompose(Unit) {
- pagerState = rememberPagerState { 1000 }
+ state = rememberPagerState()
HorizontalOrVerticalPager(
modifier = Modifier.mainAxisSize(pageSizeDp * 1.5f),
- state = pagerState
+ state = state,
+ pageCount = 1000
) {
Spacer(
Modifier
@@ -326,7 +328,7 @@
rule.runOnIdle {
// this will schedule the prefetching
runBlocking(AutoTestFrameClock()) {
- pagerState.scrollBy(pageSize.toFloat())
+ state.scrollBy(pageSize.toFloat())
}
// then we synchronously dispose LazyColumn
emit = false
@@ -340,10 +342,11 @@
fun snappingToOtherPositionWhilePrefetchIsScheduled() {
val composedItems = mutableListOf<Int>()
rule.setContent {
- pagerState = rememberPagerState { 1000 }
+ state = rememberPagerState()
HorizontalOrVerticalPager(
modifier = Modifier.mainAxisSize(pageSizeDp * 1.5f),
- state = pagerState
+ state = state,
+ pageCount = 1000
) {
composedItems.add(it)
Spacer(
@@ -364,10 +367,10 @@
runBlocking(AutoTestFrameClock()) {
// this will move the viewport so pages 1 and 2 are visible
// and schedule a prefetching for 3
- pagerState.scrollBy(pageSize.toFloat())
+ state.scrollBy(pageSize.toFloat())
// then we move so that pages 100 and 101 are visible.
// this should cancel the prefetch for 3
- pagerState.scrollToPage(100)
+ state.scrollToPage(100)
}
}
@@ -390,14 +393,14 @@
runBlocking(AutoTestFrameClock()) {
// this will move the viewport so pages 1-2 are visible
// and schedule a prefetching for 3
- pagerState.scrollBy(pageSizePx.toFloat())
+ state.scrollBy(pageSizePx.toFloat())
// move viewport by screen size to pages 4-5, so page 3 is just behind
// the first visible page
- pagerState.scrollBy(pageSizePx * 3f)
+ state.scrollBy(pageSizePx * 3f)
// move scroll further to pages 5-6, so page 3 is reused
- pagerState.scrollBy(pageSizePx.toFloat())
+ state.scrollBy(pageSizePx.toFloat())
}
}
@@ -406,7 +409,7 @@
rule.runOnIdle {
runBlocking(AutoTestFrameClock()) {
// scroll again to ensure page 3 was dropped
- pagerState.scrollBy(pageSizePx * 100f)
+ state.scrollBy(pageSizePx * 100f)
}
}
@@ -436,13 +439,16 @@
reverseLayout: Boolean = false,
contentPadding: PaddingValues = PaddingValues(0.dp)
) {
+ state = PagerState(
+ initialPage = initialPage,
+ initialPageOffsetFraction = initialPageOffsetFraction
+ )
createPager(
+ state = state,
modifier = Modifier.mainAxisSize(pageSizeDp * 1.5f),
reverseLayout = reverseLayout,
contentPadding = contentPadding,
offscreenPageLimit = paramConfig.beyondBoundsPageCount,
- initialPage = initialPage,
- initialPageOffsetFraction = initialPageOffsetFraction,
pageCount = { 100 },
pageSize = {
object : PageSize {
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerScrollingTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerScrollingTest.kt
index 60a7995..14eabb4 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerScrollingTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerScrollingTest.kt
@@ -41,10 +41,8 @@
@Test
fun swipeWithLowVelocity_shouldBounceBack() {
// Arrange
- createPager(
- initialPage = 5,
- modifier = Modifier.fillMaxSize()
- )
+ val state = PagerState(5)
+ createPager(state = state, modifier = Modifier.fillMaxSize())
val delta = pagerSize * 0.4f * scrollForwardSign
// Act - forward
@@ -77,11 +75,8 @@
@Test
fun swipeWithHighVelocity_shouldGoToNextPage() {
// Arrange
- createPager(
- initialPage = 5,
-
- modifier = Modifier.fillMaxSize()
- )
+ val state = PagerState(5)
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// make sure the scroll distance is not enough to go to next page
val delta = pagerSize * 0.4f * scrollForwardSign
@@ -115,11 +110,8 @@
@Test
fun swipeWithHighVelocity_overHalfPage_shouldGoToNextPage() {
// Arrange
- createPager(
- initialPage = 5,
-
- modifier = Modifier.fillMaxSize()
- )
+ val state = PagerState(5)
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// make sure the scroll distance is not enough to go to next page
val delta = pagerSize * 0.8f * scrollForwardSign
@@ -153,11 +145,8 @@
@Test
fun scrollWithoutVelocity_shouldSettlingInClosestPage() {
// Arrange
- createPager(
- initialPage = 5,
-
- modifier = Modifier.fillMaxSize()
- )
+ val state = PagerState(5)
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// This will scroll 1 whole page before flinging
val delta = pagerSize * 1.4f * scrollForwardSign
@@ -168,9 +157,9 @@
rule.waitForIdle()
// Assert
- assertThat(pagerState.currentPage).isAtMost(7)
- rule.onNodeWithTag("${pagerState.currentPage}").assertIsDisplayed()
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ assertThat(state.currentPage).isAtMost(7)
+ rule.onNodeWithTag("${state.currentPage}").assertIsDisplayed()
+ confirmPageIsInCorrectPosition(state.currentPage)
// Act - backward
onPager().performTouchInput {
@@ -179,20 +168,21 @@
rule.waitForIdle()
// Assert
- assertThat(pagerState.currentPage).isAtLeast(5)
- rule.onNodeWithTag("${pagerState.currentPage}").assertIsDisplayed()
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ assertThat(state.currentPage).isAtLeast(5)
+ rule.onNodeWithTag("${state.currentPage}").assertIsDisplayed()
+ confirmPageIsInCorrectPosition(state.currentPage)
}
@Test
fun scrollWithSameVelocity_shouldYieldSameResult_forward() {
// Arrange
var initialPage = 1
+ val state = PagerState(initialPage)
createPager(
pageSize = { PageSize.Fixed(200.dp) },
- initialPage = initialPage,
- pageCount = { 100 },
+ state = state,
modifier = Modifier.fillMaxSize(),
+ pageCount = { 100 },
snappingPage = PagerSnapDistance.atMost(3)
)
// This will scroll 0.5 page before flinging
@@ -204,13 +194,13 @@
}
rule.waitForIdle()
- val pageDisplacement = pagerState.currentPage - initialPage
+ val pageDisplacement = state.currentPage - initialPage
// Repeat starting from different places
// reset
initialPage = 10
rule.runOnIdle {
- runBlocking { pagerState.scrollToPage(initialPage) }
+ runBlocking { state.scrollToPage(initialPage) }
}
onPager().performTouchInput {
@@ -218,11 +208,11 @@
}
rule.waitForIdle()
- assertThat(pagerState.currentPage - initialPage).isEqualTo(pageDisplacement)
+ assertThat(state.currentPage - initialPage).isEqualTo(pageDisplacement)
initialPage = 50
rule.runOnIdle {
- runBlocking { pagerState.scrollToPage(initialPage) }
+ runBlocking { state.scrollToPage(initialPage) }
}
onPager().performTouchInput {
@@ -230,18 +220,19 @@
}
rule.waitForIdle()
- assertThat(pagerState.currentPage - initialPage).isEqualTo(pageDisplacement)
+ assertThat(state.currentPage - initialPage).isEqualTo(pageDisplacement)
}
@Test
fun scrollWithSameVelocity_shouldYieldSameResult_backward() {
// Arrange
var initialPage = 90
+ val state = PagerState(initialPage)
createPager(
pageSize = { PageSize.Fixed(200.dp) },
- initialPage = initialPage,
- pageCount = { 100 },
+ state = state,
modifier = Modifier.fillMaxSize(),
+ pageCount = { 100 },
snappingPage = PagerSnapDistance.atMost(3)
)
// This will scroll 0.5 page before flinging
@@ -253,13 +244,13 @@
}
rule.waitForIdle()
- val pageDisplacement = pagerState.currentPage - initialPage
+ val pageDisplacement = state.currentPage - initialPage
// Repeat starting from different places
// reset
initialPage = 70
rule.runOnIdle {
- runBlocking { pagerState.scrollToPage(initialPage) }
+ runBlocking { state.scrollToPage(initialPage) }
}
onPager().performTouchInput {
@@ -267,11 +258,11 @@
}
rule.waitForIdle()
- assertThat(pagerState.currentPage - initialPage).isEqualTo(pageDisplacement)
+ assertThat(state.currentPage - initialPage).isEqualTo(pageDisplacement)
initialPage = 30
rule.runOnIdle {
- runBlocking { pagerState.scrollToPage(initialPage) }
+ runBlocking { state.scrollToPage(initialPage) }
}
onPager().performTouchInput {
@@ -279,7 +270,7 @@
}
rule.waitForIdle()
- assertThat(pagerState.currentPage - initialPage).isEqualTo(pageDisplacement)
+ assertThat(state.currentPage - initialPage).isEqualTo(pageDisplacement)
}
companion object {
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerStateTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerStateTest.kt
index 6b97a8e..6e5d7ee 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerStateTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerStateTest.kt
@@ -26,8 +26,6 @@
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
-import androidx.compose.ui.layout.onSizeChanged
-import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.StateRestorationTester
import androidx.compose.ui.test.onNodeWithTag
@@ -53,7 +51,7 @@
@Test
fun pagerStateNotAttached_shouldReturnDefaultValues_andChangeAfterAttached() = runBlocking {
// Arrange
- val state = PagerStateImpl(5, 0.2f) { DefaultPageCount }
+ val state = PagerState(initialPage = 5, initialPageOffsetFraction = 0.2f)
assertThat(state.currentPage).isEqualTo(5)
assertThat(state.currentPageOffsetFraction).isEqualTo(0.2f)
@@ -61,21 +59,7 @@
val currentPage = derivedStateOf { state.currentPage }
val currentPageOffsetFraction = derivedStateOf { state.currentPageOffsetFraction }
- rule.setContent {
- HorizontalOrVerticalPager(
- state = state,
- modifier = Modifier
- .fillMaxSize()
- .testTag(PagerTestTag)
- .onSizeChanged { pagerSize = if (vertical) it.height else it.width },
- pageSize = PageSize.Fill,
- reverseLayout = config.reverseLayout,
- pageSpacing = config.pageSpacing,
- contentPadding = config.mainAxisContentPadding,
- ) {
- Page(index = it)
- }
- }
+ createPager(state = state, modifier = Modifier.fillMaxSize())
withContext(Dispatchers.Main + AutoTestFrameClock()) {
state.scrollToPage(state.currentPage + 1)
@@ -90,15 +74,16 @@
@Test
fun scrollToPage_shouldPlacePagesCorrectly() = runBlocking {
// Arrange
- createPager(modifier = Modifier.fillMaxSize())
+ val state = PagerState()
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// Act and Assert
repeat(DefaultAnimationRepetition) {
- assertThat(pagerState.currentPage).isEqualTo(it)
+ assertThat(state.currentPage).isEqualTo(it)
withContext(Dispatchers.Main + AutoTestFrameClock()) {
- pagerState.scrollToPage(pagerState.currentPage + 1)
+ state.scrollToPage(state.currentPage + 1)
}
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ confirmPageIsInCorrectPosition(state.currentPage)
}
}
@@ -106,312 +91,314 @@
@Test
fun scrollToPage_usedOffset_shouldPlacePagesCorrectly() = runBlocking {
// Arrange
-
+ val state = PagerState()
suspend fun scrollToPageWithOffset(page: Int, offset: Float) {
withContext(Dispatchers.Main + AutoTestFrameClock()) {
- pagerState.scrollToPage(page, offset)
+ state.scrollToPage(page, offset)
}
}
// Arrange
- createPager(modifier = Modifier.fillMaxSize())
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// Act
scrollToPageWithOffset(10, 0.5f)
// Assert
- confirmPageIsInCorrectPosition(pagerState.currentPage, 10, pageOffset = 0.5f)
+ confirmPageIsInCorrectPosition(state.currentPage, 10, pageOffset = 0.5f)
// Act
scrollToPageWithOffset(4, 0.2f)
// Assert
- confirmPageIsInCorrectPosition(pagerState.currentPage, 4, pageOffset = 0.2f)
+ confirmPageIsInCorrectPosition(state.currentPage, 4, pageOffset = 0.2f)
// Act
scrollToPageWithOffset(12, -0.4f)
// Assert
- confirmPageIsInCorrectPosition(pagerState.currentPage, 12, pageOffset = -0.4f)
+ confirmPageIsInCorrectPosition(state.currentPage, 12, pageOffset = -0.4f)
// Act
scrollToPageWithOffset(DefaultPageCount - 1, 0.5f)
// Assert
- confirmPageIsInCorrectPosition(pagerState.currentPage, DefaultPageCount - 1)
+ confirmPageIsInCorrectPosition(state.currentPage, DefaultPageCount - 1)
// Act
scrollToPageWithOffset(0, -0.5f)
// Assert
- confirmPageIsInCorrectPosition(pagerState.currentPage, 0)
+ confirmPageIsInCorrectPosition(state.currentPage, 0)
}
@Test
fun scrollToPage_longSkipShouldNotPlaceIntermediatePages() = runBlocking {
// Arrange
-
- createPager(modifier = Modifier.fillMaxSize())
+ val state = PagerState()
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// Act
- assertThat(pagerState.currentPage).isEqualTo(0)
+ assertThat(state.currentPage).isEqualTo(0)
withContext(Dispatchers.Main + AutoTestFrameClock()) {
- pagerState.scrollToPage(DefaultPageCount - 1)
+ state.scrollToPage(DefaultPageCount - 1)
}
// Assert
rule.runOnIdle {
- assertThat(pagerState.currentPage).isEqualTo(DefaultPageCount - 1)
+ assertThat(state.currentPage).isEqualTo(DefaultPageCount - 1)
assertThat(placed).doesNotContain(DefaultPageCount / 2 - 1)
assertThat(placed).doesNotContain(DefaultPageCount / 2)
assertThat(placed).doesNotContain(DefaultPageCount / 2 + 1)
}
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ confirmPageIsInCorrectPosition(state.currentPage)
}
@Test
fun animateScrollToPage_shouldPlacePagesCorrectly() = runBlocking {
// Arrange
-
- createPager(modifier = Modifier.fillMaxSize())
+ val state = PagerState()
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// Act and Assert
repeat(DefaultAnimationRepetition) {
- assertThat(pagerState.currentPage).isEqualTo(it)
+ assertThat(state.currentPage).isEqualTo(it)
withContext(Dispatchers.Main + AutoTestFrameClock()) {
- pagerState.animateScrollToPage(pagerState.currentPage + 1)
+ state.animateScrollToPage(state.currentPage + 1)
}
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ confirmPageIsInCorrectPosition(state.currentPage)
}
}
@Test
fun animateScrollToPage_usedOffset_shouldPlacePagesCorrectly() = runBlocking {
// Arrange
-
+ val state = PagerState()
suspend fun animateScrollToPageWithOffset(page: Int, offset: Float) {
withContext(Dispatchers.Main + AutoTestFrameClock()) {
- pagerState.animateScrollToPage(page, offset)
+ state.animateScrollToPage(page, offset)
}
}
// Arrange
- createPager(modifier = Modifier.fillMaxSize())
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// Act
animateScrollToPageWithOffset(10, 0.5f)
// Assert
- confirmPageIsInCorrectPosition(pagerState.currentPage, 10, pageOffset = 0.5f)
+ confirmPageIsInCorrectPosition(state.currentPage, 10, pageOffset = 0.5f)
// Act
animateScrollToPageWithOffset(4, 0.2f)
// Assert
- confirmPageIsInCorrectPosition(pagerState.currentPage, 4, pageOffset = 0.2f)
+ confirmPageIsInCorrectPosition(state.currentPage, 4, pageOffset = 0.2f)
// Act
animateScrollToPageWithOffset(12, -0.4f)
// Assert
- confirmPageIsInCorrectPosition(pagerState.currentPage, 12, pageOffset = -0.4f)
+ confirmPageIsInCorrectPosition(state.currentPage, 12, pageOffset = -0.4f)
// Act
animateScrollToPageWithOffset(DefaultPageCount - 1, 0.5f)
// Assert
- confirmPageIsInCorrectPosition(pagerState.currentPage, DefaultPageCount - 1)
+ confirmPageIsInCorrectPosition(state.currentPage, DefaultPageCount - 1)
// Act
animateScrollToPageWithOffset(0, -0.5f)
// Assert
- confirmPageIsInCorrectPosition(pagerState.currentPage, 0)
+ confirmPageIsInCorrectPosition(state.currentPage, 0)
}
@Test
fun animateScrollToPage_longSkipShouldNotPlaceIntermediatePages() = runBlocking {
// Arrange
-
- createPager(modifier = Modifier.fillMaxSize())
+ val state = PagerState()
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// Act
- assertThat(pagerState.currentPage).isEqualTo(0)
+ assertThat(state.currentPage).isEqualTo(0)
withContext(Dispatchers.Main + AutoTestFrameClock()) {
- pagerState.animateScrollToPage(DefaultPageCount - 1)
+ state.animateScrollToPage(DefaultPageCount - 1)
}
// Assert
rule.runOnIdle {
- assertThat(pagerState.currentPage).isEqualTo(DefaultPageCount - 1)
+ assertThat(state.currentPage).isEqualTo(DefaultPageCount - 1)
assertThat(placed).doesNotContain(DefaultPageCount / 2 - 1)
assertThat(placed).doesNotContain(DefaultPageCount / 2)
assertThat(placed).doesNotContain(DefaultPageCount / 2 + 1)
}
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ confirmPageIsInCorrectPosition(state.currentPage)
}
@Test
fun scrollToPage_shouldCoerceWithinRange() = runBlocking {
// Arrange
-
- createPager(modifier = Modifier.fillMaxSize())
+ val state = PagerState()
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// Act
- assertThat(pagerState.currentPage).isEqualTo(0)
+ assertThat(state.currentPage).isEqualTo(0)
withContext(Dispatchers.Main + AutoTestFrameClock()) {
- pagerState.scrollToPage(DefaultPageCount)
+ state.scrollToPage(DefaultPageCount)
}
// Assert
- rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(DefaultPageCount - 1) }
+ rule.runOnIdle { assertThat(state.currentPage).isEqualTo(DefaultPageCount - 1) }
// Act
withContext(Dispatchers.Main + AutoTestFrameClock()) {
- pagerState.scrollToPage(-1)
+ state.scrollToPage(-1)
}
// Assert
- rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(0) }
+ rule.runOnIdle { assertThat(state.currentPage).isEqualTo(0) }
}
@Test
fun scrollToPage_usingLaunchedEffect() {
-
- createPager(additionalContent = {
- LaunchedEffect(pagerState) {
- pagerState.scrollToPage(10)
+ val state = PagerState()
+ createPager(state, additionalContent = {
+ LaunchedEffect(state) {
+ state.scrollToPage(10)
}
})
rule.waitForIdle()
- assertThat(pagerState.currentPage).isEqualTo(10)
+ assertThat(state.currentPage).isEqualTo(10)
confirmPageIsInCorrectPosition(10)
}
@Test
fun scrollToPageWithOffset_usingLaunchedEffect() {
- createPager(additionalContent = {
- LaunchedEffect(pagerState) {
- pagerState.scrollToPage(10, 0.4f)
+ val state = PagerState()
+ createPager(state, additionalContent = {
+ LaunchedEffect(state) {
+ state.scrollToPage(10, 0.4f)
}
})
rule.waitForIdle()
- assertThat(pagerState.currentPage).isEqualTo(10)
+ assertThat(state.currentPage).isEqualTo(10)
confirmPageIsInCorrectPosition(10, pageOffset = 0.4f)
}
@Test
fun animateScrollToPage_shouldCoerceWithinRange() = runBlocking {
// Arrange
-
- createPager(modifier = Modifier.fillMaxSize())
+ val state = PagerState()
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// Act
- assertThat(pagerState.currentPage).isEqualTo(0)
+ assertThat(state.currentPage).isEqualTo(0)
withContext(Dispatchers.Main + AutoTestFrameClock()) {
- pagerState.animateScrollToPage(DefaultPageCount)
+ state.animateScrollToPage(DefaultPageCount)
}
// Assert
- rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(DefaultPageCount - 1) }
+ rule.runOnIdle { assertThat(state.currentPage).isEqualTo(DefaultPageCount - 1) }
// Act
withContext(Dispatchers.Main + AutoTestFrameClock()) {
- pagerState.animateScrollToPage(-1)
+ state.animateScrollToPage(-1)
}
// Assert
- rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(0) }
+ rule.runOnIdle { assertThat(state.currentPage).isEqualTo(0) }
}
@Test
fun animateScrollToPage_moveToSamePageWithOffset_shouldScroll() = runBlocking {
// Arrange
- createPager(initialPage = 5, modifier = Modifier.fillMaxSize())
+ val state = PagerState(initialPage = 5)
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// Act
- assertThat(pagerState.currentPage).isEqualTo(5)
+ assertThat(state.currentPage).isEqualTo(5)
withContext(Dispatchers.Main + AutoTestFrameClock()) {
- pagerState.animateScrollToPage(5, 0.4f)
+ state.animateScrollToPage(5, 0.4f)
}
// Assert
- rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(5) }
- rule.runOnIdle { assertThat(pagerState.currentPageOffsetFraction).isWithin(0.01f).of(0.4f) }
+ rule.runOnIdle { assertThat(state.currentPage).isEqualTo(5) }
+ rule.runOnIdle { assertThat(state.currentPageOffsetFraction).isWithin(0.01f).of(0.4f) }
}
@Test
fun animateScrollToPage_withPassedAnimation() = runBlocking {
// Arrange
-
- createPager(modifier = Modifier.fillMaxSize())
+ val state = PagerState()
+ createPager(state = state, modifier = Modifier.fillMaxSize())
val differentAnimation: AnimationSpec<Float> = tween()
// Act and Assert
repeat(DefaultAnimationRepetition) {
- assertThat(pagerState.currentPage).isEqualTo(it)
+ assertThat(state.currentPage).isEqualTo(it)
withContext(Dispatchers.Main + AutoTestFrameClock()) {
- pagerState.animateScrollToPage(
- pagerState.currentPage + 1,
+ state.animateScrollToPage(
+ state.currentPage + 1,
animationSpec = differentAnimation
)
}
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ confirmPageIsInCorrectPosition(state.currentPage)
}
}
@Test
fun animatedScrollToPage_usingLaunchedEffect() {
-
- createPager(additionalContent = {
- LaunchedEffect(pagerState) {
- pagerState.animateScrollToPage(10)
+ val state = PagerState()
+ createPager(state, additionalContent = {
+ LaunchedEffect(state) {
+ state.animateScrollToPage(10)
}
})
rule.waitForIdle()
- assertThat(pagerState.currentPage).isEqualTo(10)
+ assertThat(state.currentPage).isEqualTo(10)
confirmPageIsInCorrectPosition(10)
}
@Test
fun animatedScrollToPageWithOffset_usingLaunchedEffect() {
-
- createPager(additionalContent = {
- LaunchedEffect(pagerState) {
- pagerState.animateScrollToPage(10, 0.4f)
+ val state = PagerState()
+ createPager(state, additionalContent = {
+ LaunchedEffect(state) {
+ state.animateScrollToPage(10, 0.4f)
}
})
rule.waitForIdle()
- assertThat(pagerState.currentPage).isEqualTo(10)
+ assertThat(state.currentPage).isEqualTo(10)
confirmPageIsInCorrectPosition(10, pageOffset = 0.4f)
}
@Test
fun animatedScrollToPage_viewPortNumberOfPages_usingLaunchedEffect_shouldNotPlaceALlPages() {
-
- createPager(additionalContent = {
- LaunchedEffect(pagerState) {
- pagerState.animateScrollToPage(DefaultPageCount - 1)
+ val state = PagerState()
+ createPager(state, additionalContent = {
+ LaunchedEffect(state) {
+ state.animateScrollToPage(DefaultPageCount - 1)
}
})
rule.waitForIdle()
// Assert
rule.runOnIdle {
- assertThat(pagerState.currentPage).isEqualTo(DefaultPageCount - 1)
+ assertThat(state.currentPage).isEqualTo(DefaultPageCount - 1)
assertThat(placed).doesNotContain(DefaultPageCount / 2 - 1)
assertThat(placed).doesNotContain(DefaultPageCount / 2)
assertThat(placed).doesNotContain(DefaultPageCount / 2 + 1)
}
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ confirmPageIsInCorrectPosition(state.currentPage)
}
@Test
fun currentPage_shouldChangeWhenClosestPageToSnappedPositionChanges() {
// Arrange
-
- createPager(modifier = Modifier.fillMaxSize())
- var previousCurrentPage = pagerState.currentPage
+ val state = PagerState()
+ createPager(state = state, modifier = Modifier.fillMaxSize())
+ var previousCurrentPage = state.currentPage
// Act
// Move less than half an item
@@ -427,15 +414,15 @@
// Assert
rule.runOnIdle {
- assertThat(pagerState.currentPage).isEqualTo(previousCurrentPage)
+ assertThat(state.currentPage).isEqualTo(previousCurrentPage)
}
// Release pointer
onPager().performTouchInput { up() }
rule.runOnIdle {
- previousCurrentPage = pagerState.currentPage
+ previousCurrentPage = state.currentPage
}
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ confirmPageIsInCorrectPosition(state.currentPage)
// Arrange
// Pass closest to snap position threshold (over half an item)
@@ -453,22 +440,24 @@
// Assert
rule.runOnIdle {
- assertThat(pagerState.currentPage).isEqualTo(previousCurrentPage + 1)
+ assertThat(state.currentPage).isEqualTo(previousCurrentPage + 1)
}
onPager().performTouchInput { up() }
rule.waitForIdle()
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ confirmPageIsInCorrectPosition(state.currentPage)
}
@Test
fun targetPage_performScrollBelowThreshold_shouldNotShowNextPage() {
// Arrange
+ val state = PagerState()
createPager(
+ state = state,
modifier = Modifier.fillMaxSize(),
snappingPage = PagerSnapDistance.atMost(3)
)
- rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
+ rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
rule.mainClock.autoAdvance = false
// Act
@@ -476,7 +465,7 @@
val forwardDelta =
scrollForwardSign.toFloat() * with(rule.density) { DefaultPositionThreshold.toPx() / 2 }
- var previousTargetPage = pagerState.targetPage
+ var previousTargetPage = state.targetPage
onPager().performTouchInput {
down(layoutStart)
@@ -484,12 +473,12 @@
}
// Assert
- assertThat(pagerState.targetPage).isEqualTo(previousTargetPage)
+ assertThat(state.targetPage).isEqualTo(previousTargetPage)
// Reset
rule.mainClock.autoAdvance = true
onPager().performTouchInput { up() }
- rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
+ rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
// Act
// Moving more than threshold
@@ -497,7 +486,7 @@
-DefaultPositionThreshold.toPx() / 2
}
- previousTargetPage = pagerState.targetPage
+ previousTargetPage = state.targetPage
onPager().performTouchInput {
down(layoutStart)
@@ -505,17 +494,19 @@
}
// Assert
- assertThat(pagerState.targetPage).isEqualTo(previousTargetPage)
+ assertThat(state.targetPage).isEqualTo(previousTargetPage)
}
@Test
fun targetPage_performScroll_shouldShowNextPage() {
// Arrange
+ val state = PagerState()
createPager(
+ state = state,
modifier = Modifier.fillMaxSize(),
snappingPage = PagerSnapDistance.atMost(3)
)
- rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
+ rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
rule.mainClock.autoAdvance = false
// Act
@@ -527,15 +518,15 @@
}
// Assert
- assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage + 1)
- assertThat(pagerState.targetPage).isNotEqualTo(pagerState.currentPage)
+ assertThat(state.targetPage).isEqualTo(state.currentPage + 1)
+ assertThat(state.targetPage).isNotEqualTo(state.currentPage)
// Reset
rule.mainClock.autoAdvance = true
onPager().performTouchInput { up() }
- rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
+ rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
rule.runOnIdle {
- runBlocking { pagerState.scrollToPage(5) }
+ runBlocking { state.scrollToPage(5) }
}
rule.mainClock.autoAdvance = false
@@ -548,113 +539,117 @@
}
// Assert
- assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage - 1)
- assertThat(pagerState.targetPage).isNotEqualTo(pagerState.currentPage)
+ assertThat(state.targetPage).isEqualTo(state.currentPage - 1)
+ assertThat(state.targetPage).isNotEqualTo(state.currentPage)
rule.mainClock.autoAdvance = true
onPager().performTouchInput { up() }
- rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
+ rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
}
@Test
fun targetPage_performingFling_shouldGoToPredictedPage() {
// Arrange
-
+ val state = PagerState()
createPager(
+ state = state,
modifier = Modifier.fillMaxSize(),
snappingPage = PagerSnapDistance.atMost(3)
)
- rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
+ rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
rule.mainClock.autoAdvance = false
// Act
// Moving forward
- var previousTarget = pagerState.targetPage
+ var previousTarget = state.targetPage
val forwardDelta = pagerSize * scrollForwardSign.toFloat()
onPager().performTouchInput {
swipeWithVelocityAcrossMainAxis(20000f, forwardDelta)
}
- rule.mainClock.advanceTimeUntil { pagerState.targetPage != previousTarget }
- var flingOriginIndex = pagerState.firstVisiblePage
+ rule.mainClock.advanceTimeUntil { state.targetPage != previousTarget }
+ var flingOriginIndex = state.firstVisiblePageInfo?.index ?: 0
// Assert
- assertThat(pagerState.targetPage).isEqualTo(flingOriginIndex + 3)
- assertThat(pagerState.targetPage).isNotEqualTo(pagerState.currentPage)
+ assertThat(state.targetPage).isEqualTo(flingOriginIndex + 3)
+ assertThat(state.targetPage).isNotEqualTo(state.currentPage)
rule.mainClock.autoAdvance = true
- rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
+ rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
rule.mainClock.autoAdvance = false
// Act
// Moving backward
- previousTarget = pagerState.targetPage
+ previousTarget = state.targetPage
val backwardDelta = -pagerSize * scrollForwardSign.toFloat()
onPager().performTouchInput {
swipeWithVelocityAcrossMainAxis(20000f, backwardDelta)
}
- rule.mainClock.advanceTimeUntil { pagerState.targetPage != previousTarget }
+ rule.mainClock.advanceTimeUntil { state.targetPage != previousTarget }
// Assert
- flingOriginIndex = pagerState.firstVisiblePage + 1
- assertThat(pagerState.targetPage).isEqualTo(flingOriginIndex - 3)
- assertThat(pagerState.targetPage).isNotEqualTo(pagerState.currentPage)
+ flingOriginIndex = (state.firstVisiblePageInfo?.index ?: 0) + 1
+ assertThat(state.targetPage).isEqualTo(flingOriginIndex - 3)
+ assertThat(state.targetPage).isNotEqualTo(state.currentPage)
rule.mainClock.autoAdvance = true
- rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
+ rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
}
@Test
fun targetPage_shouldReflectTargetWithAnimation() {
// Arrange
-
+ val state = PagerState()
createPager(
+ state = state,
modifier = Modifier.fillMaxSize()
)
- rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
+ rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
rule.mainClock.autoAdvance = false
// Act
// Moving forward
- var previousTarget = pagerState.targetPage
+ var previousTarget = state.targetPage
rule.runOnIdle {
scope.launch {
- pagerState.animateScrollToPage(DefaultPageCount - 1)
+ state.animateScrollToPage(DefaultPageCount - 1)
}
}
- rule.mainClock.advanceTimeUntil { pagerState.targetPage != previousTarget }
+ rule.mainClock.advanceTimeUntil { state.targetPage != previousTarget }
// Assert
- assertThat(pagerState.targetPage).isEqualTo(DefaultPageCount - 1)
- assertThat(pagerState.targetPage).isNotEqualTo(pagerState.currentPage)
+ assertThat(state.targetPage).isEqualTo(DefaultPageCount - 1)
+ assertThat(state.targetPage).isNotEqualTo(state.currentPage)
rule.mainClock.autoAdvance = true
- rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
+ rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
rule.mainClock.autoAdvance = false
// Act
// Moving backward
- previousTarget = pagerState.targetPage
+ previousTarget = state.targetPage
rule.runOnIdle {
scope.launch {
- pagerState.animateScrollToPage(0)
+ state.animateScrollToPage(0)
}
}
- rule.mainClock.advanceTimeUntil { pagerState.targetPage != previousTarget }
+ rule.mainClock.advanceTimeUntil { state.targetPage != previousTarget }
// Assert
- assertThat(pagerState.targetPage).isEqualTo(0)
- assertThat(pagerState.targetPage).isNotEqualTo(pagerState.currentPage)
+ assertThat(state.targetPage).isEqualTo(0)
+ assertThat(state.targetPage).isNotEqualTo(state.currentPage)
rule.mainClock.autoAdvance = true
- rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
+ rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
}
@Test
fun settledPage_onAnimationScroll_shouldChangeOnScrollFinishedOnly() {
// Arrange
+ val state = PagerState()
var settledPageChanges = 0
createPager(
+ state = state,
modifier = Modifier.fillMaxSize(),
additionalContent = {
- LaunchedEffect(key1 = pagerState.settledPage) {
+ LaunchedEffect(key1 = state.settledPage) {
settledPageChanges++
}
}
@@ -662,49 +657,51 @@
// Settle page changed once for first composition
rule.runOnIdle {
- assertThat(pagerState.settledPage).isEqualTo(pagerState.currentPage)
+ assertThat(state.settledPage).isEqualTo(state.currentPage)
assertTrue { settledPageChanges == 1 }
}
settledPageChanges = 0
- val previousSettled = pagerState.settledPage
+ val previousSettled = state.settledPage
rule.mainClock.autoAdvance = false
// Act
// Moving forward
rule.runOnIdle {
scope.launch {
- pagerState.animateScrollToPage(DefaultPageCount - 1)
+ state.animateScrollToPage(DefaultPageCount - 1)
}
}
// Settled page shouldn't change whilst scroll is in progress.
- assertTrue { pagerState.isScrollInProgress }
+ assertTrue { state.isScrollInProgress }
assertTrue { settledPageChanges == 0 }
- assertThat(pagerState.settledPage).isEqualTo(previousSettled)
+ assertThat(state.settledPage).isEqualTo(previousSettled)
rule.mainClock.advanceTimeUntil { settledPageChanges != 0 }
rule.runOnIdle {
- assertTrue { !pagerState.isScrollInProgress }
- assertThat(pagerState.settledPage).isEqualTo(pagerState.currentPage)
+ assertTrue { !state.isScrollInProgress }
+ assertThat(state.settledPage).isEqualTo(state.currentPage)
}
}
@Test
fun settledPage_onGestureScroll_shouldChangeOnScrollFinishedOnly() {
// Arrange
+ val state = PagerState()
var settledPageChanges = 0
createPager(
+ state = state,
modifier = Modifier.fillMaxSize(),
additionalContent = {
- LaunchedEffect(key1 = pagerState.settledPage) {
+ LaunchedEffect(key1 = state.settledPage) {
settledPageChanges++
}
}
)
settledPageChanges = 0
- val previousSettled = pagerState.settledPage
+ val previousSettled = state.settledPage
rule.mainClock.autoAdvance = false
// Act
// Moving forward
@@ -714,26 +711,27 @@
}
// Settled page shouldn't change whilst scroll is in progress.
- assertTrue { pagerState.isScrollInProgress }
+ assertTrue { state.isScrollInProgress }
assertTrue { settledPageChanges == 0 }
- assertThat(pagerState.settledPage).isEqualTo(previousSettled)
+ assertThat(state.settledPage).isEqualTo(previousSettled)
rule.mainClock.advanceTimeUntil { settledPageChanges != 0 }
rule.runOnIdle {
- assertTrue { !pagerState.isScrollInProgress }
- assertThat(pagerState.settledPage).isEqualTo(pagerState.currentPage)
+ assertTrue { !state.isScrollInProgress }
+ assertThat(state.settledPage).isEqualTo(state.currentPage)
}
}
@Test
fun currentPageOffset_shouldReflectScrollingOfCurrentPage() {
// Arrange
- createPager(initialPage = DefaultPageCount / 2, modifier = Modifier.fillMaxSize())
+ val state = PagerState(DefaultPageCount / 2)
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// No offset initially
rule.runOnIdle {
- assertThat(pagerState.currentPageOffsetFraction).isWithin(0.01f).of(0f)
+ assertThat(state.currentPageOffsetFraction).isWithin(0.01f).of(0f)
}
// Act
@@ -748,7 +746,7 @@
}
rule.runOnIdle {
- assertThat(pagerState.currentPageOffsetFraction).isWithin(0.1f).of(0.25f)
+ assertThat(state.currentPageOffsetFraction).isWithin(0.1f).of(0.25f)
}
onPager().performTouchInput { up() }
@@ -757,13 +755,13 @@
// Reset
rule.runOnIdle {
scope.launch {
- pagerState.scrollToPage(DefaultPageCount / 2)
+ state.scrollToPage(DefaultPageCount / 2)
}
}
// No offset initially (again)
rule.runOnIdle {
- assertThat(pagerState.currentPageOffsetFraction).isWithin(0.01f).of(0f)
+ assertThat(state.currentPageOffsetFraction).isWithin(0.01f).of(0f)
}
// Act
@@ -778,22 +776,23 @@
}
rule.runOnIdle {
- assertThat(pagerState.currentPageOffsetFraction).isWithin(0.1f).of(-0.25f)
+ assertThat(state.currentPageOffsetFraction).isWithin(0.1f).of(-0.25f)
}
}
@Test
fun initialPageOnPagerState_shouldDisplayThatPageFirst() {
// Arrange
+ val state = PagerState(5)
// Act
- createPager(initialPage = 5, modifier = Modifier.fillMaxSize())
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// Assert
rule.onNodeWithTag("4").assertDoesNotExist()
rule.onNodeWithTag("5").assertIsDisplayed()
rule.onNodeWithTag("6").assertDoesNotExist()
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ confirmPageIsInCorrectPosition(state.currentPage)
}
@Test
@@ -802,10 +801,11 @@
val tester = StateRestorationTester(rule)
lateinit var state: PagerState
tester.setContent {
- state = rememberPagerState(pageCount = { DefaultPageCount })
+ state = rememberPagerState()
scope = rememberCoroutineScope()
HorizontalOrVerticalPager(
state = state,
+ pageCount = DefaultPageCount,
modifier = Modifier.fillMaxSize()
) {
Page(it)
@@ -838,27 +838,27 @@
@Test
fun scrollTo_beforeFirstLayout_shouldWaitForStateAndLayoutSetting() {
// Arrange
-
+ val state = PagerState(0)
rule.mainClock.autoAdvance = false
// Act
- createPager(modifier = Modifier.fillMaxSize(), additionalContent = {
- LaunchedEffect(pagerState) {
- pagerState.scrollToPage(5)
+ createPager(state = state, modifier = Modifier.fillMaxSize(), additionalContent = {
+ LaunchedEffect(state) {
+ state.scrollToPage(5)
}
})
// Assert
- assertThat(pagerState.currentPage).isEqualTo(5)
+ assertThat(state.currentPage).isEqualTo(5)
}
@Test
fun currentPageOffsetFraction_shouldNeverBeNan() {
rule.setContent {
- val state = rememberPagerState(pageCount = { 10 })
+ val state = rememberPagerState()
// Read state in composition, should never be Nan
assertFalse { state.currentPageOffsetFraction.isNaN() }
- HorizontalOrVerticalPager(state = state) {
+ HorizontalOrVerticalPager(pageCount = 10, state = state) {
Page(index = it)
}
}
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerSwipeEdgeTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerSwipeEdgeTest.kt
index 8926c1f..7a5a1bc 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerSwipeEdgeTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerSwipeEdgeTest.kt
@@ -38,7 +38,8 @@
@Test
fun swipePageTowardsEdge_shouldNotMove() {
// Arrange
- createPager(modifier = Modifier.fillMaxSize())
+ val state = PagerState()
+ createPager(state = state, modifier = Modifier.fillMaxSize())
val delta = pagerSize * 0.4f * scrollForwardSign
// Act - backward
diff --git a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerTest.kt b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerTest.kt
index 753c0a2..24b1450 100644
--- a/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerTest.kt
+++ b/compose/foundation/foundation/src/androidAndroidTest/kotlin/androidx/compose/foundation/pager/PagerTest.kt
@@ -20,16 +20,12 @@
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
-import androidx.compose.ui.composed
-import androidx.compose.ui.layout.onSizeChanged
-import androidx.compose.ui.platform.testTag
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performTouchInput
import androidx.test.filters.LargeTest
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -48,8 +44,9 @@
@Test
fun userScrollEnabledIsOff_shouldNotAllowGestureScroll() {
// Arrange
-
+ val state = PagerState()
createPager(
+ state = state,
userScrollEnabled = false,
modifier = Modifier.fillMaxSize()
)
@@ -59,7 +56,7 @@
// Assert
rule.runOnIdle {
- assertThat(pagerState.currentPage).isEqualTo(0)
+ assertThat(state.currentPage).isEqualTo(0)
}
confirmPageIsInCorrectPosition(0, 0)
@@ -68,8 +65,9 @@
@Test
fun userScrollEnabledIsOff_shouldAllowAnimationScroll() {
// Arrange
-
+ val state = PagerState()
createPager(
+ state = state,
userScrollEnabled = false,
modifier = Modifier.fillMaxSize()
)
@@ -77,13 +75,13 @@
// Act
rule.runOnIdle {
scope.launch {
- pagerState.animateScrollToPage(5)
+ state.animateScrollToPage(5)
}
}
// Assert
rule.runOnIdle {
- assertThat(pagerState.currentPage).isEqualTo(5)
+ assertThat(state.currentPage).isEqualTo(5)
}
confirmPageIsInCorrectPosition(5)
}
@@ -91,8 +89,9 @@
@Test
fun userScrollEnabledIsOn_shouldAllowGestureScroll() {
// Arrange
+ val state = PagerState(5)
createPager(
- initialPage = 5,
+ state = state,
userScrollEnabled = true,
modifier = Modifier.fillMaxSize()
)
@@ -100,24 +99,25 @@
onPager().performTouchInput { swipeWithVelocityAcrossMainAxis(1000f) }
rule.runOnIdle {
- assertThat(pagerState.currentPage).isNotEqualTo(5)
+ assertThat(state.currentPage).isNotEqualTo(5)
}
- confirmPageIsInCorrectPosition(pagerState.currentPage)
+ confirmPageIsInCorrectPosition(state.currentPage)
}
@Test
fun pageCount_pagerOnlyContainsGivenPageCountItems() {
// Arrange
+ val state = PagerState()
// Act
- createPager(modifier = Modifier.fillMaxSize())
+ createPager(state = state, modifier = Modifier.fillMaxSize())
// Assert
repeat(DefaultPageCount) {
rule.onNodeWithTag("$it").assertIsDisplayed()
rule.runOnIdle {
scope.launch {
- pagerState.scroll {
+ state.scroll {
scrollBy(pagerSize.toFloat())
}
}
@@ -130,10 +130,12 @@
@Test
fun mutablePageCount_assertPagesAreChangedIfCountIsChanged() {
// Arrange
+ val state = PagerState()
val pageCount = mutableStateOf(2)
createPager(
- pageCount = { pageCount.value },
+ state = state,
modifier = Modifier.fillMaxSize(),
+ pageCount = { pageCount.value }
)
rule.onNodeWithTag("3").assertDoesNotExist()
@@ -147,7 +149,7 @@
rule.onNodeWithTag("$it").assertIsDisplayed()
rule.runOnIdle {
scope.launch {
- pagerState.scroll {
+ state.scroll {
scrollBy(pagerSize.toFloat())
}
}
@@ -156,100 +158,6 @@
}
}
- @Test
- fun pageCount_readBeforeCompositionIsAccurate() {
- // Arrange
- val pageCount = mutableStateOf(2)
- val state = PagerStateImpl(0, 0f) { pageCount.value }
- assertThat(state.pageCount).isEqualTo(pageCount.value)
- rule.setContent {
- HorizontalOrVerticalPager(
- state = state,
- modifier = Modifier
- .fillMaxSize()
- .testTag(PagerTestTag)
- .onSizeChanged { pagerSize = if (vertical) it.height else it.width },
- pageSize = PageSize.Fill,
- reverseLayout = config.reverseLayout,
- pageSpacing = config.pageSpacing,
- contentPadding = config.mainAxisContentPadding,
- ) {
- Page(index = it)
- }
- }
-
- rule.runOnIdle { pageCount.value = 5 }
- assertThat(state.pageCount).isEqualTo(pageCount.value)
- }
-
- @Test
- fun pageCount_changeInCountDoesNotCausePagerToRecompose() {
- // Arrange
- var recomposeCount = 0
- val pageCount = mutableStateOf(2)
- val state = PagerStateImpl(0, 0f) { pageCount.value }
- assertThat(state.pageCount).isEqualTo(pageCount.value)
-
- rule.setContent {
- HorizontalOrVerticalPager(
- state = state,
- modifier = Modifier
- .fillMaxSize()
- .testTag(PagerTestTag)
- .composed {
- recomposeCount++
- Modifier
- },
- pageSize = PageSize.Fill,
- reverseLayout = config.reverseLayout,
- pageSpacing = config.pageSpacing,
- contentPadding = config.mainAxisContentPadding,
- ) {
- Page(index = it)
- }
- }
-
- assertThat(recomposeCount).isEqualTo(1)
- rule.runOnIdle { pageCount.value = 5 } // change count
- assertThat(state.pageCount).isEqualTo(pageCount.value)
- assertThat(recomposeCount).isEqualTo(1)
- }
-
- @Test
- fun pageCountDecreased_currentPageIsAdjustedAccordingly() {
- // Arrange
- val pageCount = mutableStateOf(5)
- val state = PagerStateImpl(0, 0f) { pageCount.value }
- assertThat(state.pageCount).isEqualTo(pageCount.value)
-
- rule.setContent {
- HorizontalOrVerticalPager(
- state = state,
- modifier = Modifier
- .fillMaxSize()
- .testTag(PagerTestTag),
- pageSize = PageSize.Fill,
- reverseLayout = config.reverseLayout,
- pageSpacing = config.pageSpacing,
- contentPadding = config.mainAxisContentPadding,
- ) {
- Page(index = it)
- }
- }
-
- rule.runOnIdle {
- runBlocking {
- state.scrollToPage(3)
- }
- }
- rule.runOnIdle { assertThat(state.currentPage).isEqualTo(3) }
- pageCount.value = 2 // change count, less than current page
- rule.runOnIdle {
- assertThat(state.pageCount).isEqualTo(pageCount.value)
- assertThat(state.currentPage).isEqualTo(1) // last page
- }
- }
-
companion object {
@JvmStatic
@Parameterized.Parameters(name = "{0}")
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/LazyLayoutPager.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/LazyLayoutPager.kt
index 9f00444..ce3dd25 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/LazyLayoutPager.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/LazyLayoutPager.kt
@@ -37,11 +37,9 @@
import androidx.compose.foundation.lazy.layout.lazyLayoutSemantics
import androidx.compose.foundation.overscroll
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
-import androidx.compose.runtime.structuralEqualityPolicy
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
@@ -55,6 +53,8 @@
internal fun Pager(
/** Modifier to be applied for the inner layout */
modifier: Modifier,
+ /** The amount of Pages that will be present in this Pager **/
+ pageCount: Int,
/** State controlling the scroll position */
state: PagerState,
/** The inner padding to be added for the whole content(not for each individual page) */
@@ -94,8 +94,9 @@
val pagerItemProvider = rememberPagerItemProvider(
state = state,
pageContent = pageContent,
- key = key
- ) { state.pageCount }
+ key = key,
+ pageCount = pageCount
+ )
val beyondBoundsInfo = remember { LazyListBeyondBoundsInfo() }
@@ -110,7 +111,7 @@
horizontalAlignment = horizontalAlignment,
verticalAlignment = verticalAlignment,
itemProvider = pagerItemProvider,
- pageCount = { state.pageCount },
+ pageCount = pageCount,
beyondBoundsInfo = beyondBoundsInfo
)
@@ -171,11 +172,10 @@
val state: PagerState,
latestContent: () -> (@Composable (page: Int) -> Unit),
key: ((index: Int) -> Any)?,
- pageCount: () -> Int
+ pageCount: Int
) : LazyLayoutItemProvider {
- private val pagerContent by derivedStateOf(structuralEqualityPolicy()) {
- PagerLayoutIntervalContent(latestContent(), key = key, pageCount = pageCount())
- }
+ private val pagerContent =
+ PagerLayoutIntervalContent(latestContent(), key = key, pageCount = pageCount)
private val keyToIndexMap: LazyLayoutKeyIndexMap by NearestRangeKeyIndexMapState(
firstVisibleItemIndex = { state.firstVisiblePage },
slidingWindowSize = { NearestItemsSlidingWindowSize },
@@ -203,8 +203,8 @@
val key: ((index: Int) -> Any)?,
val pageCount: Int
) : LazyLayoutIntervalContent<PagerIntervalContent>() {
- override val intervals: IntervalList<PagerIntervalContent> =
- MutableIntervalList<PagerIntervalContent>().apply {
+ override val intervals: IntervalList<PagerIntervalContent>
+ get() = MutableIntervalList<PagerIntervalContent>().apply {
addInterval(pageCount, PagerIntervalContent(key = key, item = pageContent))
}
}
@@ -221,7 +221,7 @@
state: PagerState,
pageContent: @Composable (page: Int) -> Unit,
key: ((index: Int) -> Any)?,
- pageCount: () -> Int
+ pageCount: Int
): PagerLazyLayoutItemProvider {
val latestContent = rememberUpdatedState(pageContent)
return remember(state, latestContent, key, pageCount) {
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/Pager.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/Pager.kt
index 581e2af..0c55052 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/Pager.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/Pager.kt
@@ -72,84 +72,6 @@
* Please refer to the sample to learn how to use this API.
* @sample androidx.compose.foundation.samples.SimpleHorizontalPagerSample
*
- * @param state The state to control this pager
- * @param modifier A modifier instance to be applied to this Pager outer layout
- * @param contentPadding a padding around the whole content. This will add padding for the
- * content after it has been clipped, which is not possible via [modifier] param. You can use it
- * to add a padding before the first page or after the last one. Use [pageSpacing] to add spacing
- * between the pages.
- * @param pageSize Use this to change how the pages will look like inside this pager.
- * @param beyondBoundsPageCount Pages to load before and after the list of visible
- * pages. Note: Be aware that using a large value for [beyondBoundsPageCount] will cause a lot of
- * pages to be composed, measured and placed which will defeat the purpose of using lazy loading.
- * This should be used as an optimization to pre-load a couple of pages before and after the visible
- * ones.
- * @param pageSpacing The amount of space to be used to separate the pages in this Pager
- * @param verticalAlignment How pages are aligned vertically in this Pager.
- * @param flingBehavior The [FlingBehavior] to be used for post scroll gestures.
- * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions
- * is allowed. You can still scroll programmatically using [PagerState.scroll] even when it is
- * disabled.
- * @param reverseLayout reverse the direction of scrolling and layout.
- * @param key a stable and unique key representing the item. When you specify the key the scroll
- * position will be maintained based on the key, which means if you add/remove items before the
- * current visible item the item with the given key will be kept as the first visible one.
- * @param pageNestedScrollConnection A [NestedScrollConnection] that dictates how this [Pager]
- * behaves with nested lists. The default behavior will see [Pager] to consume all nested deltas.
- * @param pageContent This Pager's page Composable.
- */
-@Composable
-@ExperimentalFoundationApi
-fun HorizontalPager(
- state: PagerState,
- modifier: Modifier = Modifier,
- contentPadding: PaddingValues = PaddingValues(0.dp),
- pageSize: PageSize = PageSize.Fill,
- beyondBoundsPageCount: Int = 0,
- pageSpacing: Dp = 0.dp,
- verticalAlignment: Alignment.Vertical = Alignment.CenterVertically,
- flingBehavior: SnapFlingBehavior = PagerDefaults.flingBehavior(state = state),
- userScrollEnabled: Boolean = true,
- reverseLayout: Boolean = false,
- key: ((index: Int) -> Any)? = null,
- pageNestedScrollConnection: NestedScrollConnection = PagerDefaults.pageNestedScrollConnection(
- Orientation.Horizontal
- ),
- pageContent: @Composable (page: Int) -> Unit
-) {
- Pager(
- state = state,
- modifier = modifier,
- contentPadding = contentPadding,
- pageSize = pageSize,
- beyondBoundsPageCount = beyondBoundsPageCount,
- pageSpacing = pageSpacing,
- orientation = Orientation.Horizontal,
- verticalAlignment = verticalAlignment,
- horizontalAlignment = Alignment.CenterHorizontally,
- flingBehavior = flingBehavior,
- userScrollEnabled = userScrollEnabled,
- reverseLayout = reverseLayout,
- key = key,
- pageNestedScrollConnection = pageNestedScrollConnection,
- pageContent = pageContent
- )
-}
-
-/**
- * A Pager that scrolls horizontally. Pages are lazily placed in accordance to the available
- * viewport size. By definition, pages in a [Pager] have the same size, defined by [pageSize] and
- * use a snap animation (provided by [flingBehavior] to scroll pages into a specific position). You
- * can use [beyondBoundsPageCount] to place more pages before and after the visible pages.
- *
- * If you need snapping with pages of different size, you can use a [SnapFlingBehavior] with a
- * [SnapLayoutInfoProvider] adapted to a LazyList.
- * @see androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider for the implementation
- * of a [SnapLayoutInfoProvider] that uses [androidx.compose.foundation.lazy.LazyListState].
- *
- * Please refer to the sample to learn how to use this API.
- * @sample androidx.compose.foundation.samples.SimpleHorizontalPagerSample
- *
* @param pageCount The number of pages this Pager will contain
* @param modifier A modifier instance to be applied to this Pager outer layout
* @param state The state to control this pager
@@ -177,38 +99,12 @@
* behaves with nested lists. The default behavior will see [Pager] to consume all nested deltas.
* @param pageContent This Pager's page Composable.
*/
-@Deprecated(
- "Please use the overload without pageCount. pageCount should be provided " +
- "through PagerState.", ReplaceWith(
- """HorizontalPager(
- modifier = modifier,
- state = state,
- pageSpacing = pageSpacing,
- horizontalAlignment = horizontalAlignment,
- userScrollEnabled = userScrollEnabled,
- reverseLayout = reverseLayout,
- contentPadding = contentPadding,
- beyondBoundsPageCount = beyondBoundsPageCount,
- pageSize = pageSize,
- flingBehavior = flingBehavior,
- key = key,
- pageNestedScrollConnection = pageNestedScrollConnection,
- pageContent = pageContent
- )""",
- imports = arrayOf(
- "androidx.compose.foundation.gestures.Orientation",
- "androidx.compose.foundation.layout.PaddingValues",
- "androidx.compose.foundation.pager.PageSize",
- "androidx.compose.foundation.pager.PagerDefaults"
- )
- )
-)
@Composable
@ExperimentalFoundationApi
fun HorizontalPager(
pageCount: Int,
modifier: Modifier = Modifier,
- state: PagerState = rememberPagerState { pageCount },
+ state: PagerState = rememberPagerState(),
contentPadding: PaddingValues = PaddingValues(0.dp),
pageSize: PageSize = PageSize.Fill,
beyondBoundsPageCount: Int = 0,
@@ -224,99 +120,22 @@
pageContent: @Composable (page: Int) -> Unit
) {
Pager(
- state = state,
modifier = modifier,
+ pageCount = pageCount,
+ state = state,
contentPadding = contentPadding,
+ reverseLayout = reverseLayout,
+ orientation = Orientation.Horizontal,
+ flingBehavior = flingBehavior,
+ userScrollEnabled = userScrollEnabled,
pageSize = pageSize,
beyondBoundsPageCount = beyondBoundsPageCount,
pageSpacing = pageSpacing,
- orientation = Orientation.Horizontal,
+ pageContent = pageContent,
+ pageNestedScrollConnection = pageNestedScrollConnection,
verticalAlignment = verticalAlignment,
horizontalAlignment = Alignment.CenterHorizontally,
- flingBehavior = flingBehavior,
- userScrollEnabled = userScrollEnabled,
- reverseLayout = reverseLayout,
- key = key,
- pageNestedScrollConnection = pageNestedScrollConnection,
- pageContent = pageContent
- )
-}
-
-/**
- * A Pager that scrolls vertically. Pages are lazily placed in accordance to the available
- * viewport size. By definition, pages in a [Pager] have the same size, defined by [pageSize] and
- * use a snap animation (provided by [flingBehavior] to scroll pages into a specific position). You
- * can use [beyondBoundsPageCount] to place more pages before and after the visible pages.
- *
- * If you need snapping with pages of different size, you can use a [SnapFlingBehavior] with a
- * [SnapLayoutInfoProvider] adapted to a LazyList.
- * @see androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider for the implementation
- * of a [SnapLayoutInfoProvider] that uses [androidx.compose.foundation.lazy.LazyListState].
- *
- * Please refer to the sample to learn how to use this API.
- * @sample androidx.compose.foundation.samples.SimpleVerticalPagerSample
- *
- * @param state The state to control this pager
- * @param modifier A modifier instance to be apply to this Pager outer layout
- * @param contentPadding a padding around the whole content. This will add padding for the
- * content after it has been clipped, which is not possible via [modifier] param. You can use it
- * to add a padding before the first page or after the last one. Use [pageSpacing] to add spacing
- * between the pages.
- * @param pageSize Use this to change how the pages will look like inside this pager.
- * @param beyondBoundsPageCount Pages to load before and after the list of visible
- * pages. Note: Be aware that using a large value for [beyondBoundsPageCount] will cause a lot of
- * pages to be composed, measured and placed which will defeat the purpose of using lazy loading.
- * This should be used as an optimization to pre-load a couple of pages before and after the visible
- * ones.
- * @param pageSpacing The amount of space to be used to separate the pages in this Pager
- * @param horizontalAlignment How pages are aligned horizontally in this Pager.
- * @param flingBehavior The [FlingBehavior] to be used for post scroll gestures.
- * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions
- * is allowed. You can still scroll programmatically using [PagerState.scroll] even when it is
- * disabled.
- * @param reverseLayout reverse the direction of scrolling and layout.
- * @param key a stable and unique key representing the item. When you specify the key the scroll
- * position will be maintained based on the key, which means if you add/remove items before the
- * current visible item the item with the given key will be kept as the first visible one.
- * @param pageNestedScrollConnection A [NestedScrollConnection] that dictates how this [Pager] behaves
- * with nested lists. The default behavior will see [Pager] to consume all nested deltas.
- * @param pageContent This Pager's page Composable.
- */
-@Composable
-@ExperimentalFoundationApi
-fun VerticalPager(
- state: PagerState,
- modifier: Modifier = Modifier,
- contentPadding: PaddingValues = PaddingValues(0.dp),
- pageSize: PageSize = PageSize.Fill,
- beyondBoundsPageCount: Int = 0,
- pageSpacing: Dp = 0.dp,
- horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,
- flingBehavior: SnapFlingBehavior = PagerDefaults.flingBehavior(state = state),
- userScrollEnabled: Boolean = true,
- reverseLayout: Boolean = false,
- key: ((index: Int) -> Any)? = null,
- pageNestedScrollConnection: NestedScrollConnection = PagerDefaults.pageNestedScrollConnection(
- Orientation.Vertical
- ),
- pageContent: @Composable (page: Int) -> Unit
-) {
- Pager(
- state = state,
- modifier = modifier,
- contentPadding = contentPadding,
- pageSize = pageSize,
- beyondBoundsPageCount = beyondBoundsPageCount,
- pageSpacing = pageSpacing,
- orientation = Orientation.Vertical,
- verticalAlignment = Alignment.CenterVertically,
- horizontalAlignment = horizontalAlignment,
- flingBehavior = flingBehavior,
- userScrollEnabled = userScrollEnabled,
- reverseLayout = reverseLayout,
- key = key,
- pageNestedScrollConnection = pageNestedScrollConnection,
- pageContent = pageContent
+ key = key
)
}
@@ -361,38 +180,12 @@
* with nested lists. The default behavior will see [Pager] to consume all nested deltas.
* @param pageContent This Pager's page Composable.
*/
-@Deprecated(
- "Please use the overload without pageCount. pageCount should be provided " +
- "through PagerState.", ReplaceWith(
- """VerticalPager(
- modifier = modifier,
- state = state,
- pageSpacing = pageSpacing,
- horizontalAlignment = horizontalAlignment,
- userScrollEnabled = userScrollEnabled,
- reverseLayout = reverseLayout,
- contentPadding = contentPadding,
- beyondBoundsPageCount = beyondBoundsPageCount,
- pageSize = pageSize,
- flingBehavior = flingBehavior,
- key = key,
- pageNestedScrollConnection = pageNestedScrollConnection,
- pageContent = pageContent
- )""",
- imports = arrayOf(
- "androidx.compose.foundation.gestures.Orientation",
- "androidx.compose.foundation.layout.PaddingValues",
- "androidx.compose.foundation.pager.PageSize",
- "androidx.compose.foundation.pager.PagerDefaults"
- )
- )
-)
@Composable
@ExperimentalFoundationApi
fun VerticalPager(
pageCount: Int,
modifier: Modifier = Modifier,
- state: PagerState = rememberPagerState { pageCount },
+ state: PagerState = rememberPagerState(),
contentPadding: PaddingValues = PaddingValues(0.dp),
pageSize: PageSize = PageSize.Fill,
beyondBoundsPageCount: Int = 0,
@@ -408,21 +201,22 @@
pageContent: @Composable (page: Int) -> Unit
) {
Pager(
- state = state,
modifier = modifier,
+ pageCount = pageCount,
+ state = state,
contentPadding = contentPadding,
+ reverseLayout = reverseLayout,
+ orientation = Orientation.Vertical,
+ flingBehavior = flingBehavior,
+ userScrollEnabled = userScrollEnabled,
pageSize = pageSize,
beyondBoundsPageCount = beyondBoundsPageCount,
pageSpacing = pageSpacing,
- orientation = Orientation.Vertical,
+ pageContent = pageContent,
+ pageNestedScrollConnection = pageNestedScrollConnection,
verticalAlignment = Alignment.CenterVertically,
horizontalAlignment = horizontalAlignment,
- flingBehavior = flingBehavior,
- userScrollEnabled = userScrollEnabled,
- reverseLayout = reverseLayout,
- key = key,
- pageNestedScrollConnection = pageNestedScrollConnection,
- pageContent = pageContent
+ key = key
)
}
@@ -663,11 +457,9 @@
val effectivePageSizePx = pagerState.pageSize + pagerState.pageSpacing
val animationOffsetPx =
decayAnimationSpec.calculateTargetValue(0f, initialVelocity)
- val startPage = if (initialVelocity < 0) {
- pagerState.firstVisiblePage + 1
- } else {
- pagerState.firstVisiblePage
- }
+ val startPage = pagerState.firstVisiblePageInfo?.let {
+ if (initialVelocity < 0) it.index + 1 else it.index
+ } ?: pagerState.currentPage
val scrollOffset =
layoutInfo.visiblePagesInfo.fastFirstOrNull { it.index == startPage }?.offset ?: 0
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasure.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasure.kt
index 6785dea..78aa13a 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasure.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasure.kt
@@ -64,8 +64,11 @@
): PagerMeasureResult {
require(beforeContentPadding >= 0)
require(afterContentPadding >= 0)
+
val pageSizeWithSpacing = (pageAvailableSize + spaceBetweenPages).coerceAtLeast(0)
+
debugLog { "Remeasuring..." }
+
return if (pageCount <= 0) {
PagerMeasureResult(
visiblePagesInfo = emptyList(),
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasurePolicy.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasurePolicy.kt
index 0c56d50..f535064 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasurePolicy.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasurePolicy.kt
@@ -50,7 +50,7 @@
pageSize: PageSize,
horizontalAlignment: Alignment.Horizontal?,
verticalAlignment: Alignment.Vertical?,
- pageCount: () -> Int,
+ pageCount: Int,
beyondBoundsInfo: LazyListBeyondBoundsInfo
) = remember<LazyLayoutMeasureScope.(Constraints) -> MeasureResult>(
contentPadding,
@@ -156,7 +156,7 @@
beforeContentPadding = beforeContentPadding,
afterContentPadding = afterContentPadding,
constraints = contentConstraints,
- pageCount = pageCount(),
+ pageCount = pageCount,
spaceBetweenPages = spaceBetweenPages,
mainAxisAvailableSize = mainAxisAvailableSize,
visualPageOffset = visualItemOffset,
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerState.kt
index 3906300..04e021f 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerState.kt
@@ -61,92 +61,15 @@
* @param initialPageOffsetFraction The offset of the initial page as a fraction of the page size.
* This should vary between -0.5 and 0.5 and indicates how to offset the initial page from the
* snapped position.
- * @param pageCount The amount of pages this Pager will have.
*/
@ExperimentalFoundationApi
@Composable
fun rememberPagerState(
initialPage: Int = 0,
- initialPageOffsetFraction: Float = 0f,
- pageCount: () -> Int
-): PagerState {
- return rememberSaveable(saver = PagerStateImpl.Saver) {
- PagerStateImpl(
- initialPage,
- initialPageOffsetFraction,
- pageCount
- )
- }.apply {
- pageCountState.value = pageCount
- }
-}
-
-/**
- * Creates and remember a [PagerState] to be used with a [Pager]
- *
- * Please refer to the sample to learn how to use this API.
- * @sample androidx.compose.foundation.samples.PagerWithStateSample
- *
- * @param initialPage The pager that should be shown first.
- * @param initialPageOffsetFraction The offset of the initial page as a fraction of the page size.
- * This should vary between -0.5 and 0.5 and indicates how to offset the initial page from the
- * snapped position.
- */
-@Deprecated(
- "Please use the overload where you can provide a source of truth for the pageCount.",
- ReplaceWith(
- """rememberPagerState(
- initialPage = initialPage,
- initialPageOffsetFraction = initialPageOffsetFraction
- ){
- // provide pageCount
- }"""
- )
-)
-@ExperimentalFoundationApi
-@Composable
-fun rememberPagerState(
- initialPage: Int = 0,
initialPageOffsetFraction: Float = 0f
): PagerState {
- return rememberSaveable(saver = PagerStateImpl.Saver) {
- PagerStateImpl(
- initialPage = initialPage,
- initialPageOffsetFraction = initialPageOffsetFraction
- ) { 0 }
- }
-}
-
-@ExperimentalFoundationApi
-internal class PagerStateImpl(
- initialPage: Int,
- initialPageOffsetFraction: Float,
- updatedPageCount: () -> Int
-) : PagerState(initialPage, initialPageOffsetFraction) {
-
- var pageCountState = mutableStateOf(updatedPageCount)
- override val pageCount: Int get() = pageCountState.value.invoke()
-
- companion object {
- /**
- * To keep current page and current page offset saved
- */
- val Saver: Saver<PagerStateImpl, *> = listSaver(
- save = {
- listOf(
- it.currentPage,
- it.currentPageOffsetFraction,
- it.pageCount
- )
- },
- restore = {
- PagerStateImpl(
- initialPage = it[0] as Int,
- initialPageOffsetFraction = it[1] as Float,
- updatedPageCount = { it[2] as Int }
- )
- }
- )
+ return rememberSaveable(saver = PagerState.Saver) {
+ PagerState(initialPage = initialPage, initialPageOffsetFraction = initialPageOffsetFraction)
}
}
@@ -158,16 +81,11 @@
*/
@ExperimentalFoundationApi
@Stable
-abstract class PagerState(
+class PagerState(
val initialPage: Int = 0,
val initialPageOffsetFraction: Float = 0f
) : ScrollableState {
- /**
- * The total amount of pages present in this pager
- */
- abstract val pageCount: Int
-
init {
require(initialPageOffsetFraction in -0.5..0.5) {
"initialPageOffsetFraction $initialPageOffsetFraction is " +
@@ -248,6 +166,18 @@
minThreshold / pageSize.toFloat()
}
+ internal val pageCount: Int
+ get() = pagerLayoutInfoState.value.pagesCount
+
+ internal val firstVisiblePageInfo: PageInfo?
+ get() = visiblePages.lastOrNull {
+ density.calculateDistanceToDesiredSnapPosition(
+ pagerLayoutInfoState.value,
+ it,
+ SnapAlignmentStartToStart
+ ) <= 0
+ }
+
private val distanceToSnapPosition: Float
get() = layoutInfo.closestPageToSnapPosition?.let {
density.calculateDistanceToDesiredSnapPosition(
@@ -492,9 +422,9 @@
override val isScrollInProgress: Boolean
get() = scrollableState.isScrollInProgress
- final override var canScrollForward: Boolean by mutableStateOf(false)
+ override var canScrollForward: Boolean by mutableStateOf(false)
private set
- final override var canScrollBackward: Boolean by mutableStateOf(false)
+ override var canScrollBackward: Boolean by mutableStateOf(false)
private set
/**
@@ -599,6 +529,26 @@
}
}
}
+
+ companion object {
+ /**
+ * To keep current page and current page offset saved
+ */
+ val Saver: Saver<PagerState, *> = listSaver(
+ save = {
+ listOf(
+ it.currentPage,
+ it.currentPageOffsetFraction
+ )
+ },
+ restore = {
+ PagerState(
+ initialPage = it[0] as Int,
+ initialPageOffsetFraction = it[1] as Float
+ )
+ }
+ )
+ }
}
@OptIn(ExperimentalFoundationApi::class)
diff --git a/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/PagerActivity.kt b/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/PagerActivity.kt
index c7e90d4..a9466ca 100644
--- a/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/PagerActivity.kt
+++ b/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/PagerActivity.kt
@@ -44,7 +44,7 @@
val itemCount = intent.getIntExtra(ExtraItemCount, 3000)
setContent {
- val pagerState = rememberPagerState { itemCount }
+ val pagerState = rememberPagerState()
Box(
modifier = Modifier
.fillMaxSize(),
@@ -56,7 +56,8 @@
.semantics { contentDescription = "Pager" }
.background(Color.White),
state = pagerState,
- pageSize = PageSize.Fill
+ pageSize = PageSize.Fill,
+ pageCount = itemCount
) {
PagerItem(it)
}
diff --git a/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/PagerAsCarouselActivity.kt b/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/PagerAsCarouselActivity.kt
index df252e7..50fc66b 100644
--- a/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/PagerAsCarouselActivity.kt
+++ b/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/PagerAsCarouselActivity.kt
@@ -45,7 +45,7 @@
val itemCount = intent.getIntExtra(ExtraItemCount, 3000)
setContent {
- val pagerState = rememberPagerState { itemCount }
+ val pagerState = rememberPagerState()
Box(
modifier = Modifier
.fillMaxSize()
@@ -57,6 +57,7 @@
.semantics { contentDescription = "Carousel" }
.background(Color.White),
state = pagerState,
+ pageCount = itemCount,
pageSize = PageSize.Fixed(200.dp)
) {
PagerItem(it)
diff --git a/paging/paging-compose/samples/src/main/java/androidx/paging/compose/samples/PagingFoundationSample.kt b/paging/paging-compose/samples/src/main/java/androidx/paging/compose/samples/PagingFoundationSample.kt
index 27b2fac..8b55ca8 100644
--- a/paging/paging-compose/samples/src/main/java/androidx/paging/compose/samples/PagingFoundationSample.kt
+++ b/paging/paging-compose/samples/src/main/java/androidx/paging/compose/samples/PagingFoundationSample.kt
@@ -54,12 +54,13 @@
@Sampled
@Composable
public fun PagingWithHorizontalPager() {
+ val pagerState = rememberPagerState()
val lazyPagingItems = pager.collectAsLazyPagingItems()
- val pagerState = rememberPagerState { lazyPagingItems.itemCount }
HorizontalPager(
modifier = Modifier.fillMaxSize(),
state = pagerState,
+ pageCount = lazyPagingItems.itemCount,
pageSize = PageSize.Fixed(200.dp),
key = lazyPagingItems.itemKey { it }
) { index ->
@@ -71,12 +72,13 @@
@OptIn(ExperimentalFoundationApi::class)
@Composable
public fun PagingWithVerticalPager() {
+ val pagerState = rememberPagerState()
val lazyPagingItems = pager.collectAsLazyPagingItems()
- val pagerState = rememberPagerState { lazyPagingItems.itemCount }
VerticalPager(
modifier = Modifier.fillMaxSize(),
state = pagerState,
+ pageCount = lazyPagingItems.itemCount,
pageSize = PageSize.Fixed(200.dp),
key = lazyPagingItems.itemKey { it }
) { index ->