androidx.compose.foundation.pager
Interfaces
PageInfo |
This represents a single measured page in a |
Cmn
|
PageSize |
This is used to determine how Pages are laid out in |
Cmn
|
PagerLayoutInfo |
Contains useful information about the currently displayed layout state of a |
Cmn
|
PagerScope |
Receiver scope for |
Cmn
|
PagerSnapDistance |
|
Cmn
|
Classes
PageSize.Fixed |
Multiple pages in a viewport |
Cmn
|
PagerState |
The state that can be used to control |
Cmn
|
Objects
PageSize.Fill |
Pages take up the whole Pager size. |
Cmn
|
PagerDefaults |
Contains the default values used by |
Cmn
|
Top-level functions summary
Unit |
@ComposableA Pager that scrolls horizontally. |
Cmn
|
LazyLayoutScrollScope |
LazyLayoutScrollScope(state: PagerState, scrollScope: ScrollScope)A |
Cmn
|
PagerState |
PagerState(Creates a default |
Cmn
|
Unit |
@ComposableA Pager that scrolls vertically. |
Cmn
|
PagerState |
@ComposableCreates and remember a |
Cmn
|
Top-level functions
HorizontalPager
@Composable
fun HorizontalPager(
state: PagerState,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
pageSize: PageSize = PageSize.Fill,
beyondViewportPageCount: Int = PagerDefaults.BeyondViewportPageCount,
pageSpacing: Dp = 0.dp,
verticalAlignment: Alignment.Vertical = Alignment.CenterVertically,
flingBehavior: TargetedFlingBehavior = PagerDefaults.flingBehavior(state = state),
userScrollEnabled: Boolean = true,
reverseLayout: Boolean = false,
key: ((index: Int) -> Any)? = null,
pageNestedScrollConnection: NestedScrollConnection = PagerDefaults.pageNestedScrollConnection(state, Orientation.Horizontal),
snapPosition: SnapPosition = SnapPosition.Start,
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect(),
pageContent: @Composable PagerScope.(page: Int) -> Unit
): Unit
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 beyondViewportPageCount 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.
import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material.Text import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp // Creates a 1-pager/viewport horizontal pager with single page snapping val state = rememberPagerState { 10 } HorizontalPager(state = state, modifier = Modifier.fillMaxSize()) { page -> Box( modifier = Modifier.padding(10.dp).background(Color.Blue).fillMaxWidth().aspectRatio(1f), contentAlignment = Alignment.Center, ) { Text(text = page.toString(), fontSize = 32.sp) } }
import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.Text import androidx.compose.material.TopAppBar import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.NestedScrollSource import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp // This is a sample using NestedScroll and Pager. // We use the toolbar offset changing example from // androidx.compose.ui.samples.NestedScrollConnectionSample val pagerState = rememberPagerState { 10 } val toolbarHeight = 48.dp val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() } val toolbarOffsetHeightPx = remember { mutableStateOf(0f) } val nestedScrollConnection = remember { object : NestedScrollConnection { override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { val delta = available.y val newOffset = toolbarOffsetHeightPx.value + delta toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f) return Offset.Zero } } } Box(modifier = Modifier.fillMaxSize().nestedScroll(nestedScrollConnection)) { TopAppBar( modifier = Modifier.height(toolbarHeight).offset { IntOffset(x = 0, y = toolbarOffsetHeightPx.value.roundToInt()) }, title = { Text("Toolbar offset is ${toolbarOffsetHeightPx.value}") }, ) val paddingOffset = toolbarHeight + with(LocalDensity.current) { toolbarOffsetHeightPx.value.toDp() } HorizontalPager( modifier = Modifier.fillMaxSize(), state = pagerState, contentPadding = PaddingValues(top = paddingOffset), ) { Column(modifier = Modifier.fillMaxWidth().verticalScroll(rememberScrollState())) { repeat(20) { Box( modifier = Modifier.fillMaxWidth() .height(64.dp) .padding(4.dp) .background(if (it % 2 == 0) Color.Black else Color.Yellow), contentAlignment = Alignment.Center, ) { Text( text = it.toString(), color = if (it % 2 != 0) Color.Black else Color.Yellow, ) } } } } }
| Parameters | |
|---|---|
state: PagerState |
The state to control this pager |
modifier: Modifier = Modifier |
A modifier instance to be applied to this Pager outer layout |
contentPadding: PaddingValues = PaddingValues(0.dp) |
a padding around the whole content. This will add padding for the content after it has been clipped, which is not possible via |
pageSize: PageSize = PageSize.Fill |
Use this to change how the pages will look like inside this pager. |
beyondViewportPageCount: Int = PagerDefaults.BeyondViewportPageCount |
Pages to compose and layout before and after the list of visible pages. Note: Be aware that using a large value for |
pageSpacing: Dp = 0.dp |
The amount of space to be used to separate the pages in this Pager |
verticalAlignment: Alignment.Vertical = Alignment.CenterVertically |
How pages are aligned vertically in this Pager. |
flingBehavior: TargetedFlingBehavior = PagerDefaults.flingBehavior(state = state) |
The |
userScrollEnabled: Boolean = true |
whether the scrolling via the user gestures or accessibility actions is allowed. You can still scroll programmatically using |
reverseLayout: Boolean = false |
reverse the direction of scrolling and layout. |
key: ((index: Int) -> Any)? = null |
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. If null is passed the position in the list will represent the key. |
pageNestedScrollConnection: NestedScrollConnection = PagerDefaults.pageNestedScrollConnection(state, Orientation.Horizontal) |
A |
snapPosition: SnapPosition = SnapPosition.Start |
The calculation of how this Pager will perform snapping of pages. Use this to provide different settling to different positions in the layout. This is used by |
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect() |
the |
pageContent: @Composable PagerScope.(page: Int) -> Unit |
This Pager's page Composable. |
| See also | |
|---|---|
SnapLayoutInfoProvider |
for the implementation of a Please refer to the samples to learn how to use this API. |
LazyLayoutScrollScope
fun LazyLayoutScrollScope(state: PagerState, scrollScope: ScrollScope): LazyLayoutScrollScope
A LazyLayoutScrollScope that allows customization of animated scroll in Pager. The scope contains information about the layout where animated scroll can be performed as well as the necessary tools to do that respecting the scroll mutation priority.
import androidx.compose.animation.core.animate import androidx.compose.animation.core.tween import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.layout.LazyLayoutScrollScope import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.LazyLayoutScrollScope import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.Button import androidx.compose.material.Text import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp suspend fun PagerState.customScroll(block: suspend LazyLayoutScrollScope.() -> Unit) = scroll { block.invoke(LazyLayoutScrollScope(this@customScroll, this)) } val itemsList = (0..100).toList() val state = rememberPagerState { itemsList.size } val scope = rememberCoroutineScope() Column(Modifier.verticalScroll(rememberScrollState())) { Button( onClick = { scope.launch { state.customScroll { snapToItem(40, 0) // teleport to item 40 val distance = calculateDistanceTo(50).toFloat() var previousValue = 0f androidx.compose.animation.core.animate( 0f, distance, animationSpec = tween(5_000), ) { currentValue, _ -> previousValue += scrollBy(currentValue - previousValue) } } } } ) { Text("Scroll To Item 50") } HorizontalPager(state) { Box(Modifier.padding(2.dp).background(Color.Red).height(600.dp).fillMaxWidth()) { Text(itemsList[it].toString()) } } }
| Parameters | |
|---|---|
state: PagerState |
The |
scrollScope: ScrollScope |
The base |
| Returns | |
|---|---|
LazyLayoutScrollScope |
An implementation of |
PagerState
fun PagerState(
currentPage: Int = 0,
currentPageOffsetFraction: @FloatRange(from = -0.5, to = 0.5) Float = 0.0f,
pageCount: () -> Int
): PagerState
Creates a default PagerState to be used with a Pager
Please refer to the sample to learn how to use this API.
import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material.Text import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp // You can use PagerState to define an initial page val state = rememberPagerState(initialPage = 5) { 10 } HorizontalPager(modifier = Modifier.fillMaxSize(), state = state) { page -> Box( modifier = Modifier.padding(10.dp).background(Color.Blue).fillMaxWidth().aspectRatio(1f), contentAlignment = Alignment.Center, ) { Text(text = page.toString(), fontSize = 32.sp) } }
| Parameters | |
|---|---|
currentPage: Int = 0 |
The pager that should be shown first. |
currentPageOffsetFraction: @FloatRange(from = -0.5, to = 0.5) Float = 0.0f |
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. |
pageCount: () -> Int |
The amount of pages this Pager will have. |
VerticalPager
@Composable
fun VerticalPager(
state: PagerState,
modifier: Modifier = Modifier,
contentPadding: PaddingValues = PaddingValues(0.dp),
pageSize: PageSize = PageSize.Fill,
beyondViewportPageCount: Int = PagerDefaults.BeyondViewportPageCount,
pageSpacing: Dp = 0.dp,
horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,
flingBehavior: TargetedFlingBehavior = PagerDefaults.flingBehavior(state = state),
userScrollEnabled: Boolean = true,
reverseLayout: Boolean = false,
key: ((index: Int) -> Any)? = null,
pageNestedScrollConnection: NestedScrollConnection = PagerDefaults.pageNestedScrollConnection(state, Orientation.Vertical),
snapPosition: SnapPosition = SnapPosition.Start,
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect(),
pageContent: @Composable PagerScope.(page: Int) -> Unit
): Unit
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 beyondViewportPageCount 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.
import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.VerticalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material.Text import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp // Creates a 1-pager/viewport vertical pager with single page snapping val state = rememberPagerState { 10 } VerticalPager(state = state, modifier = Modifier.fillMaxSize()) { page -> Box( modifier = Modifier.padding(10.dp).background(Color.Blue).fillMaxWidth().aspectRatio(1f), contentAlignment = Alignment.Center, ) { Text(text = page.toString(), fontSize = 32.sp) } }
| Parameters | |
|---|---|
state: PagerState |
The state to control this pager |
modifier: Modifier = Modifier |
A modifier instance to be apply to this Pager outer layout |
contentPadding: PaddingValues = PaddingValues(0.dp) |
a padding around the whole content. This will add padding for the content after it has been clipped, which is not possible via |
pageSize: PageSize = PageSize.Fill |
Use this to change how the pages will look like inside this pager. |
beyondViewportPageCount: Int = PagerDefaults.BeyondViewportPageCount |
Pages to compose and layout before and after the list of visible pages. Note: Be aware that using a large value for |
pageSpacing: Dp = 0.dp |
The amount of space to be used to separate the pages in this Pager |
horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally |
How pages are aligned horizontally in this Pager. |
flingBehavior: TargetedFlingBehavior = PagerDefaults.flingBehavior(state = state) |
The |
userScrollEnabled: Boolean = true |
whether the scrolling via the user gestures or accessibility actions is allowed. You can still scroll programmatically using |
reverseLayout: Boolean = false |
reverse the direction of scrolling and layout. |
key: ((index: Int) -> Any)? = null |
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. If null is passed the position in the list will represent the key. |
pageNestedScrollConnection: NestedScrollConnection = PagerDefaults.pageNestedScrollConnection(state, Orientation.Vertical) |
A |
snapPosition: SnapPosition = SnapPosition.Start |
The calculation of how this Pager will perform snapping of Pages. Use this to provide different settling to different positions in the layout. This is used by |
overscrollEffect: OverscrollEffect? = rememberOverscrollEffect() |
the |
pageContent: @Composable PagerScope.(page: Int) -> Unit |
This Pager's page Composable. |
| See also | |
|---|---|
SnapLayoutInfoProvider |
for the implementation of a Please refer to the sample to learn how to use this API. |
rememberPagerState
@Composable
fun rememberPagerState(
initialPage: Int = 0,
initialPageOffsetFraction: @FloatRange(from = -0.5, to = 0.5) Float = 0.0f,
pageCount: () -> Int
): PagerState
Creates and remember a PagerState to be used with a Pager
Please refer to the sample to learn how to use this API.
import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material.Text import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp // You can use PagerState to define an initial page val state = rememberPagerState(initialPage = 5) { 10 } HorizontalPager(modifier = Modifier.fillMaxSize(), state = state) { page -> Box( modifier = Modifier.padding(10.dp).background(Color.Blue).fillMaxWidth().aspectRatio(1f), contentAlignment = Alignment.Center, ) { Text(text = page.toString(), fontSize = 32.sp) } }
| Parameters | |
|---|---|
initialPage: Int = 0 |
The pager that should be shown first. |
initialPageOffsetFraction: @FloatRange(from = -0.5, to = 0.5) Float = 0.0f |
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. |
pageCount: () -> Int |
The amount of pages this Pager will have. |