Update pageCount use and application in Pager

pageCount should be used inside PagerState. This allows for better flexibility in the public API (it can be accessed from state), it also allows for usage in composition.

Relnote: Remove pageCount from Horizontal/VerticalPager. This should be provided at the state creation. Updated PagerState and rememberPagerState to accept the pageCount.

Test: Previous tests should pass.
Fixes: 266965072
Change-Id: Ieb52d10f08c4a45beaa4ce0a72734a44afb60ce7
diff --git a/compose/foundation/foundation/api/public_plus_experimental_current.txt b/compose/foundation/foundation/api/public_plus_experimental_current.txt
index 6d55c8e..33b5d9d 100644
--- a/compose/foundation/foundation/api/public_plus_experimental_current.txt
+++ b/compose/foundation/foundation/api/public_plus_experimental_current.txt
@@ -981,8 +981,10 @@
   }
 
   public final class PagerKt {
-    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);
+    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);
   }
 
   @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public interface PagerSnapDistance {
@@ -994,40 +996,39 @@
     method public androidx.compose.foundation.pager.PagerSnapDistance atMost(int pages);
   }
 
-  @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public final class PagerState implements androidx.compose.foundation.gestures.ScrollableState {
+  @androidx.compose.foundation.ExperimentalFoundationApi @androidx.compose.runtime.Stable public abstract class PagerState implements androidx.compose.foundation.gestures.ScrollableState {
     ctor public PagerState(optional int initialPage, optional float initialPageOffsetFraction);
-    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 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 float dispatchRawDelta(float delta);
-    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 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 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 suspend Object? scrollToPage(int page, optional float pageOffsetFraction, optional kotlin.coroutines.Continuation<? super kotlin.Unit>);
-    property public boolean canScrollBackward;
-    property public boolean canScrollForward;
+    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;
     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);
+    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);
   }
 
 }
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 a55b0aa..5b43150 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,13 +55,12 @@
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
 private fun HorizontalCarrouselDemo() {
-    val pagerState = rememberPagerState()
+    val pagerState = rememberPagerState { PagesCount }
 
     Column(modifier = Modifier.fillMaxSize()) {
         HorizontalPager(
             modifier = Modifier,
             state = pagerState,
-            pageCount = PagesCount,
             pageSize = PageSize.Fixed(200.dp)
         ) {
             CarrouselItem(it, Orientation.Vertical)
@@ -73,13 +72,12 @@
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
 private fun VerticalCarrouselDemo() {
-    val pagerState = rememberPagerState()
+    val pagerState = rememberPagerState { PagesCount }
 
     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)
@@ -91,13 +89,12 @@
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
 private fun HorizontalCustomPageSizeDemo() {
-    val pagerState = rememberPagerState()
+    val pagerState = rememberPagerState { PagesCount }
 
     Column(modifier = Modifier.fillMaxSize()) {
         HorizontalPager(
             modifier = Modifier,
             state = pagerState,
-            pageCount = PagesCount,
             pageSize = ThreePagesPerViewport,
             pageSpacing = 8.dp
         ) {
@@ -110,13 +107,12 @@
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
 private fun HorizontalCustomPageSizeWithCustomMaxScrollDemo() {
-    val pagerState = rememberPagerState()
+    val pagerState = rememberPagerState { PagesCount }
 
     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 49473eb..45a08b6 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,11 +72,10 @@
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
 private fun VerticalPagerDemo() {
-    val pagerState = rememberPagerState()
+    val pagerState = rememberPagerState { PagesCount }
     VerticalPager(
         modifier = Modifier.fillMaxSize(),
         state = pagerState,
-        pageCount = PagesCount
     ) {
         PagerItem(it)
     }
@@ -85,12 +84,11 @@
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
 internal fun HorizontalPagerDemo() {
-    val pagerState = rememberPagerState()
+    val pagerState = rememberPagerState { PagesCount }
 
     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 48202c2..5922b08 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,13 +46,12 @@
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
 private fun StateDrivenPage() {
-    val pagerState = rememberPagerState()
+    val pagerState = rememberPagerState { PagesCount }
 
     Column(modifier = Modifier.fillMaxSize()) {
         HorizontalPager(
             modifier = Modifier.weight(0.9f),
-            state = pagerState,
-            pageCount = PagesCount
+            state = pagerState
         ) {
             PagerItem(it)
         }
@@ -63,13 +62,12 @@
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
 private fun StateDrivenPageWithMonitor() {
-    val pagerState = rememberPagerState()
+    val pagerState = rememberPagerState { PagesCount }
 
     Column(modifier = Modifier.fillMaxSize()) {
         HorizontalPager(
             modifier = Modifier.weight(0.8f),
-            state = pagerState,
-            pageCount = PagesCount
+            state = pagerState
         ) {
             PagerItem(it)
         }
@@ -81,12 +79,11 @@
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
 private fun StateMonitoringPager() {
-    val pagerState = rememberPagerState()
+    val pagerState = rememberPagerState { PagesCount }
     Column(modifier = Modifier.fillMaxSize()) {
         HorizontalPager(
             modifier = Modifier.weight(0.9f),
-            state = pagerState,
-            pageCount = PagesCount
+            state = pagerState
         ) {
             PagerItem(it)
         }
@@ -107,7 +104,7 @@
 @OptIn(ExperimentalFoundationApi::class)
 @Composable
 private fun StateMonitoringCustomPageSize() {
-    val pagerState = rememberPagerState()
+    val pagerState = rememberPagerState { PagesCount }
 
     val fling = PagerDefaults.flingBehavior(
         state = pagerState, PagerSnapDistance.atMost(3)
@@ -117,7 +114,6 @@
         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 bed4f40..b95aeb5 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.Text
 import androidx.compose.material.Button
+import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Alignment
@@ -47,9 +47,10 @@
 @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
@@ -69,9 +70,10 @@
 @Composable
 fun SimpleVerticalPagerSample() {
     // Creates a 1-pager/viewport vertical pager with single page snapping
+    val state = rememberPagerState { 10 }
     VerticalPager(
-        modifier = Modifier.fillMaxSize(),
-        pageCount = 10
+        state = state,
+        modifier = Modifier.fillMaxSize()
     ) { page ->
         Box(
             modifier = Modifier
@@ -91,11 +93,10 @@
 @Composable
 fun PagerWithStateSample() {
     // You can use PagerState to define an initial page
-    val state = rememberPagerState(initialPage = 5)
+    val state = rememberPagerState(initialPage = 5) { 10 }
     HorizontalPager(
         modifier = Modifier.fillMaxSize(),
-        state = state,
-        pageCount = 10
+        state = state
     ) { page ->
         Box(
             modifier = Modifier
@@ -129,9 +130,10 @@
         }
     }
 
+    val state = rememberPagerState { 10 }
     HorizontalPager(
+        state = state,
         modifier = Modifier.fillMaxSize(),
-        pageCount = 10,
         pageSize = CustomPageSize
     ) { page ->
         Box(
@@ -151,12 +153,11 @@
 @Sampled
 @Composable
 fun ObservingStateChangesInPagerStateSample() {
-    val pagerState = rememberPagerState()
+    val pagerState = rememberPagerState { 10 }
     Column(modifier = Modifier.fillMaxSize()) {
         HorizontalPager(
             modifier = Modifier.weight(0.9f),
-            state = pagerState,
-            pageCount = 10
+            state = pagerState
         ) { page ->
             Box(
                 modifier = Modifier
@@ -169,9 +170,11 @@
                 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}")
@@ -183,13 +186,12 @@
 @Sampled
 @Composable
 fun AnimateScrollPageSample() {
-    val state = rememberPagerState()
+    val state = rememberPagerState { 10 }
     val animationScope = rememberCoroutineScope()
     Column {
         HorizontalPager(
             modifier = Modifier.weight(0.7f),
-            state = state,
-            pageCount = 10
+            state = state
         ) { page ->
             Box(
                 modifier = Modifier
@@ -203,7 +205,11 @@
             }
         }
 
-        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)
@@ -219,13 +225,12 @@
 @Sampled
 @Composable
 fun ScrollToPageSample() {
-    val state = rememberPagerState()
+    val state = rememberPagerState { 10 }
     val scrollScope = rememberCoroutineScope()
     Column {
         HorizontalPager(
             modifier = Modifier.height(400.dp),
-            state = state,
-            pageCount = 10
+            state = state
         ) { 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 adcc360..1905bee 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
@@ -70,6 +70,7 @@
     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,9 +109,10 @@
         }
 
     internal fun createPager(
-        state: PagerState,
-        modifier: Modifier = Modifier,
+        initialPage: Int = 0,
+        initialPageOffsetFraction: Float = 0f,
         pageCount: () -> Int = { DefaultPageCount },
+        modifier: Modifier = Modifier,
         offscreenPageLimit: Int = config.beyondBoundsPageCount,
         pageSize: () -> PageSize = { PageSize.Fill },
         userScrollEnabled: Boolean = true,
@@ -126,6 +128,9 @@
     ) {
 
         rule.setContent {
+            val state = rememberPagerState(initialPage, initialPageOffsetFraction, pageCount).also {
+                pagerState = it
+            }
             composeView = LocalView.current
             focusManager = LocalFocusManager.current
             val flingBehavior =
@@ -145,7 +150,6 @@
                         .nestedScroll(nestedScrollConnection)
                 ) {
                     HorizontalOrVerticalPager(
-                        pageCount = pageCount(),
                         state = state,
                         beyondBoundsPageCount = offscreenPageLimit,
                         modifier = modifier
@@ -262,8 +266,7 @@
     @OptIn(ExperimentalFoundationApi::class)
     @Composable
     internal fun HorizontalOrVerticalPager(
-        pageCount: Int,
-        state: PagerState = rememberPagerState(),
+        state: PagerState = rememberPagerState(pageCount = { DefaultPageCount }),
         modifier: Modifier = Modifier,
         userScrollEnabled: Boolean = true,
         reverseLayout: Boolean = false,
@@ -277,7 +280,6 @@
     ) {
         if (vertical) {
             VerticalPager(
-                pageCount = pageCount,
                 state = state,
                 modifier = modifier,
                 userScrollEnabled = userScrollEnabled,
@@ -292,7 +294,6 @@
             )
         } else {
             HorizontalPager(
-                pageCount = pageCount,
                 state = state,
                 modifier = modifier,
                 userScrollEnabled = userScrollEnabled,
@@ -373,7 +374,3 @@
     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 1680009..3527b40 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,10 +33,8 @@
     @Test
     fun checkNoPagesArePlaced() {
         // Arrange
-        val state = PagerState()
-
         // Act
-        createPager(state = state, modifier = Modifier.fillMaxSize(), pageCount = { 0 })
+        createPager(pageCount = { 0 }, modifier = Modifier.fillMaxSize())
 
         // 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 bd96983..6531eba 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,8 +38,7 @@
     @Test
     fun swipeForwardAndBackward_verifyPagesAreLaidOutCorrectly() {
         // Arrange
-        val state = PagerState()
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(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 eebddc6..988a695 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,10 +36,9 @@
     @Test
     fun pageSizeFill_onlySnappedItemIsDisplayed() {
         // Arrange
-        val state = PagerState(5)
 
         // Act
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(initialPage = 5, modifier = Modifier.fillMaxSize())
 
         // Assert
         rule.onNodeWithTag("4").assertDoesNotExist()
@@ -51,7 +50,6 @@
     @Test
     fun pagerSizeCustom_visibleItemsAreWithinViewport() {
         // Arrange
-        val state = PagerState(5)
         val pagerMode = object : PageSize {
             override fun Density.calculateMainAxisPageSize(
                 availableSpace: Int,
@@ -63,7 +61,7 @@
 
         // Act
         createPager(
-            state = state,
+            initialPage = 5,
             modifier = Modifier.crossAxisSize(200.dp),
             offscreenPageLimit = 0,
             pageSize = { pagerMode }
@@ -71,14 +69,14 @@
 
         // Assert
         rule.runOnIdle {
-            val visibleItems = state.layoutInfo.visiblePagesInfo.size
+            val visibleItems = pagerState.layoutInfo.visiblePagesInfo.size
             val pageCount = with(rule.density) {
                 (pagerSize / (pageSize + config.pageSpacing.roundToPx()))
             } + 1
             Truth.assertThat(visibleItems).isEqualTo(pageCount)
         }
 
-        for (pageIndex in 5 until state.layoutInfo.visiblePagesInfo.size + 4) {
+        for (pageIndex in 5 until pagerState.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 ff8f42c..06cd075 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,24 +52,22 @@
 
     @Test
     fun accessibilityScroll_scrollToPage() {
-        val state = PagerState()
-        createPager(state, offscreenPageLimit = 1)
+        createPager(offscreenPageLimit = 1)
 
-        rule.runOnIdle { assertThat(state.currentPage).isEqualTo(0) }
+        rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(0) }
 
         rule.onNodeWithTag("1").assertExists()
         rule.onNodeWithTag("1").performScrollTo()
 
-        rule.runOnIdle { assertThat(state.currentPage).isEqualTo(1) }
-        rule.runOnIdle { assertThat(state.currentPageOffsetFraction).isEqualTo(0.0f) }
+        rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(1) }
+        rule.runOnIdle { assertThat(pagerState.currentPageOffsetFraction).isEqualTo(0.0f) }
     }
 
     @Test
     fun accessibilityPaging_animateScrollToPage() {
-        val state = PagerState(initialPage = 5)
-        createPager(state)
+        createPager(initialPage = 5, pageCount = { DefaultPageCount })
 
-        rule.runOnIdle { assertThat(state.currentPage).isEqualTo(5) }
+        rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(5) }
 
         val actionBackward = if (vertical) {
             android.R.id.accessibilityActionPageUp
@@ -86,8 +84,8 @@
         }
 
         // Go to the previous page
-        rule.runOnIdle { assertThat(state.currentPage).isEqualTo(4) }
-        rule.runOnIdle { assertThat(state.currentPageOffsetFraction).isEqualTo(0.0f) }
+        rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(4) }
+        rule.runOnIdle { assertThat(pagerState.currentPageOffsetFraction).isEqualTo(0.0f) }
 
         val actionForward = if (vertical) {
             android.R.id.accessibilityActionPageDown
@@ -104,16 +102,15 @@
         }
 
         // Go to the next page
-        rule.runOnIdle { assertThat(state.currentPage).isEqualTo(5) }
-        rule.runOnIdle { assertThat(state.currentPageOffsetFraction).isEqualTo(0.0f) }
+        rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(5) }
+        rule.runOnIdle { assertThat(pagerState.currentPageOffsetFraction).isEqualTo(0.0f) }
     }
 
     @Test
     fun userScrollEnabledIsOff_shouldNotAllowPageAccessibilityActions() {
         // Arrange
-        val state = PagerState()
         createPager(
-            state = state,
+            pageCount = { DefaultPageCount },
             userScrollEnabled = false,
             modifier = Modifier.fillMaxSize()
         )
@@ -129,23 +126,22 @@
     @Test
     fun focusScroll_forwardAndBackward_shouldGoToPage_pageShouldBeCorrectlyPlaced() {
         // Arrange
-        val state = PagerState()
-        createPager(state)
+        createPager(pageCount = { DefaultPageCount })
         rule.runOnIdle { firstItemFocusRequester.requestFocus() }
 
         // Act: move forward
         rule.runOnIdle { focusManager.moveFocus(FocusDirection.Next) }
 
         // Assert
-        rule.runOnIdle { assertThat(state.currentPage).isEqualTo(1) }
-        rule.runOnIdle { assertThat(state.currentPageOffsetFraction).isEqualTo(0.0f) }
+        rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(1) }
+        rule.runOnIdle { assertThat(pagerState.currentPageOffsetFraction).isEqualTo(0.0f) }
 
         // Act: move backward
         rule.runOnIdle { focusManager.moveFocus(FocusDirection.Previous) }
 
         // Assert
-        rule.runOnIdle { assertThat(state.currentPage).isEqualTo(0) }
-        rule.runOnIdle { assertThat(state.currentPageOffsetFraction).isEqualTo(0.0f) }
+        rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(0) }
+        rule.runOnIdle { assertThat(pagerState.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 66adc7b..3ca1e45 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,12 +74,10 @@
 
     @Test
     fun contentPaddingIsApplied() {
-        val state = PagerState()
         val containerSize = pageTotalSize * 2
         val largePaddingSize = pageTotalSize
 
         createPager(
-            state = state,
             modifier = Modifier
                 .requiredSize(containerSize)
                 .testTag(PagerTag),
@@ -104,7 +102,7 @@
             .assertCrossAxisSizeIsEqualTo(containerSize - smallPaddingSize * 2)
             .assertMainAxisSizeIsEqualTo(pageTotalSize)
 
-        state.scrollBy(largePaddingSize)
+        pagerState.scrollBy(largePaddingSize)
 
         rule.onNodeWithTag(PageTag)
             .assertStartPositionInRootIsEqualTo(0.dp)
@@ -113,10 +111,7 @@
 
     @Test
     fun contentPaddingIsNotAffectingScrollPosition() {
-        val state = PagerState()
-
         createPager(
-            state = state,
             modifier = Modifier
                 .requiredSize(pageTotalSize * 2)
                 .testTag(PagerTag),
@@ -132,19 +127,17 @@
             )
         }
 
-        state.assertScrollPosition(0, 0.dp)
+        pagerState.assertScrollPosition(0, 0.dp)
 
-        state.scrollBy(pageTotalSize)
+        pagerState.scrollBy(pageTotalSize)
 
-        state.assertScrollPosition(0, pageTotalSize)
+        pagerState.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),
@@ -166,9 +159,9 @@
         rule.onNodeWithTag("2")
             .assertStartPositionInRootIsEqualTo(pageTotalSize * 2 + padding)
 
-        state.scrollBy(padding)
+        pagerState.scrollBy(padding)
 
-        state.assertScrollPosition(1, padding - pageTotalSize)
+        pagerState.assertScrollPosition(1, padding - pageTotalSize)
 
         rule.onNodeWithTag("0")
             .assertStartPositionInRootIsEqualTo(0.dp)
@@ -182,10 +175,8 @@
 
     @Test
     fun scrollBackwardItemWithinStartPaddingDisplayed() {
-        val state = PagerState()
         val padding = pageTotalSize * 1.5f
         createPager(
-            state = state,
             modifier = Modifier
                 .requiredSize(padding * 2 + pageTotalSize)
                 .testTag(PagerTag),
@@ -200,10 +191,10 @@
             )
         }
 
-        state.scrollBy(pageTotalSize * 3)
-        state.scrollBy(-pageTotalSize * 1.5f)
+        pagerState.scrollBy(pageTotalSize * 3)
+        pagerState.scrollBy(-pageTotalSize * 1.5f)
 
-        state.assertScrollPosition(1, pageTotalSize * 0.5f)
+        pagerState.assertScrollPosition(1, pageTotalSize * 0.5f)
 
         rule.onNodeWithTag("0")
             .assertStartPositionInRootIsEqualTo(pageTotalSize * 1.5f - padding)
@@ -217,10 +208,8 @@
 
     @Test
     fun scrollForwardTillTheEnd() {
-        val state = PagerState()
         val padding = pageTotalSize * 1.5f
         createPager(
-            state = state,
             modifier = Modifier
                 .requiredSize(padding * 2 + pageTotalSize)
                 .testTag(PagerTag),
@@ -235,9 +224,9 @@
             )
         }
 
-        state.scrollBy(pageTotalSize * 3)
+        pagerState.scrollBy(pageTotalSize * 3)
 
-        state.assertScrollPosition(3, 0.dp)
+        pagerState.assertScrollPosition(3, 0.dp)
 
         rule.onNodeWithTag("1")
             .assertStartPositionInRootIsEqualTo(pageTotalSize - padding)
@@ -247,9 +236,9 @@
             .assertStartPositionInRootIsEqualTo(pageTotalSize * 3 - padding)
 
         // there are no space to scroll anymore, so it should change nothing
-        state.scrollBy(10.dp)
+        pagerState.scrollBy(10.dp)
 
-        state.assertScrollPosition(3, 0.dp)
+        pagerState.assertScrollPosition(3, 0.dp)
 
         rule.onNodeWithTag("1")
             .assertStartPositionInRootIsEqualTo(pageTotalSize - padding)
@@ -261,10 +250,8 @@
 
     @Test
     fun scrollForwardTillTheEndAndABitBack() {
-        val state = PagerState()
         val padding = pageTotalSize * 1.5f
         createPager(
-            state = state,
             modifier = Modifier
                 .requiredSize(padding * 2 + pageTotalSize)
                 .testTag(PagerTag),
@@ -279,10 +266,10 @@
             )
         }
 
-        state.scrollBy(pageTotalSize * 3)
-        state.scrollBy(-pageTotalSize / 2)
+        pagerState.scrollBy(pageTotalSize * 3)
+        pagerState.scrollBy(-pageTotalSize / 2)
 
-        state.assertScrollPosition(2, pageTotalSize / 2)
+        pagerState.assertScrollPosition(2, pageTotalSize / 2)
 
         rule.onNodeWithTag("1")
             .assertStartPositionInRootIsEqualTo(pageTotalSize * 1.5f - padding)
@@ -295,15 +282,16 @@
     @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(
@@ -331,15 +319,16 @@
     @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)
                 ) { }
             }
@@ -355,15 +344,16 @@
     @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 { }
@@ -383,10 +373,8 @@
         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,
@@ -411,7 +399,7 @@
             .assertStartPositionInRootIsEqualTo(-pageTotalSize / 2)
 
         // Scroll to the top.
-        state.scrollBy(pageTotalSize * 2.5f)
+        pagerState.scrollBy(pageTotalSize * 2.5f)
 
         rule.onNodeWithTag("2").assertStartPositionInRootIsEqualTo(topPadding)
         // Shouldn't be visible
@@ -424,10 +412,8 @@
         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,
@@ -449,7 +435,7 @@
         rule.onNodeWithTag("1").assertDoesNotExist()
 
         // Scroll to the top.
-        state.scrollBy(pageTotalSize * 5f)
+        pagerState.scrollBy(pageTotalSize * 5f)
 
         rule.onNodeWithTag("2").assertStartPositionInRootIsEqualTo(topPadding)
         // Shouldn't be visible
@@ -461,7 +447,7 @@
     fun overscrollWithContentPadding() {
         lateinit var state: PagerState
         rule.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState { 2 }
             Box(
                 modifier = Modifier
                     .testTag(ContainerTag)
@@ -470,7 +456,6 @@
                 HorizontalOrVerticalPager(
                     state = state,
                     contentPadding = PaddingValues(mainAxis = smallPaddingSize),
-                    pageCount = 2,
                     pageSize = PageSize.Fixed(pageTotalSize)
                 ) {
                     Box(
@@ -512,7 +497,7 @@
     fun totalPaddingLargerParentSize_initialState() {
         lateinit var state: PagerState
         rule.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState() { 4 }
             Box(
                 modifier = Modifier
                     .testTag(ContainerTag)
@@ -521,7 +506,6 @@
                 HorizontalOrVerticalPager(
                     state = state,
                     contentPadding = PaddingValues(mainAxis = pageTotalSize),
-                    pageCount = 4,
                     pageSize = PageSize.Fixed(pageTotalSize)
                 ) {
                     Box(
@@ -550,7 +534,7 @@
     fun totalPaddingLargerParentSize_scrollByPadding() {
         lateinit var state: PagerState
         rule.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState { 4 }
             Box(
                 modifier = Modifier
                     .testTag(ContainerTag)
@@ -559,7 +543,6 @@
                 HorizontalOrVerticalPager(
                     state = state,
                     contentPadding = PaddingValues(mainAxis = pageTotalSize),
-                    pageCount = 4,
                     pageSize = PageSize.Fixed(pageTotalSize)
                 ) {
                     Box(
@@ -592,7 +575,7 @@
     fun totalPaddingLargerParentSize_scrollToLastItem() {
         lateinit var state: PagerState
         rule.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState { 4 }
             Box(
                 modifier = Modifier
                     .testTag(ContainerTag)
@@ -601,7 +584,6 @@
                 HorizontalOrVerticalPager(
                     state = state,
                     contentPadding = PaddingValues(mainAxis = pageTotalSize),
-                    pageCount = 4,
                     pageSize = PageSize.Fixed(pageTotalSize)
                 ) {
                     Box(
@@ -634,7 +616,7 @@
     fun totalPaddingLargerParentSize_scrollToLastItemByDelta() {
         lateinit var state: PagerState
         rule.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState { 4 }
             Box(
                 modifier = Modifier
                     .testTag(ContainerTag)
@@ -644,7 +626,6 @@
                     state = state,
                     contentPadding = PaddingValues(mainAxis = pageTotalSize),
                     pageSize = PageSize.Fixed(pageTotalSize),
-                    pageCount = 4
                 ) {
                     Box(
                         Modifier
@@ -677,7 +658,7 @@
         // the whole end content padding is displayed
         lateinit var state: PagerState
         rule.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState { 4 }
             Box(
                 modifier = Modifier
                     .testTag(ContainerTag)
@@ -686,8 +667,7 @@
                 HorizontalOrVerticalPager(
                     state = state,
                     contentPadding = PaddingValues(mainAxis = pageTotalSize),
-                    pageSize = PageSize.Fixed(pageTotalSize),
-                    pageCount = 4
+                    pageSize = PageSize.Fixed(pageTotalSize)
                 ) {
                     Box(
                         Modifier
@@ -716,7 +696,7 @@
     fun eachPaddingLargerParentSize_initialState() {
         lateinit var state: PagerState
         rule.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState { 4 }
             Box(
                 modifier = Modifier
                     .testTag(ContainerTag)
@@ -725,8 +705,7 @@
                 HorizontalOrVerticalPager(
                     state = state,
                     contentPadding = PaddingValues(mainAxis = pageTotalSize * 2),
-                    pageSize = PageSize.Fixed(pageTotalSize),
-                    pageCount = 4
+                    pageSize = PageSize.Fixed(pageTotalSize)
                 ) {
                     Box(
                         Modifier
@@ -751,7 +730,7 @@
     fun eachPaddingLargerParentSize_scrollByPadding() {
         lateinit var state: PagerState
         rule.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState { 4 }
             Box(
                 modifier = Modifier
                     .testTag(ContainerTag)
@@ -760,8 +739,7 @@
                 HorizontalOrVerticalPager(
                     state = state,
                     contentPadding = PaddingValues(mainAxis = pageTotalSize * 2),
-                    pageSize = PageSize.Fixed(pageTotalSize),
-                    pageCount = 4
+                    pageSize = PageSize.Fixed(pageTotalSize)
                 ) {
                     Box(
                         Modifier
@@ -793,7 +771,7 @@
     fun eachPaddingLargerParentSize_scrollToLastItem() {
         lateinit var state: PagerState
         rule.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState { 4 }
             Box(
                 modifier = Modifier
                     .testTag(ContainerTag)
@@ -802,8 +780,7 @@
                 HorizontalOrVerticalPager(
                     state = state,
                     contentPadding = PaddingValues(mainAxis = pageTotalSize * 2),
-                    pageSize = PageSize.Fixed(pageTotalSize),
-                    pageCount = 4
+                    pageSize = PageSize.Fixed(pageTotalSize)
                 ) {
                     Box(
                         Modifier
@@ -838,7 +815,7 @@
     fun eachPaddingLargerParentSize_scrollToLastItemByDelta() {
         lateinit var state: PagerState
         rule.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState { 4 }
             Box(
                 modifier = Modifier
                     .testTag(ContainerTag)
@@ -847,8 +824,7 @@
                 HorizontalOrVerticalPager(
                     state = state,
                     contentPadding = PaddingValues(mainAxis = pageTotalSize * 2),
-                    pageSize = PageSize.Fixed(pageTotalSize),
-                    pageCount = 4
+                    pageSize = PageSize.Fixed(pageTotalSize)
                 ) {
                     Box(
                         Modifier
@@ -884,7 +860,7 @@
         // only the end content padding is displayed
         lateinit var state: PagerState
         rule.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState { 4 }
             Box(
                 modifier = Modifier
                     .testTag(ContainerTag)
@@ -893,8 +869,7 @@
                 HorizontalOrVerticalPager(
                     state = state,
                     contentPadding = PaddingValues(mainAxis = pageTotalSize * 2),
-                    pageSize = PageSize.Fixed(pageTotalSize),
-                    pageCount = 4
+                    pageSize = PageSize.Fixed(pageTotalSize)
                 ) {
                     Box(
                         Modifier
@@ -925,7 +900,7 @@
         val padding = PaddingValues(start = 20.dp, end = 8.dp)
         lateinit var state: PagerState
         rule.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState { 4 }
             CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) {
                 HorizontalOrVerticalPager(
                     modifier = Modifier
@@ -933,7 +908,6 @@
                         .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 2c60da4..4f02a20 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,31 +30,39 @@
 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.drawWithContent
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.geometry.Size
 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 : SingleOrientationPagerTest(Orientation.Horizontal) {
+class PagerContentTest {
+
+    @get:Rule
+    val rule = createComposeRule()
 
     @OptIn(ExperimentalFoundationApi::class)
     @Test
     fun pageContent_makeSureContainerOwnsOutsideModifiers() {
         // Arrange
-        val state = PagerState()
+        lateinit var state: PagerState
         rule.setContent {
-            HorizontalOrVerticalPager(
-                pageCount = 10,
-                state = state,
+            HorizontalPager(
+                state = rememberPagerState { 10 }.also { state = it },
                 contentPadding = PaddingValues(horizontal = 32.dp),
                 pageSpacing = 4.dp,
                 modifier = Modifier
@@ -82,45 +90,51 @@
 
     @OptIn(ExperimentalFoundationApi::class)
     @Test
+    @SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
     fun pageContent_makeSureInnerModifiersAreAppliedToPages() {
         // Arrange
-        val state = PagerState()
-        val drawingList = mutableListOf<Int>()
+        val colors = listOf(Color.Blue, Color.Green, Color.Red)
         rule.setContent {
-            HorizontalOrVerticalPager(
-                pageCount = 10,
-                state = state,
+            HorizontalPager(
+                state = rememberPagerState { colors.size },
                 modifier = Modifier
-                    .width(100.dp)
-                    .testTag("pager"),
-                pageSize = PageSize.Fixed(10.dp)
+                    .width(6.dp)
+                    .testTag(PagerTestTag),
+                pageSize = PageSize.Fixed(2.dp)
             ) { page ->
+                val color = colors[page]
                 Box(
                     modifier = Modifier
-                        .background(Color.Black)
-                        .size(100.dp)
-                        .zIndex(if (page % 2 == 0) 100f else 50f)
-                        .drawWithContent {
-                            drawingList.add(page)
-                        }
                         .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())
+                            )
+                        }
                 )
             }
         }
 
-        rule.runOnIdle {
-            assertContentEquals(drawingList, listOf(1, 3, 5, 7, 9, 0, 2, 4, 6, 8))
-        }
+        rule.onNodeWithTag(PagerTestTag)
+            .captureToImage()
+            .assertPixels { Color.Green }
     }
 
     @OptIn(ExperimentalFoundationApi::class)
     @Test
     fun scrollableState_isScrollableWhenChangingPages() {
         val states = mutableMapOf<Int, ScrollState>()
-        val pagerState = PagerState()
+        val pagerState = PagerStateImpl(
+            initialPage = 0,
+            initialPageOffsetFraction = 0.0f,
+            updatedPageCount = { 2 })
         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 33cc710..e9c8ddf 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,8 +54,7 @@
         rule.setContent {
             InfiniteAxisRootComposable {
                 HorizontalOrVerticalPager(
-                    pageCount = DefaultPageCount,
-                    state = rememberPagerState(),
+                    state = rememberPagerState(pageCount = { DefaultPageCount }),
                     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 a2b44b83..b9975e5 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,10 +57,7 @@
 
     @Test
     fun visiblePagesAreCorrect() {
-        val state = PagerState()
-
         createPager(
-            state,
             modifier = Modifier.requiredSize(pageSizeDp * 3.5f),
             pageCount = { 5 },
             pageSize = { PageSize.Fixed(pageSizeDp) }
@@ -68,16 +65,13 @@
             Box(Modifier.requiredSize(pageSizeDp))
         }
         rule.runOnIdle {
-            state.layoutInfo.assertVisiblePages(count = 4)
+            pagerState.layoutInfo.assertVisiblePages(count = 4)
         }
     }
 
     @Test
     fun visiblePagesAreCorrectAfterScroll() {
-        val state = PagerState()
-
         createPager(
-            state,
             modifier = Modifier.requiredSize(pageSizeDp * 3.5f),
             pageCount = { 5 },
             pageSize = { PageSize.Fixed(pageSizeDp) }
@@ -87,11 +81,11 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollToPage(1)
-                state.scrollBy(10f)
+                pagerState.scrollToPage(1)
+                pagerState.scrollBy(10f)
             }
 
-            state.layoutInfo.assertVisiblePages(
+            pagerState.layoutInfo.assertVisiblePages(
                 count = 4,
                 startIndex = 1,
                 startOffset = -10
@@ -101,10 +95,7 @@
 
     @Test
     fun visiblePagesAreCorrectWithSpacing() {
-        val state = PagerState()
-
         createPager(
-            state,
             modifier = Modifier.requiredSize(pageSizeDp * 3.5f),
             pageCount = { 5 },
             pageSpacing = pageSizeDp,
@@ -114,22 +105,20 @@
         }
 
         rule.runOnIdle {
-            state.layoutInfo.assertVisiblePages(count = 2, spacing = pageSizePx)
+            pagerState.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 = state) {
-                    snapshotFlow { state.layoutInfo }.collect {
+                LaunchedEffect(key1 = pagerState) {
+                    snapshotFlow { pagerState.layoutInfo }.collect {
                         currentInfo.value = it
                     }
                 }
@@ -142,7 +131,7 @@
             // empty it here and scrolling should invoke observingFun again
             currentInfo.value = null
             runBlocking {
-                state.scrollToPage(1)
+                pagerState.scrollToPage(1)
             }
         }
 
@@ -154,17 +143,15 @@
 
     @Test
     fun visiblePagesAreObservableWhenResize() {
-        val state = PagerState()
         var pageSize by mutableStateOf(PageSize.Fixed(pageSizeDp * 2))
         var currentInfo: PagerLayoutInfo? = null
 
         @Composable
         fun observingFun() {
-            currentInfo = state.layoutInfo
+            currentInfo = pagerState.layoutInfo
         }
 
         createPager(
-            state,
             pageCount = { 1 },
             pageSize = { pageSize },
             additionalContent = { observingFun() }
@@ -190,10 +177,7 @@
     @Test
     fun totalCountIsCorrect() {
         var count by mutableStateOf(10)
-        val state = PagerState()
-
         createPager(
-            state,
             pageCount = { count },
             pageSize = { PageSize.Fixed(10.dp) }
         ) {
@@ -201,12 +185,12 @@
         }
 
         rule.runOnIdle {
-            assertThat(state.layoutInfo.pagesCount).isEqualTo(10)
+            assertThat(pagerState.layoutInfo.pagesCount).isEqualTo(10)
             count = 20
         }
 
         rule.runOnIdle {
-            assertThat(state.layoutInfo.pagesCount).isEqualTo(20)
+            assertThat(pagerState.layoutInfo.pagesCount).isEqualTo(20)
         }
     }
 
@@ -214,10 +198,7 @@
     fun viewportOffsetsAndSizeAreCorrect() {
         val sizePx = 45
         val sizeDp = with(rule.density) { sizePx.toDp() }
-        val state = PagerState()
-
         createPager(
-            state,
             modifier = Modifier
                 .mainAxisSize(sizeDp)
                 .crossAxisSize(sizeDp * 2),
@@ -228,9 +209,9 @@
         }
 
         rule.runOnIdle {
-            assertThat(state.layoutInfo.viewportStartOffset).isEqualTo(0)
-            assertThat(state.layoutInfo.viewportEndOffset).isEqualTo(sizePx)
-            assertThat(state.layoutInfo.viewportSize).isEqualTo(
+            assertThat(pagerState.layoutInfo.viewportStartOffset).isEqualTo(0)
+            assertThat(pagerState.layoutInfo.viewportEndOffset).isEqualTo(sizePx)
+            assertThat(pagerState.layoutInfo.viewportSize).isEqualTo(
                 if (vertical) IntSize(sizePx * 2, sizePx) else IntSize(sizePx, sizePx * 2)
             )
         }
@@ -249,10 +230,8 @@
         val afterContentPaddingDp = with(rule.density) {
             if (!reverseLayout) endPaddingPx.toDp() else startPaddingPx.toDp()
         }
-        val state = PagerState()
 
         createPager(
-            state,
             modifier = Modifier
                 .mainAxisSize(sizeDp)
                 .crossAxisSize(sizeDp * 2),
@@ -269,10 +248,10 @@
         }
 
         rule.runOnIdle {
-            assertThat(state.layoutInfo.viewportStartOffset).isEqualTo(-startPaddingPx)
-            assertThat(state.layoutInfo.viewportEndOffset).isEqualTo(sizePx - startPaddingPx)
-            assertThat(state.layoutInfo.afterContentPadding).isEqualTo(endPaddingPx)
-            assertThat(state.layoutInfo.viewportSize).isEqualTo(
+            assertThat(pagerState.layoutInfo.viewportStartOffset).isEqualTo(-startPaddingPx)
+            assertThat(pagerState.layoutInfo.viewportEndOffset).isEqualTo(sizePx - startPaddingPx)
+            assertThat(pagerState.layoutInfo.afterContentPadding).isEqualTo(endPaddingPx)
+            assertThat(pagerState.layoutInfo.viewportSize).isEqualTo(
                 if (vertical) IntSize(sizePx * 2, sizePx) else IntSize(sizePx, sizePx * 2)
             )
         }
@@ -280,10 +259,7 @@
 
     @Test
     fun emptyPagesInVisiblePagesInfo() {
-        val state = PagerState()
-
         createPager(
-            state,
             pageCount = { 2 },
             pageSize = { PageSize.Fixed(pageSizeDp) }
         ) {
@@ -291,9 +267,9 @@
         }
 
         rule.runOnIdle {
-            assertThat(state.layoutInfo.visiblePagesInfo.size).isEqualTo(2)
-            assertThat(state.layoutInfo.visiblePagesInfo.first().index).isEqualTo(0)
-            assertThat(state.layoutInfo.visiblePagesInfo.last().index).isEqualTo(1)
+            assertThat(pagerState.layoutInfo.visiblePagesInfo.size).isEqualTo(2)
+            assertThat(pagerState.layoutInfo.visiblePagesInfo.first().index).isEqualTo(0)
+            assertThat(pagerState.layoutInfo.visiblePagesInfo.last().index).isEqualTo(1)
         }
     }
 
@@ -310,10 +286,8 @@
         val afterContentPaddingDp = with(rule.density) {
             if (!reverseLayout) endPaddingPx.toDp() else startPaddingPx.toDp()
         }
-        val state = PagerState()
 
         createPager(
-            state,
             modifier = Modifier
                 .mainAxisSize(sizeDp)
                 .crossAxisSize(sizeDp * 2),
@@ -328,11 +302,11 @@
         ) {}
 
         rule.runOnIdle {
-            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(
+            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(
                 if (vertical) IntSize(sizePx * 2, sizePx) else IntSize(sizePx, sizePx * 2)
             )
         }
@@ -351,10 +325,8 @@
         val afterContentPaddingDp = with(rule.density) {
             if (!reverseLayout) endPaddingPx.toDp() else startPaddingPx.toDp()
         }
-        val state = PagerState()
 
         createPager(
-            state,
             modifier = Modifier
                 .mainAxisSize(sizeDp)
                 .crossAxisSize(sizeDp * 2),
@@ -371,11 +343,11 @@
         }
 
         rule.runOnIdle {
-            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(
+            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(
                 if (vertical) IntSize(sizePx * 2, sizePx) else IntSize(sizePx, sizePx * 2)
             )
         }
@@ -383,10 +355,7 @@
 
     @Test
     fun reverseLayoutIsCorrect() {
-        val state = PagerState()
-
         createPager(
-            state,
             modifier = Modifier.requiredSize(pageSizeDp * 3.5f),
             pageCount = { 5 },
             pageSize = { PageSize.Fixed(pageSizeDp) }
@@ -395,17 +364,13 @@
         }
 
         rule.runOnIdle {
-            assertThat(state.layoutInfo.reverseLayout).isEqualTo(param.reverseLayout)
+            assertThat(pagerState.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) }
@@ -414,7 +379,7 @@
         }
 
         rule.runOnIdle {
-            assertThat(state.layoutInfo.orientation)
+            assertThat(pagerState.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 ffa4aed..78b2758 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,7 +20,6 @@
 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
@@ -35,10 +34,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
@@ -54,8 +53,7 @@
     @Test
     fun nestedScrollContent_shouldNotPropagateUnconsumedFlings() {
         // Arrange
-        val pagerState = PagerState()
-        createPager(pagerState) {
+        createPager(pageCount = { DefaultPageCount }) {
             LazyList(
                 modifier = Modifier.fillMaxSize(),
                 contentPadding = PaddingValues(0.dp),
@@ -93,7 +91,6 @@
     @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 {
@@ -101,7 +98,10 @@
                 return Velocity.Zero
             }
         }
-        createPager(pagerState, nestedScrollConnection = dataCapturingConnection) {
+        createPager(
+            pageCount = { DefaultPageCount },
+            nestedScrollConnection = dataCapturingConnection
+        ) {
             LazyList(
                 modifier = Modifier.fillMaxSize(),
                 contentPadding = PaddingValues(0.dp),
@@ -141,9 +141,8 @@
     @Test
     fun nestedScrollContent_shouldPropagateScrollCorrectly() {
         // Arrange
-        val pagerState = PagerState()
         val lazyListState = LazyListState(9)
-        createPager(pagerState) {
+        createPager(pageCount = { DefaultPageCount }) {
             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 4e93b07..aaf1a6f 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,8 +36,11 @@
     @Test
     fun offscreenPageLimitIsUsed_shouldPlaceMoreItemsThanVisibleOnesAsWeScroll() {
         // Arrange
-        val state = PagerState()
-        createPager(state = state, modifier = Modifier.fillMaxSize(), offscreenPageLimit = 1)
+        createPager(
+            pageCount = { DefaultPageCount },
+            modifier = Modifier.fillMaxSize(),
+            offscreenPageLimit = 1
+        )
         val delta = pagerSize * 1.4f * scrollForwardSign
 
         repeat(DefaultAnimationRepetition) {
@@ -50,25 +53,29 @@
             // Next page was placed
             rule.runOnIdle {
                 Truth.assertThat(placed).contains(
-                    (state.currentPage + 1)
+                    (pagerState.currentPage + 1)
                         .coerceAtMost(DefaultPageCount - 1)
                 )
             }
         }
         rule.waitForIdle()
-        confirmPageIsInCorrectPosition(state.currentPage)
+        confirmPageIsInCorrectPosition(pagerState.currentPage)
     }
 
     @Test
     fun offscreenPageLimitIsUsed_shouldPlaceMoreItemsThanVisibleOnes() {
         // Arrange
         val initialIndex = 5
-        val state = PagerState(initialIndex)
 
         // Act
-        createPager(state = state, modifier = Modifier.fillMaxSize(), offscreenPageLimit = 2)
-        val firstVisible = state.layoutInfo.visiblePagesInfo.first().index
-        val lastVisible = state.layoutInfo.visiblePagesInfo.last().index
+        createPager(
+            initialPage = initialIndex,
+            pageCount = { DefaultPageCount },
+            modifier = Modifier.fillMaxSize(),
+            offscreenPageLimit = 2
+        )
+        val firstVisible = pagerState.layoutInfo.visiblePagesInfo.first().index
+        val lastVisible = pagerState.layoutInfo.visiblePagesInfo.last().index
         // Assert
         rule.runOnIdle {
             Truth.assertThat(placed).contains(firstVisible - 2)
@@ -85,15 +92,19 @@
     @Test
     fun offscreenPageLimitIsNotUsed_shouldNotPlaceMoreItemsThanVisibleOnes() {
         // Arrange
-        val state = PagerState(5)
 
         // Act
-        createPager(state = state, modifier = Modifier.fillMaxSize(), offscreenPageLimit = 0)
+        createPager(
+            initialPage = 5,
+            pageCount = { DefaultPageCount },
+            modifier = Modifier.fillMaxSize(),
+            offscreenPageLimit = 0
+        )
 
         // Assert
         rule.waitForIdle()
-        val firstVisible = state.layoutInfo.visiblePagesInfo.first().index
-        val lastVisible = state.layoutInfo.visiblePagesInfo.last().index
+        val firstVisible = pagerState.layoutInfo.visiblePagesInfo.first().index
+        val lastVisible = pagerState.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 a56661e..abd50db 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,6 +37,7 @@
 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
@@ -44,18 +45,22 @@
 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 :
-    SingleOrientationPagerTest(orientation = Orientation.Horizontal) {
+class PagerPinnableContainerTest {
+
+    @get:Rule
+    val rule = createComposeRule()
 
     private var pinnableContainer: PinnableContainer? = null
 
     private var pageSizeDp = Dp.Unspecified
 
     private val composed = mutableSetOf<Int>()
+    private lateinit var pagerState: PagerState
 
     @Before
     fun setup() {
@@ -81,13 +86,11 @@
 
     @Test
     fun pinnedPageIsComposedAndPlacedWhenScrolledOut() {
-        val state = PagerState()
         // Arrange.
         rule.setContent {
-            HorizontalOrVerticalPager(
-                state = state,
+            HorizontalPager(
+                state = rememberPagerState { 100 }.also { pagerState = it },
                 modifier = Modifier.size(pageSizeDp * 2),
-                pageCount = 100,
                 pageSize = PageSize.Fixed(pageSizeDp)
             ) { page ->
                 if (page == 1) {
@@ -104,7 +107,7 @@
         rule.runOnIdle {
             assertThat(composed).contains(1)
             runBlocking {
-                state.scrollToPage(3)
+                pagerState.scrollToPage(3)
             }
         }
 
@@ -126,13 +129,11 @@
 
     @Test
     fun pagesBetweenPinnedAndCurrentVisibleAreNotComposed() {
-        val state = PagerState()
         // Arrange.
         rule.setContent {
-            HorizontalOrVerticalPager(
-                state = state,
+            HorizontalPager(
+                state = rememberPagerState { 100 }.also { pagerState = it },
                 modifier = Modifier.size(pageSizeDp * 2),
-                pageCount = 100,
                 pageSize = PageSize.Fixed(pageSizeDp)
             ) { page ->
                 if (page == 1) {
@@ -148,7 +149,7 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollToPage(4)
+                pagerState.scrollToPage(4)
             }
         }
 
@@ -168,13 +169,11 @@
 
     @Test
     fun pinnedPageAfterVisibleOnesIsComposedAndPlacedWhenScrolledOut() {
-        val state = PagerState()
         // Arrange.
         rule.setContent {
-            HorizontalOrVerticalPager(
-                state = state,
+            HorizontalPager(
+                state = rememberPagerState { 100 }.also { pagerState = it },
                 modifier = Modifier.size(pageSizeDp * 2),
-                pageCount = 100,
                 pageSize = PageSize.Fixed(pageSizeDp)
             ) { page ->
                 if (page == 4) {
@@ -186,7 +185,7 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollToPage(4)
+                pagerState.scrollToPage(4)
             }
         }
 
@@ -202,7 +201,7 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollToPage(0)
+                pagerState.scrollToPage(0)
             }
         }
 
@@ -223,13 +222,11 @@
 
     @Test
     fun pinnedPageCanBeUnpinned() {
-        val state = PagerState()
         // Arrange.
         rule.setContent {
-            HorizontalOrVerticalPager(
-                state = state,
+            HorizontalPager(
+                state = rememberPagerState { 100 }.also { pagerState = it },
                 modifier = Modifier.size(pageSizeDp * 2),
-                pageCount = 100,
                 pageSize = PageSize.Fixed(pageSizeDp)
             ) { page ->
                 if (page == 1) {
@@ -245,7 +242,7 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollToPage(3)
+                pagerState.scrollToPage(3)
             }
         }
 
@@ -269,11 +266,10 @@
 
     @Test
     fun pinnedPageIsStillPinnedWhenReorderedAndNotVisibleAnymore() {
-        val state = PagerState()
         var list by mutableStateOf(listOf(0, 1, 2, 3, 4))
         // Arrange.
         rule.setContent {
-            Pager(state, list, 2, 3)
+            Pager(list, 2, 3)
         }
 
         rule.runOnIdle {
@@ -299,11 +295,10 @@
     }
 
     @Composable
-    fun Pager(state: PagerState, dataset: List<Int>, pinnedPage: Int, visiblePages: Int) {
-        HorizontalOrVerticalPager(
-            state = state,
-            modifier = Modifier.mainAxisSize(pageSizeDp * visiblePages),
-            pageCount = dataset.size,
+    fun Pager(dataset: List<Int>, pinnedPage: Int, visiblePages: Int) {
+        HorizontalPager(
+            state = rememberPagerState { dataset.size },
+            modifier = Modifier.width(pageSizeDp * visiblePages),
             pageSize = PageSize.Fixed(pageSizeDp),
             key = { dataset[it] }
         ) { page ->
@@ -316,13 +311,17 @@
 
     @Test
     fun unpinnedWhenPagerStateChanges() {
-        var state by mutableStateOf(PagerState(initialPage = 2))
+        var state by mutableStateOf(
+            PagerStateImpl(
+                initialPage = 2,
+                initialPageOffsetFraction = 0f,
+                updatedPageCount = { 100 })
+        )
         // Arrange.
         rule.setContent {
-            HorizontalOrVerticalPager(
+            HorizontalPager(
                 state = state,
                 modifier = Modifier.size(pageSizeDp * 2),
-                pageCount = 100,
                 pageSize = PageSize.Fixed(pageSizeDp)
             ) { page ->
                 if (page == 2) {
@@ -350,7 +349,10 @@
 
         rule.runOnIdle {
             assertThat(composed).contains(2)
-            state = PagerState()
+            state = PagerStateImpl(
+                initialPage = 0,
+                initialPageOffsetFraction = 0f,
+                updatedPageCount = { 100 })
         }
 
         rule.waitUntil {
@@ -364,13 +366,17 @@
 
     @Test
     fun pinAfterPagerStateChange() {
-        var state by mutableStateOf(PagerState())
+        var state by mutableStateOf(
+            PagerStateImpl(
+                initialPage = 0,
+                initialPageOffsetFraction = 0f,
+                updatedPageCount = { 100 })
+        )
         // Arrange.
         rule.setContent {
-            HorizontalOrVerticalPager(
+            HorizontalPager(
                 state = state,
                 modifier = Modifier.size(pageSizeDp * 2),
-                pageCount = 100,
                 pageSize = PageSize.Fixed(pageSizeDp)
             ) { page ->
                 if (page == 0) {
@@ -381,7 +387,10 @@
         }
 
         rule.runOnIdle {
-            state = PagerState()
+            state = PagerStateImpl(
+                initialPage = 0,
+                initialPageOffsetFraction = 0f,
+                updatedPageCount = { 100 })
         }
 
         rule.runOnIdle {
@@ -407,13 +416,12 @@
 
     @Test
     fun pagesArePinnedBasedOnGlobalIndexes() {
-        val state = PagerState(initialPage = 3)
         // Arrange.
+        lateinit var state: PagerState
         rule.setContent {
-            HorizontalOrVerticalPager(
-                state = state,
+            HorizontalPager(
+                state = rememberPagerState(initialPage = 3) { 100 }.also { state = it },
                 modifier = Modifier.size(pageSizeDp * 2),
-                pageCount = 100,
                 pageSize = PageSize.Fixed(pageSizeDp)
             ) { page ->
                 if (page == 3) {
@@ -451,14 +459,13 @@
 
     @Test
     fun pinnedPageIsRemovedWhenNotVisible() {
-        val state = PagerState(initialPage = 3)
+        lateinit var state: PagerState
         var pageCount by mutableStateOf(10)
         // Arrange.
         rule.setContent {
-            HorizontalOrVerticalPager(
-                state = state,
+            HorizontalPager(
+                state = rememberPagerState(initialPage = 3) { pageCount }.also { state = it },
                 modifier = Modifier.size(pageSizeDp * 2),
-                pageCount = pageCount,
                 pageSize = PageSize.Fixed(pageSizeDp)
             ) { page ->
                 if (page == 3) {
@@ -496,11 +503,10 @@
 
     @Test
     fun pinnedPageIsRemovedWhenVisible() {
-        val state = PagerState()
         var pages by mutableStateOf(listOf(0, 1, 2))
         // Arrange.
         rule.setContent {
-            Pager(state = state, dataset = pages, pinnedPage = 1, visiblePages = 2)
+            Pager(dataset = pages, pinnedPage = 1, visiblePages = 2)
         }
 
         rule.runOnIdle {
@@ -522,13 +528,11 @@
 
     @Test
     fun pinnedMultipleTimes() {
-        val state = PagerState(0)
         // Arrange.
         rule.setContent {
-            HorizontalOrVerticalPager(
-                state = state,
+            HorizontalPager(
+                state = rememberPagerState { 100 }.also { pagerState = it },
                 modifier = Modifier.size(pageSizeDp * 2),
-                pageCount = 100,
                 pageSize = PageSize.Fixed(pageSizeDp)
             ) { page ->
                 if (page == 1) {
@@ -549,7 +553,7 @@
             handles.add(requireNotNull(pinnableContainer).pin())
             assertThat(composed).contains(0)
             runBlocking {
-                state.scrollToPage(3)
+                pagerState.scrollToPage(3)
             }
         }
 
@@ -583,8 +587,8 @@
         // Arrange.
         rule.setContent {
             CompositionLocalProvider(LocalPinnableContainer provides parentContainer) {
-                HorizontalOrVerticalPager(
-                    pageCount = 1,
+                HorizontalPager(
+                    state = rememberPagerState { 1 },
                     pageSize = PageSize.Fixed(pageSizeDp)
                 ) {
                     pinnableContainer = LocalPinnableContainer.current
@@ -627,8 +631,8 @@
         // Arrange.
         rule.setContent {
             CompositionLocalProvider(LocalPinnableContainer provides parentContainer) {
-                HorizontalOrVerticalPager(
-                    pageCount = 1,
+                HorizontalPager(
+                    state = rememberPagerState { 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 cedcfd6..18ab68b 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,7 +52,6 @@
 
     var pageSizePx = 30
     val pageSizeDp = with(rule.density) { pageSizePx.toDp() }
-    lateinit var state: PagerState
 
     @Test
     fun notPrefetchingForwardInitially() {
@@ -76,7 +75,7 @@
         val preFetchIndex = 2
         rule.runOnIdle {
             runBlocking {
-                state.scrollBy(5f)
+                pagerState.scrollBy(5f)
             }
         }
 
@@ -94,7 +93,7 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollBy(-5f)
+                pagerState.scrollBy(-5f)
             }
         }
 
@@ -113,7 +112,7 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollBy(5f)
+                pagerState.scrollBy(5f)
             }
         }
         var prefetchIndex = initialIndex + 2
@@ -126,8 +125,8 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollBy(-2f)
-                state.scrollBy(-1f)
+                pagerState.scrollBy(-2f)
+                pagerState.scrollBy(-1f)
             }
         }
 
@@ -146,7 +145,7 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollBy(5f)
+                pagerState.scrollBy(5f)
             }
         }
 
@@ -154,8 +153,8 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollBy(pageSizePx / 2f)
-                state.scrollBy(pageSizePx / 2f)
+                pagerState.scrollBy(pageSizePx / 2f)
+                pagerState.scrollBy(pageSizePx / 2f)
             }
         }
 
@@ -177,7 +176,7 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollBy(-5f)
+                pagerState.scrollBy(-5f)
             }
         }
 
@@ -185,8 +184,8 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollBy(-pageSizePx / 2f)
-                state.scrollBy(-pageSizePx / 2f)
+                pagerState.scrollBy(-pageSizePx / 2f)
+                pagerState.scrollBy(-pageSizePx / 2f)
             }
         }
 
@@ -207,7 +206,7 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollBy(5f)
+                pagerState.scrollBy(5f)
             }
         }
 
@@ -222,8 +221,8 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollBy(-2f)
-                state.scrollBy(-1f)
+                pagerState.scrollBy(-2f)
+                pagerState.scrollBy(-1f)
             }
         }
 
@@ -259,7 +258,7 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollBy(5f)
+                pagerState.scrollBy(5f)
             }
         }
 
@@ -273,7 +272,7 @@
 
         rule.runOnIdle {
             runBlocking {
-                state.scrollBy(-2f)
+                pagerState.scrollBy(-2f)
             }
         }
 
@@ -298,11 +297,10 @@
             ) { constraints ->
                 val placeable = if (emit) {
                     subcompose(Unit) {
-                        state = rememberPagerState()
+                        pagerState = rememberPagerState { 1000 }
                         HorizontalOrVerticalPager(
                             modifier = Modifier.mainAxisSize(pageSizeDp * 1.5f),
-                            state = state,
-                            pageCount = 1000
+                            state = pagerState
                         ) {
                             Spacer(
                                 Modifier
@@ -328,7 +326,7 @@
         rule.runOnIdle {
             // this will schedule the prefetching
             runBlocking(AutoTestFrameClock()) {
-                state.scrollBy(pageSize.toFloat())
+                pagerState.scrollBy(pageSize.toFloat())
             }
             // then we synchronously dispose LazyColumn
             emit = false
@@ -342,11 +340,10 @@
     fun snappingToOtherPositionWhilePrefetchIsScheduled() {
         val composedItems = mutableListOf<Int>()
         rule.setContent {
-            state = rememberPagerState()
+            pagerState = rememberPagerState { 1000 }
             HorizontalOrVerticalPager(
                 modifier = Modifier.mainAxisSize(pageSizeDp * 1.5f),
-                state = state,
-                pageCount = 1000
+                state = pagerState
             ) {
                 composedItems.add(it)
                 Spacer(
@@ -367,10 +364,10 @@
             runBlocking(AutoTestFrameClock()) {
                 // this will move the viewport so pages 1 and 2 are visible
                 // and schedule a prefetching for 3
-                state.scrollBy(pageSize.toFloat())
+                pagerState.scrollBy(pageSize.toFloat())
                 // then we move so that pages 100 and 101 are visible.
                 // this should cancel the prefetch for 3
-                state.scrollToPage(100)
+                pagerState.scrollToPage(100)
             }
         }
 
@@ -393,14 +390,14 @@
             runBlocking(AutoTestFrameClock()) {
                 // this will move the viewport so pages 1-2 are visible
                 // and schedule a prefetching for 3
-                state.scrollBy(pageSizePx.toFloat())
+                pagerState.scrollBy(pageSizePx.toFloat())
 
                 // move viewport by screen size to pages 4-5, so page 3 is just behind
                 // the first visible page
-                state.scrollBy(pageSizePx * 3f)
+                pagerState.scrollBy(pageSizePx * 3f)
 
                 // move scroll further to pages 5-6, so page 3 is reused
-                state.scrollBy(pageSizePx.toFloat())
+                pagerState.scrollBy(pageSizePx.toFloat())
             }
         }
 
@@ -409,7 +406,7 @@
         rule.runOnIdle {
             runBlocking(AutoTestFrameClock()) {
                 // scroll again to ensure page 3 was dropped
-                state.scrollBy(pageSizePx * 100f)
+                pagerState.scrollBy(pageSizePx * 100f)
             }
         }
 
@@ -439,16 +436,13 @@
         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 d683975..4129468 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,8 +41,7 @@
     @Test
     fun swipeWithLowVelocity_defaultVelocityThreshold_shouldBounceBack() {
         // Arrange
-        val state = PagerState(5)
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(initialPage = 5, modifier = Modifier.fillMaxSize())
         val delta = pagerSize * 0.4f * scrollForwardSign
 
         // Act - forward
@@ -75,10 +74,9 @@
     @Test
     fun swipeWithLowVelocity_customVelocityThreshold_shouldBounceBack() {
         // Arrange
-        val state = PagerState(5)
         val snapVelocityThreshold = 200.dp
         createPager(
-            state = state,
+            initialPage = 5,
             modifier = Modifier.fillMaxSize(),
             snapVelocityThreshold = snapVelocityThreshold
         )
@@ -114,8 +112,7 @@
     @Test
     fun swipeWithHighVelocity_defaultVelocityTreshold_shouldGoToNextPage() {
         // Arrange
-        val state = PagerState(5)
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(initialPage = 5, modifier = Modifier.fillMaxSize())
         // make sure the scroll distance is not enough to go to next page
         val delta = pagerSize * 0.4f * scrollForwardSign
 
@@ -149,10 +146,9 @@
     @Test
     fun swipeWithHighVelocity_customVelocityThreshold_shouldGoToNextPage() {
         // Arrange
-        val state = PagerState(5)
         val snapVelocityThreshold = 200.dp
         createPager(
-            state = state,
+            initialPage = 5,
             modifier = Modifier.fillMaxSize(),
             snapVelocityThreshold = snapVelocityThreshold
         )
@@ -189,8 +185,7 @@
     @Test
     fun swipeWithHighVelocity_overHalfPage_shouldGoToNextPage() {
         // Arrange
-        val state = PagerState(5)
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(initialPage = 5, modifier = Modifier.fillMaxSize())
         // make sure the scroll distance is not enough to go to next page
         val delta = pagerSize * 0.8f * scrollForwardSign
 
@@ -224,8 +219,7 @@
     @Test
     fun scrollWithoutVelocity_shouldSettlingInClosestPage() {
         // Arrange
-        val state = PagerState(5)
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(initialPage = 5, modifier = Modifier.fillMaxSize())
         // This will scroll 1 whole page before flinging
         val delta = pagerSize * 1.4f * scrollForwardSign
 
@@ -236,9 +230,9 @@
         rule.waitForIdle()
 
         // Assert
-        assertThat(state.currentPage).isAtMost(7)
-        rule.onNodeWithTag("${state.currentPage}").assertIsDisplayed()
-        confirmPageIsInCorrectPosition(state.currentPage)
+        assertThat(pagerState.currentPage).isAtMost(7)
+        rule.onNodeWithTag("${pagerState.currentPage}").assertIsDisplayed()
+        confirmPageIsInCorrectPosition(pagerState.currentPage)
 
         // Act - backward
         onPager().performTouchInput {
@@ -247,19 +241,18 @@
         rule.waitForIdle()
 
         // Assert
-        assertThat(state.currentPage).isAtLeast(5)
-        rule.onNodeWithTag("${state.currentPage}").assertIsDisplayed()
-        confirmPageIsInCorrectPosition(state.currentPage)
+        assertThat(pagerState.currentPage).isAtLeast(5)
+        rule.onNodeWithTag("${pagerState.currentPage}").assertIsDisplayed()
+        confirmPageIsInCorrectPosition(pagerState.currentPage)
     }
 
     @Test
     fun scrollWithSameVelocity_shouldYieldSameResult_forward() {
         // Arrange
         var initialPage = 1
-        val state = PagerState(initialPage)
         createPager(
             pageSize = { PageSize.Fixed(200.dp) },
-            state = state,
+            initialPage = initialPage,
             modifier = Modifier.fillMaxSize(),
             pageCount = { 100 },
             snappingPage = PagerSnapDistance.atMost(3)
@@ -273,13 +266,13 @@
         }
         rule.waitForIdle()
 
-        val pageDisplacement = state.currentPage - initialPage
+        val pageDisplacement = pagerState.currentPage - initialPage
 
         // Repeat starting from different places
         // reset
         initialPage = 10
         rule.runOnIdle {
-            runBlocking { state.scrollToPage(initialPage) }
+            runBlocking { pagerState.scrollToPage(initialPage) }
         }
 
         onPager().performTouchInput {
@@ -287,11 +280,11 @@
         }
         rule.waitForIdle()
 
-        assertThat(state.currentPage - initialPage).isEqualTo(pageDisplacement)
+        assertThat(pagerState.currentPage - initialPage).isEqualTo(pageDisplacement)
 
         initialPage = 50
         rule.runOnIdle {
-            runBlocking { state.scrollToPage(initialPage) }
+            runBlocking { pagerState.scrollToPage(initialPage) }
         }
 
         onPager().performTouchInput {
@@ -299,17 +292,16 @@
         }
         rule.waitForIdle()
 
-        assertThat(state.currentPage - initialPage).isEqualTo(pageDisplacement)
+        assertThat(pagerState.currentPage - initialPage).isEqualTo(pageDisplacement)
     }
 
     @Test
     fun scrollWithSameVelocity_shouldYieldSameResult_backward() {
         // Arrange
         var initialPage = 90
-        val state = PagerState(initialPage)
         createPager(
             pageSize = { PageSize.Fixed(200.dp) },
-            state = state,
+            initialPage = initialPage,
             modifier = Modifier.fillMaxSize(),
             pageCount = { 100 },
             snappingPage = PagerSnapDistance.atMost(3)
@@ -323,13 +315,13 @@
         }
         rule.waitForIdle()
 
-        val pageDisplacement = state.currentPage - initialPage
+        val pageDisplacement = pagerState.currentPage - initialPage
 
         // Repeat starting from different places
         // reset
         initialPage = 70
         rule.runOnIdle {
-            runBlocking { state.scrollToPage(initialPage) }
+            runBlocking { pagerState.scrollToPage(initialPage) }
         }
 
         onPager().performTouchInput {
@@ -337,11 +329,11 @@
         }
         rule.waitForIdle()
 
-        assertThat(state.currentPage - initialPage).isEqualTo(pageDisplacement)
+        assertThat(pagerState.currentPage - initialPage).isEqualTo(pageDisplacement)
 
         initialPage = 30
         rule.runOnIdle {
-            runBlocking { state.scrollToPage(initialPage) }
+            runBlocking { pagerState.scrollToPage(initialPage) }
         }
 
         onPager().performTouchInput {
@@ -349,7 +341,7 @@
         }
         rule.waitForIdle()
 
-        assertThat(state.currentPage - initialPage).isEqualTo(pageDisplacement)
+        assertThat(pagerState.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 6e5d7ee..6b97a8e 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,6 +26,8 @@
 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
@@ -51,7 +53,7 @@
     @Test
     fun pagerStateNotAttached_shouldReturnDefaultValues_andChangeAfterAttached() = runBlocking {
         // Arrange
-        val state = PagerState(initialPage = 5, initialPageOffsetFraction = 0.2f)
+        val state = PagerStateImpl(5, 0.2f) { DefaultPageCount }
 
         assertThat(state.currentPage).isEqualTo(5)
         assertThat(state.currentPageOffsetFraction).isEqualTo(0.2f)
@@ -59,7 +61,21 @@
         val currentPage = derivedStateOf { state.currentPage }
         val currentPageOffsetFraction = derivedStateOf { state.currentPageOffsetFraction }
 
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        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)
+            }
+        }
 
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
             state.scrollToPage(state.currentPage + 1)
@@ -74,16 +90,15 @@
     @Test
     fun scrollToPage_shouldPlacePagesCorrectly() = runBlocking {
         // Arrange
-        val state = PagerState()
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(modifier = Modifier.fillMaxSize())
 
         // Act and Assert
         repeat(DefaultAnimationRepetition) {
-            assertThat(state.currentPage).isEqualTo(it)
+            assertThat(pagerState.currentPage).isEqualTo(it)
             withContext(Dispatchers.Main + AutoTestFrameClock()) {
-                state.scrollToPage(state.currentPage + 1)
+                pagerState.scrollToPage(pagerState.currentPage + 1)
             }
-            confirmPageIsInCorrectPosition(state.currentPage)
+            confirmPageIsInCorrectPosition(pagerState.currentPage)
         }
     }
 
@@ -91,314 +106,312 @@
     @Test
     fun scrollToPage_usedOffset_shouldPlacePagesCorrectly() = runBlocking {
         // Arrange
-        val state = PagerState()
+
         suspend fun scrollToPageWithOffset(page: Int, offset: Float) {
             withContext(Dispatchers.Main + AutoTestFrameClock()) {
-                state.scrollToPage(page, offset)
+                pagerState.scrollToPage(page, offset)
             }
         }
 
         // Arrange
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(modifier = Modifier.fillMaxSize())
 
         // Act
         scrollToPageWithOffset(10, 0.5f)
 
         // Assert
-        confirmPageIsInCorrectPosition(state.currentPage, 10, pageOffset = 0.5f)
+        confirmPageIsInCorrectPosition(pagerState.currentPage, 10, pageOffset = 0.5f)
 
         // Act
         scrollToPageWithOffset(4, 0.2f)
 
         // Assert
-        confirmPageIsInCorrectPosition(state.currentPage, 4, pageOffset = 0.2f)
+        confirmPageIsInCorrectPosition(pagerState.currentPage, 4, pageOffset = 0.2f)
 
         // Act
         scrollToPageWithOffset(12, -0.4f)
 
         // Assert
-        confirmPageIsInCorrectPosition(state.currentPage, 12, pageOffset = -0.4f)
+        confirmPageIsInCorrectPosition(pagerState.currentPage, 12, pageOffset = -0.4f)
 
         // Act
         scrollToPageWithOffset(DefaultPageCount - 1, 0.5f)
 
         // Assert
-        confirmPageIsInCorrectPosition(state.currentPage, DefaultPageCount - 1)
+        confirmPageIsInCorrectPosition(pagerState.currentPage, DefaultPageCount - 1)
 
         // Act
         scrollToPageWithOffset(0, -0.5f)
 
         // Assert
-        confirmPageIsInCorrectPosition(state.currentPage, 0)
+        confirmPageIsInCorrectPosition(pagerState.currentPage, 0)
     }
 
     @Test
     fun scrollToPage_longSkipShouldNotPlaceIntermediatePages() = runBlocking {
         // Arrange
-        val state = PagerState()
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+
+        createPager(modifier = Modifier.fillMaxSize())
 
         // Act
-        assertThat(state.currentPage).isEqualTo(0)
+        assertThat(pagerState.currentPage).isEqualTo(0)
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
-            state.scrollToPage(DefaultPageCount - 1)
+            pagerState.scrollToPage(DefaultPageCount - 1)
         }
 
         // Assert
         rule.runOnIdle {
-            assertThat(state.currentPage).isEqualTo(DefaultPageCount - 1)
+            assertThat(pagerState.currentPage).isEqualTo(DefaultPageCount - 1)
             assertThat(placed).doesNotContain(DefaultPageCount / 2 - 1)
             assertThat(placed).doesNotContain(DefaultPageCount / 2)
             assertThat(placed).doesNotContain(DefaultPageCount / 2 + 1)
         }
-        confirmPageIsInCorrectPosition(state.currentPage)
+        confirmPageIsInCorrectPosition(pagerState.currentPage)
     }
 
     @Test
     fun animateScrollToPage_shouldPlacePagesCorrectly() = runBlocking {
         // Arrange
-        val state = PagerState()
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+
+        createPager(modifier = Modifier.fillMaxSize())
 
         // Act and Assert
         repeat(DefaultAnimationRepetition) {
-            assertThat(state.currentPage).isEqualTo(it)
+            assertThat(pagerState.currentPage).isEqualTo(it)
             withContext(Dispatchers.Main + AutoTestFrameClock()) {
-                state.animateScrollToPage(state.currentPage + 1)
+                pagerState.animateScrollToPage(pagerState.currentPage + 1)
             }
-            confirmPageIsInCorrectPosition(state.currentPage)
+            confirmPageIsInCorrectPosition(pagerState.currentPage)
         }
     }
 
     @Test
     fun animateScrollToPage_usedOffset_shouldPlacePagesCorrectly() = runBlocking {
         // Arrange
-        val state = PagerState()
+
         suspend fun animateScrollToPageWithOffset(page: Int, offset: Float) {
             withContext(Dispatchers.Main + AutoTestFrameClock()) {
-                state.animateScrollToPage(page, offset)
+                pagerState.animateScrollToPage(page, offset)
             }
         }
 
         // Arrange
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(modifier = Modifier.fillMaxSize())
 
         // Act
         animateScrollToPageWithOffset(10, 0.5f)
 
         // Assert
-        confirmPageIsInCorrectPosition(state.currentPage, 10, pageOffset = 0.5f)
+        confirmPageIsInCorrectPosition(pagerState.currentPage, 10, pageOffset = 0.5f)
 
         // Act
         animateScrollToPageWithOffset(4, 0.2f)
 
         // Assert
-        confirmPageIsInCorrectPosition(state.currentPage, 4, pageOffset = 0.2f)
+        confirmPageIsInCorrectPosition(pagerState.currentPage, 4, pageOffset = 0.2f)
 
         // Act
         animateScrollToPageWithOffset(12, -0.4f)
 
         // Assert
-        confirmPageIsInCorrectPosition(state.currentPage, 12, pageOffset = -0.4f)
+        confirmPageIsInCorrectPosition(pagerState.currentPage, 12, pageOffset = -0.4f)
 
         // Act
         animateScrollToPageWithOffset(DefaultPageCount - 1, 0.5f)
 
         // Assert
-        confirmPageIsInCorrectPosition(state.currentPage, DefaultPageCount - 1)
+        confirmPageIsInCorrectPosition(pagerState.currentPage, DefaultPageCount - 1)
 
         // Act
         animateScrollToPageWithOffset(0, -0.5f)
 
         // Assert
-        confirmPageIsInCorrectPosition(state.currentPage, 0)
+        confirmPageIsInCorrectPosition(pagerState.currentPage, 0)
     }
 
     @Test
     fun animateScrollToPage_longSkipShouldNotPlaceIntermediatePages() = runBlocking {
         // Arrange
-        val state = PagerState()
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+
+        createPager(modifier = Modifier.fillMaxSize())
 
         // Act
-        assertThat(state.currentPage).isEqualTo(0)
+        assertThat(pagerState.currentPage).isEqualTo(0)
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
-            state.animateScrollToPage(DefaultPageCount - 1)
+            pagerState.animateScrollToPage(DefaultPageCount - 1)
         }
 
         // Assert
         rule.runOnIdle {
-            assertThat(state.currentPage).isEqualTo(DefaultPageCount - 1)
+            assertThat(pagerState.currentPage).isEqualTo(DefaultPageCount - 1)
             assertThat(placed).doesNotContain(DefaultPageCount / 2 - 1)
             assertThat(placed).doesNotContain(DefaultPageCount / 2)
             assertThat(placed).doesNotContain(DefaultPageCount / 2 + 1)
         }
-        confirmPageIsInCorrectPosition(state.currentPage)
+        confirmPageIsInCorrectPosition(pagerState.currentPage)
     }
 
     @Test
     fun scrollToPage_shouldCoerceWithinRange() = runBlocking {
         // Arrange
-        val state = PagerState()
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+
+        createPager(modifier = Modifier.fillMaxSize())
 
         // Act
-        assertThat(state.currentPage).isEqualTo(0)
+        assertThat(pagerState.currentPage).isEqualTo(0)
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
-            state.scrollToPage(DefaultPageCount)
+            pagerState.scrollToPage(DefaultPageCount)
         }
 
         // Assert
-        rule.runOnIdle { assertThat(state.currentPage).isEqualTo(DefaultPageCount - 1) }
+        rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(DefaultPageCount - 1) }
 
         // Act
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
-            state.scrollToPage(-1)
+            pagerState.scrollToPage(-1)
         }
 
         // Assert
-        rule.runOnIdle { assertThat(state.currentPage).isEqualTo(0) }
+        rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(0) }
     }
 
     @Test
     fun scrollToPage_usingLaunchedEffect() {
-        val state = PagerState()
-        createPager(state, additionalContent = {
-            LaunchedEffect(state) {
-                state.scrollToPage(10)
+
+        createPager(additionalContent = {
+            LaunchedEffect(pagerState) {
+                pagerState.scrollToPage(10)
             }
         })
         rule.waitForIdle()
-        assertThat(state.currentPage).isEqualTo(10)
+        assertThat(pagerState.currentPage).isEqualTo(10)
         confirmPageIsInCorrectPosition(10)
     }
 
     @Test
     fun scrollToPageWithOffset_usingLaunchedEffect() {
-        val state = PagerState()
-        createPager(state, additionalContent = {
-            LaunchedEffect(state) {
-                state.scrollToPage(10, 0.4f)
+        createPager(additionalContent = {
+            LaunchedEffect(pagerState) {
+                pagerState.scrollToPage(10, 0.4f)
             }
         })
         rule.waitForIdle()
-        assertThat(state.currentPage).isEqualTo(10)
+        assertThat(pagerState.currentPage).isEqualTo(10)
         confirmPageIsInCorrectPosition(10, pageOffset = 0.4f)
     }
 
     @Test
     fun animateScrollToPage_shouldCoerceWithinRange() = runBlocking {
         // Arrange
-        val state = PagerState()
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+
+        createPager(modifier = Modifier.fillMaxSize())
 
         // Act
-        assertThat(state.currentPage).isEqualTo(0)
+        assertThat(pagerState.currentPage).isEqualTo(0)
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
-            state.animateScrollToPage(DefaultPageCount)
+            pagerState.animateScrollToPage(DefaultPageCount)
         }
 
         // Assert
-        rule.runOnIdle { assertThat(state.currentPage).isEqualTo(DefaultPageCount - 1) }
+        rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(DefaultPageCount - 1) }
 
         // Act
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
-            state.animateScrollToPage(-1)
+            pagerState.animateScrollToPage(-1)
         }
 
         // Assert
-        rule.runOnIdle { assertThat(state.currentPage).isEqualTo(0) }
+        rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(0) }
     }
 
     @Test
     fun animateScrollToPage_moveToSamePageWithOffset_shouldScroll() = runBlocking {
         // Arrange
-        val state = PagerState(initialPage = 5)
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(initialPage = 5, modifier = Modifier.fillMaxSize())
 
         // Act
-        assertThat(state.currentPage).isEqualTo(5)
+        assertThat(pagerState.currentPage).isEqualTo(5)
 
         withContext(Dispatchers.Main + AutoTestFrameClock()) {
-            state.animateScrollToPage(5, 0.4f)
+            pagerState.animateScrollToPage(5, 0.4f)
         }
 
         // Assert
-        rule.runOnIdle { assertThat(state.currentPage).isEqualTo(5) }
-        rule.runOnIdle { assertThat(state.currentPageOffsetFraction).isWithin(0.01f).of(0.4f) }
+        rule.runOnIdle { assertThat(pagerState.currentPage).isEqualTo(5) }
+        rule.runOnIdle { assertThat(pagerState.currentPageOffsetFraction).isWithin(0.01f).of(0.4f) }
     }
 
     @Test
     fun animateScrollToPage_withPassedAnimation() = runBlocking {
         // Arrange
-        val state = PagerState()
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+
+        createPager(modifier = Modifier.fillMaxSize())
         val differentAnimation: AnimationSpec<Float> = tween()
 
         // Act and Assert
         repeat(DefaultAnimationRepetition) {
-            assertThat(state.currentPage).isEqualTo(it)
+            assertThat(pagerState.currentPage).isEqualTo(it)
             withContext(Dispatchers.Main + AutoTestFrameClock()) {
-                state.animateScrollToPage(
-                    state.currentPage + 1,
+                pagerState.animateScrollToPage(
+                    pagerState.currentPage + 1,
                     animationSpec = differentAnimation
                 )
             }
-            confirmPageIsInCorrectPosition(state.currentPage)
+            confirmPageIsInCorrectPosition(pagerState.currentPage)
         }
     }
 
     @Test
     fun animatedScrollToPage_usingLaunchedEffect() {
-        val state = PagerState()
-        createPager(state, additionalContent = {
-            LaunchedEffect(state) {
-                state.animateScrollToPage(10)
+
+        createPager(additionalContent = {
+            LaunchedEffect(pagerState) {
+                pagerState.animateScrollToPage(10)
             }
         })
         rule.waitForIdle()
-        assertThat(state.currentPage).isEqualTo(10)
+        assertThat(pagerState.currentPage).isEqualTo(10)
         confirmPageIsInCorrectPosition(10)
     }
 
     @Test
     fun animatedScrollToPageWithOffset_usingLaunchedEffect() {
-        val state = PagerState()
-        createPager(state, additionalContent = {
-            LaunchedEffect(state) {
-                state.animateScrollToPage(10, 0.4f)
+
+        createPager(additionalContent = {
+            LaunchedEffect(pagerState) {
+                pagerState.animateScrollToPage(10, 0.4f)
             }
         })
         rule.waitForIdle()
-        assertThat(state.currentPage).isEqualTo(10)
+        assertThat(pagerState.currentPage).isEqualTo(10)
         confirmPageIsInCorrectPosition(10, pageOffset = 0.4f)
     }
 
     @Test
     fun animatedScrollToPage_viewPortNumberOfPages_usingLaunchedEffect_shouldNotPlaceALlPages() {
-        val state = PagerState()
-        createPager(state, additionalContent = {
-            LaunchedEffect(state) {
-                state.animateScrollToPage(DefaultPageCount - 1)
+
+        createPager(additionalContent = {
+            LaunchedEffect(pagerState) {
+                pagerState.animateScrollToPage(DefaultPageCount - 1)
             }
         })
         rule.waitForIdle()
         // Assert
         rule.runOnIdle {
-            assertThat(state.currentPage).isEqualTo(DefaultPageCount - 1)
+            assertThat(pagerState.currentPage).isEqualTo(DefaultPageCount - 1)
             assertThat(placed).doesNotContain(DefaultPageCount / 2 - 1)
             assertThat(placed).doesNotContain(DefaultPageCount / 2)
             assertThat(placed).doesNotContain(DefaultPageCount / 2 + 1)
         }
-        confirmPageIsInCorrectPosition(state.currentPage)
+        confirmPageIsInCorrectPosition(pagerState.currentPage)
     }
 
     @Test
     fun currentPage_shouldChangeWhenClosestPageToSnappedPositionChanges() {
         // Arrange
-        val state = PagerState()
-        createPager(state = state, modifier = Modifier.fillMaxSize())
-        var previousCurrentPage = state.currentPage
+
+        createPager(modifier = Modifier.fillMaxSize())
+        var previousCurrentPage = pagerState.currentPage
 
         // Act
         // Move less than half an item
@@ -414,15 +427,15 @@
 
         // Assert
         rule.runOnIdle {
-            assertThat(state.currentPage).isEqualTo(previousCurrentPage)
+            assertThat(pagerState.currentPage).isEqualTo(previousCurrentPage)
         }
         // Release pointer
         onPager().performTouchInput { up() }
 
         rule.runOnIdle {
-            previousCurrentPage = state.currentPage
+            previousCurrentPage = pagerState.currentPage
         }
-        confirmPageIsInCorrectPosition(state.currentPage)
+        confirmPageIsInCorrectPosition(pagerState.currentPage)
 
         // Arrange
         // Pass closest to snap position threshold (over half an item)
@@ -440,24 +453,22 @@
 
         // Assert
         rule.runOnIdle {
-            assertThat(state.currentPage).isEqualTo(previousCurrentPage + 1)
+            assertThat(pagerState.currentPage).isEqualTo(previousCurrentPage + 1)
         }
 
         onPager().performTouchInput { up() }
         rule.waitForIdle()
-        confirmPageIsInCorrectPosition(state.currentPage)
+        confirmPageIsInCorrectPosition(pagerState.currentPage)
     }
 
     @Test
     fun targetPage_performScrollBelowThreshold_shouldNotShowNextPage() {
         // Arrange
-        val state = PagerState()
         createPager(
-            state = state,
             modifier = Modifier.fillMaxSize(),
             snappingPage = PagerSnapDistance.atMost(3)
         )
-        rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
+        rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
 
         rule.mainClock.autoAdvance = false
         // Act
@@ -465,7 +476,7 @@
         val forwardDelta =
             scrollForwardSign.toFloat() * with(rule.density) { DefaultPositionThreshold.toPx() / 2 }
 
-        var previousTargetPage = state.targetPage
+        var previousTargetPage = pagerState.targetPage
 
         onPager().performTouchInput {
             down(layoutStart)
@@ -473,12 +484,12 @@
         }
 
         // Assert
-        assertThat(state.targetPage).isEqualTo(previousTargetPage)
+        assertThat(pagerState.targetPage).isEqualTo(previousTargetPage)
 
         // Reset
         rule.mainClock.autoAdvance = true
         onPager().performTouchInput { up() }
-        rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
+        rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
 
         // Act
         // Moving more than threshold
@@ -486,7 +497,7 @@
             -DefaultPositionThreshold.toPx() / 2
         }
 
-        previousTargetPage = state.targetPage
+        previousTargetPage = pagerState.targetPage
 
         onPager().performTouchInput {
             down(layoutStart)
@@ -494,19 +505,17 @@
         }
 
         // Assert
-        assertThat(state.targetPage).isEqualTo(previousTargetPage)
+        assertThat(pagerState.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(state.targetPage).isEqualTo(state.currentPage) }
+        rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
 
         rule.mainClock.autoAdvance = false
         // Act
@@ -518,15 +527,15 @@
         }
 
         // Assert
-        assertThat(state.targetPage).isEqualTo(state.currentPage + 1)
-        assertThat(state.targetPage).isNotEqualTo(state.currentPage)
+        assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage + 1)
+        assertThat(pagerState.targetPage).isNotEqualTo(pagerState.currentPage)
 
         // Reset
         rule.mainClock.autoAdvance = true
         onPager().performTouchInput { up() }
-        rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
+        rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
         rule.runOnIdle {
-            runBlocking { state.scrollToPage(5) }
+            runBlocking { pagerState.scrollToPage(5) }
         }
 
         rule.mainClock.autoAdvance = false
@@ -539,117 +548,113 @@
         }
 
         // Assert
-        assertThat(state.targetPage).isEqualTo(state.currentPage - 1)
-        assertThat(state.targetPage).isNotEqualTo(state.currentPage)
+        assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage - 1)
+        assertThat(pagerState.targetPage).isNotEqualTo(pagerState.currentPage)
 
         rule.mainClock.autoAdvance = true
         onPager().performTouchInput { up() }
-        rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
+        rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
     }
 
     @Test
     fun targetPage_performingFling_shouldGoToPredictedPage() {
         // Arrange
-        val state = PagerState()
+
         createPager(
-            state = state,
             modifier = Modifier.fillMaxSize(),
             snappingPage = PagerSnapDistance.atMost(3)
         )
-        rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
+        rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
 
         rule.mainClock.autoAdvance = false
         // Act
         // Moving forward
-        var previousTarget = state.targetPage
+        var previousTarget = pagerState.targetPage
         val forwardDelta = pagerSize * scrollForwardSign.toFloat()
         onPager().performTouchInput {
             swipeWithVelocityAcrossMainAxis(20000f, forwardDelta)
         }
-        rule.mainClock.advanceTimeUntil { state.targetPage != previousTarget }
-        var flingOriginIndex = state.firstVisiblePageInfo?.index ?: 0
+        rule.mainClock.advanceTimeUntil { pagerState.targetPage != previousTarget }
+        var flingOriginIndex = pagerState.firstVisiblePage
         // Assert
-        assertThat(state.targetPage).isEqualTo(flingOriginIndex + 3)
-        assertThat(state.targetPage).isNotEqualTo(state.currentPage)
+        assertThat(pagerState.targetPage).isEqualTo(flingOriginIndex + 3)
+        assertThat(pagerState.targetPage).isNotEqualTo(pagerState.currentPage)
 
         rule.mainClock.autoAdvance = true
-        rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
+        rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
         rule.mainClock.autoAdvance = false
         // Act
         // Moving backward
-        previousTarget = state.targetPage
+        previousTarget = pagerState.targetPage
         val backwardDelta = -pagerSize * scrollForwardSign.toFloat()
         onPager().performTouchInput {
             swipeWithVelocityAcrossMainAxis(20000f, backwardDelta)
         }
-        rule.mainClock.advanceTimeUntil { state.targetPage != previousTarget }
+        rule.mainClock.advanceTimeUntil { pagerState.targetPage != previousTarget }
 
         // Assert
-        flingOriginIndex = (state.firstVisiblePageInfo?.index ?: 0) + 1
-        assertThat(state.targetPage).isEqualTo(flingOriginIndex - 3)
-        assertThat(state.targetPage).isNotEqualTo(state.currentPage)
+        flingOriginIndex = pagerState.firstVisiblePage + 1
+        assertThat(pagerState.targetPage).isEqualTo(flingOriginIndex - 3)
+        assertThat(pagerState.targetPage).isNotEqualTo(pagerState.currentPage)
 
         rule.mainClock.autoAdvance = true
-        rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
+        rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
     }
 
     @Test
     fun targetPage_shouldReflectTargetWithAnimation() {
         // Arrange
-        val state = PagerState()
+
         createPager(
-            state = state,
             modifier = Modifier.fillMaxSize()
         )
-        rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
+        rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
 
         rule.mainClock.autoAdvance = false
         // Act
         // Moving forward
-        var previousTarget = state.targetPage
+        var previousTarget = pagerState.targetPage
         rule.runOnIdle {
             scope.launch {
-                state.animateScrollToPage(DefaultPageCount - 1)
+                pagerState.animateScrollToPage(DefaultPageCount - 1)
             }
         }
-        rule.mainClock.advanceTimeUntil { state.targetPage != previousTarget }
+        rule.mainClock.advanceTimeUntil { pagerState.targetPage != previousTarget }
 
         // Assert
-        assertThat(state.targetPage).isEqualTo(DefaultPageCount - 1)
-        assertThat(state.targetPage).isNotEqualTo(state.currentPage)
+        assertThat(pagerState.targetPage).isEqualTo(DefaultPageCount - 1)
+        assertThat(pagerState.targetPage).isNotEqualTo(pagerState.currentPage)
 
         rule.mainClock.autoAdvance = true
-        rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
+        rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
         rule.mainClock.autoAdvance = false
 
         // Act
         // Moving backward
-        previousTarget = state.targetPage
+        previousTarget = pagerState.targetPage
         rule.runOnIdle {
             scope.launch {
-                state.animateScrollToPage(0)
+                pagerState.animateScrollToPage(0)
             }
         }
-        rule.mainClock.advanceTimeUntil { state.targetPage != previousTarget }
+        rule.mainClock.advanceTimeUntil { pagerState.targetPage != previousTarget }
 
         // Assert
-        assertThat(state.targetPage).isEqualTo(0)
-        assertThat(state.targetPage).isNotEqualTo(state.currentPage)
+        assertThat(pagerState.targetPage).isEqualTo(0)
+        assertThat(pagerState.targetPage).isNotEqualTo(pagerState.currentPage)
 
         rule.mainClock.autoAdvance = true
-        rule.runOnIdle { assertThat(state.targetPage).isEqualTo(state.currentPage) }
+        rule.runOnIdle { assertThat(pagerState.targetPage).isEqualTo(pagerState.currentPage) }
     }
 
     @Test
     fun settledPage_onAnimationScroll_shouldChangeOnScrollFinishedOnly() {
         // Arrange
-        val state = PagerState()
         var settledPageChanges = 0
         createPager(
-            state = state,
             modifier = Modifier.fillMaxSize(),
             additionalContent = {
-                LaunchedEffect(key1 = state.settledPage) {
+                LaunchedEffect(key1 = pagerState.settledPage) {
                     settledPageChanges++
                 }
             }
@@ -657,51 +662,49 @@
 
         // Settle page changed once for first composition
         rule.runOnIdle {
-            assertThat(state.settledPage).isEqualTo(state.currentPage)
+            assertThat(pagerState.settledPage).isEqualTo(pagerState.currentPage)
             assertTrue { settledPageChanges == 1 }
         }
 
         settledPageChanges = 0
-        val previousSettled = state.settledPage
+        val previousSettled = pagerState.settledPage
         rule.mainClock.autoAdvance = false
         // Act
         // Moving forward
         rule.runOnIdle {
             scope.launch {
-                state.animateScrollToPage(DefaultPageCount - 1)
+                pagerState.animateScrollToPage(DefaultPageCount - 1)
             }
         }
 
         // Settled page shouldn't change whilst scroll is in progress.
-        assertTrue { state.isScrollInProgress }
+        assertTrue { pagerState.isScrollInProgress }
         assertTrue { settledPageChanges == 0 }
-        assertThat(state.settledPage).isEqualTo(previousSettled)
+        assertThat(pagerState.settledPage).isEqualTo(previousSettled)
 
         rule.mainClock.advanceTimeUntil { settledPageChanges != 0 }
 
         rule.runOnIdle {
-            assertTrue { !state.isScrollInProgress }
-            assertThat(state.settledPage).isEqualTo(state.currentPage)
+            assertTrue { !pagerState.isScrollInProgress }
+            assertThat(pagerState.settledPage).isEqualTo(pagerState.currentPage)
         }
     }
 
     @Test
     fun settledPage_onGestureScroll_shouldChangeOnScrollFinishedOnly() {
         // Arrange
-        val state = PagerState()
         var settledPageChanges = 0
         createPager(
-            state = state,
             modifier = Modifier.fillMaxSize(),
             additionalContent = {
-                LaunchedEffect(key1 = state.settledPage) {
+                LaunchedEffect(key1 = pagerState.settledPage) {
                     settledPageChanges++
                 }
             }
         )
 
         settledPageChanges = 0
-        val previousSettled = state.settledPage
+        val previousSettled = pagerState.settledPage
         rule.mainClock.autoAdvance = false
         // Act
         // Moving forward
@@ -711,27 +714,26 @@
         }
 
         // Settled page shouldn't change whilst scroll is in progress.
-        assertTrue { state.isScrollInProgress }
+        assertTrue { pagerState.isScrollInProgress }
         assertTrue { settledPageChanges == 0 }
-        assertThat(state.settledPage).isEqualTo(previousSettled)
+        assertThat(pagerState.settledPage).isEqualTo(previousSettled)
 
         rule.mainClock.advanceTimeUntil { settledPageChanges != 0 }
 
         rule.runOnIdle {
-            assertTrue { !state.isScrollInProgress }
-            assertThat(state.settledPage).isEqualTo(state.currentPage)
+            assertTrue { !pagerState.isScrollInProgress }
+            assertThat(pagerState.settledPage).isEqualTo(pagerState.currentPage)
         }
     }
 
     @Test
     fun currentPageOffset_shouldReflectScrollingOfCurrentPage() {
         // Arrange
-        val state = PagerState(DefaultPageCount / 2)
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(initialPage = DefaultPageCount / 2, modifier = Modifier.fillMaxSize())
 
         // No offset initially
         rule.runOnIdle {
-            assertThat(state.currentPageOffsetFraction).isWithin(0.01f).of(0f)
+            assertThat(pagerState.currentPageOffsetFraction).isWithin(0.01f).of(0f)
         }
 
         // Act
@@ -746,7 +748,7 @@
         }
 
         rule.runOnIdle {
-            assertThat(state.currentPageOffsetFraction).isWithin(0.1f).of(0.25f)
+            assertThat(pagerState.currentPageOffsetFraction).isWithin(0.1f).of(0.25f)
         }
 
         onPager().performTouchInput { up() }
@@ -755,13 +757,13 @@
         // Reset
         rule.runOnIdle {
             scope.launch {
-                state.scrollToPage(DefaultPageCount / 2)
+                pagerState.scrollToPage(DefaultPageCount / 2)
             }
         }
 
         // No offset initially (again)
         rule.runOnIdle {
-            assertThat(state.currentPageOffsetFraction).isWithin(0.01f).of(0f)
+            assertThat(pagerState.currentPageOffsetFraction).isWithin(0.01f).of(0f)
         }
 
         // Act
@@ -776,23 +778,22 @@
         }
 
         rule.runOnIdle {
-            assertThat(state.currentPageOffsetFraction).isWithin(0.1f).of(-0.25f)
+            assertThat(pagerState.currentPageOffsetFraction).isWithin(0.1f).of(-0.25f)
         }
     }
 
     @Test
     fun initialPageOnPagerState_shouldDisplayThatPageFirst() {
         // Arrange
-        val state = PagerState(5)
 
         // Act
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(initialPage = 5, modifier = Modifier.fillMaxSize())
 
         // Assert
         rule.onNodeWithTag("4").assertDoesNotExist()
         rule.onNodeWithTag("5").assertIsDisplayed()
         rule.onNodeWithTag("6").assertDoesNotExist()
-        confirmPageIsInCorrectPosition(state.currentPage)
+        confirmPageIsInCorrectPosition(pagerState.currentPage)
     }
 
     @Test
@@ -801,11 +802,10 @@
         val tester = StateRestorationTester(rule)
         lateinit var state: PagerState
         tester.setContent {
-            state = rememberPagerState()
+            state = rememberPagerState(pageCount = { DefaultPageCount })
             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(state = state, modifier = Modifier.fillMaxSize(), additionalContent = {
-            LaunchedEffect(state) {
-                state.scrollToPage(5)
+        createPager(modifier = Modifier.fillMaxSize(), additionalContent = {
+            LaunchedEffect(pagerState) {
+                pagerState.scrollToPage(5)
             }
         })
 
         // Assert
-        assertThat(state.currentPage).isEqualTo(5)
+        assertThat(pagerState.currentPage).isEqualTo(5)
     }
 
     @Test
     fun currentPageOffsetFraction_shouldNeverBeNan() {
         rule.setContent {
-            val state = rememberPagerState()
+            val state = rememberPagerState(pageCount = { 10 })
             // Read state in composition, should never be Nan
             assertFalse { state.currentPageOffsetFraction.isNaN() }
-            HorizontalOrVerticalPager(pageCount = 10, state = state) {
+            HorizontalOrVerticalPager(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 7a5a1bc..8926c1f 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,8 +38,7 @@
     @Test
     fun swipePageTowardsEdge_shouldNotMove() {
         // Arrange
-        val state = PagerState()
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(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 24b1450..753c0a2 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,12 +20,16 @@
 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
@@ -44,9 +48,8 @@
     @Test
     fun userScrollEnabledIsOff_shouldNotAllowGestureScroll() {
         // Arrange
-        val state = PagerState()
+
         createPager(
-            state = state,
             userScrollEnabled = false,
             modifier = Modifier.fillMaxSize()
         )
@@ -56,7 +59,7 @@
 
         // Assert
         rule.runOnIdle {
-            assertThat(state.currentPage).isEqualTo(0)
+            assertThat(pagerState.currentPage).isEqualTo(0)
         }
 
         confirmPageIsInCorrectPosition(0, 0)
@@ -65,9 +68,8 @@
     @Test
     fun userScrollEnabledIsOff_shouldAllowAnimationScroll() {
         // Arrange
-        val state = PagerState()
+
         createPager(
-            state = state,
             userScrollEnabled = false,
             modifier = Modifier.fillMaxSize()
         )
@@ -75,13 +77,13 @@
         // Act
         rule.runOnIdle {
             scope.launch {
-                state.animateScrollToPage(5)
+                pagerState.animateScrollToPage(5)
             }
         }
 
         // Assert
         rule.runOnIdle {
-            assertThat(state.currentPage).isEqualTo(5)
+            assertThat(pagerState.currentPage).isEqualTo(5)
         }
         confirmPageIsInCorrectPosition(5)
     }
@@ -89,9 +91,8 @@
     @Test
     fun userScrollEnabledIsOn_shouldAllowGestureScroll() {
         // Arrange
-        val state = PagerState(5)
         createPager(
-            state = state,
+            initialPage = 5,
             userScrollEnabled = true,
             modifier = Modifier.fillMaxSize()
         )
@@ -99,25 +100,24 @@
         onPager().performTouchInput { swipeWithVelocityAcrossMainAxis(1000f) }
 
         rule.runOnIdle {
-            assertThat(state.currentPage).isNotEqualTo(5)
+            assertThat(pagerState.currentPage).isNotEqualTo(5)
         }
-        confirmPageIsInCorrectPosition(state.currentPage)
+        confirmPageIsInCorrectPosition(pagerState.currentPage)
     }
 
     @Test
     fun pageCount_pagerOnlyContainsGivenPageCountItems() {
         // Arrange
-        val state = PagerState()
 
         // Act
-        createPager(state = state, modifier = Modifier.fillMaxSize())
+        createPager(modifier = Modifier.fillMaxSize())
 
         // Assert
         repeat(DefaultPageCount) {
             rule.onNodeWithTag("$it").assertIsDisplayed()
             rule.runOnIdle {
                 scope.launch {
-                    state.scroll {
+                    pagerState.scroll {
                         scrollBy(pagerSize.toFloat())
                     }
                 }
@@ -130,12 +130,10 @@
     @Test
     fun mutablePageCount_assertPagesAreChangedIfCountIsChanged() {
         // Arrange
-        val state = PagerState()
         val pageCount = mutableStateOf(2)
         createPager(
-            state = state,
+            pageCount = { pageCount.value },
             modifier = Modifier.fillMaxSize(),
-            pageCount = { pageCount.value }
         )
 
         rule.onNodeWithTag("3").assertDoesNotExist()
@@ -149,7 +147,7 @@
             rule.onNodeWithTag("$it").assertIsDisplayed()
             rule.runOnIdle {
                 scope.launch {
-                    state.scroll {
+                    pagerState.scroll {
                         scrollBy(pagerSize.toFloat())
                     }
                 }
@@ -158,6 +156,100 @@
         }
     }
 
+    @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 ce3dd25..9f00444 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,9 +37,11 @@
 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
@@ -53,8 +55,6 @@
 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,9 +94,8 @@
     val pagerItemProvider = rememberPagerItemProvider(
         state = state,
         pageContent = pageContent,
-        key = key,
-        pageCount = pageCount
-    )
+        key = key
+    ) { state.pageCount }
 
     val beyondBoundsInfo = remember { LazyListBeyondBoundsInfo() }
 
@@ -111,7 +110,7 @@
         horizontalAlignment = horizontalAlignment,
         verticalAlignment = verticalAlignment,
         itemProvider = pagerItemProvider,
-        pageCount = pageCount,
+        pageCount = { state.pageCount },
         beyondBoundsInfo = beyondBoundsInfo
     )
 
@@ -172,10 +171,11 @@
     val state: PagerState,
     latestContent: () -> (@Composable (page: Int) -> Unit),
     key: ((index: Int) -> Any)?,
-    pageCount: Int
+    pageCount: () -> Int
 ) : LazyLayoutItemProvider {
-    private val pagerContent =
-        PagerLayoutIntervalContent(latestContent(), key = key, pageCount = pageCount)
+    private val pagerContent by derivedStateOf(structuralEqualityPolicy()) {
+        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>
-        get() = MutableIntervalList<PagerIntervalContent>().apply {
+    override val intervals: IntervalList<PagerIntervalContent> =
+        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 1f07114..c2d2fc5 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
@@ -73,6 +73,84 @@
  * 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
@@ -100,12 +178,38 @@
  * 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(),
+    state: PagerState = rememberPagerState { pageCount },
     contentPadding: PaddingValues = PaddingValues(0.dp),
     pageSize: PageSize = PageSize.Fill,
     beyondBoundsPageCount: Int = 0,
@@ -121,22 +225,99 @@
     pageContent: @Composable (page: Int) -> Unit
 ) {
     Pager(
-        modifier = modifier,
-        pageCount = pageCount,
         state = state,
+        modifier = modifier,
         contentPadding = contentPadding,
-        reverseLayout = reverseLayout,
-        orientation = Orientation.Horizontal,
-        flingBehavior = flingBehavior,
-        userScrollEnabled = userScrollEnabled,
         pageSize = pageSize,
         beyondBoundsPageCount = beyondBoundsPageCount,
         pageSpacing = pageSpacing,
-        pageContent = pageContent,
-        pageNestedScrollConnection = pageNestedScrollConnection,
+        orientation = Orientation.Horizontal,
         verticalAlignment = verticalAlignment,
         horizontalAlignment = Alignment.CenterHorizontally,
-        key = key
+        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
     )
 }
 
@@ -181,12 +362,38 @@
  * 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(),
+    state: PagerState = rememberPagerState { pageCount },
     contentPadding: PaddingValues = PaddingValues(0.dp),
     pageSize: PageSize = PageSize.Fill,
     beyondBoundsPageCount: Int = 0,
@@ -202,22 +409,21 @@
     pageContent: @Composable (page: Int) -> Unit
 ) {
     Pager(
-        modifier = modifier,
-        pageCount = pageCount,
         state = state,
+        modifier = modifier,
         contentPadding = contentPadding,
-        reverseLayout = reverseLayout,
-        orientation = Orientation.Vertical,
-        flingBehavior = flingBehavior,
-        userScrollEnabled = userScrollEnabled,
         pageSize = pageSize,
         beyondBoundsPageCount = beyondBoundsPageCount,
         pageSpacing = pageSpacing,
-        pageContent = pageContent,
-        pageNestedScrollConnection = pageNestedScrollConnection,
+        orientation = Orientation.Vertical,
         verticalAlignment = Alignment.CenterVertically,
         horizontalAlignment = horizontalAlignment,
-        key = key
+        flingBehavior = flingBehavior,
+        userScrollEnabled = userScrollEnabled,
+        reverseLayout = reverseLayout,
+        key = key,
+        pageNestedScrollConnection = pageNestedScrollConnection,
+        pageContent = pageContent
     )
 }
 
@@ -466,9 +672,11 @@
             val effectivePageSizePx = pagerState.pageSize + pagerState.pageSpacing
             val animationOffsetPx =
                 decayAnimationSpec.calculateTargetValue(0f, initialVelocity)
-            val startPage = pagerState.firstVisiblePageInfo?.let {
-                if (initialVelocity < 0) it.index + 1 else it.index
-            } ?: pagerState.currentPage
+            val startPage = if (initialVelocity < 0) {
+                pagerState.firstVisiblePage + 1
+            } else {
+                pagerState.firstVisiblePage
+            }
 
             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 78aa13a..6785dea 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,11 +64,8 @@
 ): 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 f535064..0c56d50 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 04e021f..3906300 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,15 +61,92 @@
  * @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 = PagerState.Saver) {
-        PagerState(initialPage = initialPage, initialPageOffsetFraction = initialPageOffsetFraction)
+    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 }
+                )
+            }
+        )
     }
 }
 
@@ -81,11 +158,16 @@
  */
 @ExperimentalFoundationApi
 @Stable
-class PagerState(
+abstract 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 " +
@@ -166,18 +248,6 @@
             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(
@@ -422,9 +492,9 @@
     override val isScrollInProgress: Boolean
         get() = scrollableState.isScrollInProgress
 
-    override var canScrollForward: Boolean by mutableStateOf(false)
+    final override var canScrollForward: Boolean by mutableStateOf(false)
         private set
-    override var canScrollBackward: Boolean by mutableStateOf(false)
+    final override var canScrollBackward: Boolean by mutableStateOf(false)
         private set
 
     /**
@@ -529,26 +599,6 @@
             }
         }
     }
-
-    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 a9466ca..c7e90d4 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()
+            val pagerState = rememberPagerState { itemCount }
             Box(
                 modifier = Modifier
                     .fillMaxSize(),
@@ -56,8 +56,7 @@
                         .semantics { contentDescription = "Pager" }
                         .background(Color.White),
                     state = pagerState,
-                    pageSize = PageSize.Fill,
-                    pageCount = itemCount
+                    pageSize = PageSize.Fill
                 ) {
                     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 50fc66b..df252e7 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()
+            val pagerState = rememberPagerState { itemCount }
             Box(
                 modifier = Modifier
                     .fillMaxSize()
@@ -57,7 +57,6 @@
                         .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 8b55ca8..27b2fac 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,13 +54,12 @@
 @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 ->
@@ -72,13 +71,12 @@
 @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 ->