This is my 11th consecutive game for the First-chair Challenge, and Subtitles for the first-chair challenge are likely to be in Pager layouts
There is currently a Chinese manual project for Jetpack Compose, which aims to help developers better understand and master the Compose framework.
This article is translated and written by myself. It has been published in this manual. Welcome to refer to it.
Please follow the wechat official account Jetpack Compose Museum for more information about Compose technology.
An overview of the
The library provides the Pager component for Jetpack Compose, which has similar features if you’ve used ViewPager before.
⚠️ Note that the paging class component is still experimental and the API is subject to change. All apis are annotated with @experimentalPagerAPI
HorizontalPager
One such layout is the HorizontalPager, which places all the children on a horizontal row, allowing the user to slide horizontally between the children.
The simplest usage is as follows:
// Display 10 items
val pagerState = rememberPagerState(pageCount = 10)
HorizontalPager(state = pagerState) { page ->
// Our page content
Text(
text = "Page: $page",
modifier = Modifier.fillMaxWidth()
)
}
Copy the code
If you want to jump to a particular page, you can choose to use in CoroutineScope pagerState. ScrollToPage (index) or pagerState. AnimateScrollToPage (index) one.
VerticalPager
VerticalPager is very similar to the HorizontalPager in that it places all the children on a vertical column, allowing the user to slide vertically between the children.
// Display 10 items
val pagerState = rememberPagerState(pageCount = 10)
VerticalPager(state = pagerState) { page ->
// Our page content
Text(
text = "Page: $page",
modifier = Modifier.fillMaxWidth()
)
}
Copy the code
Create a delay
All pages in HorizontalPager and VerticalPager are formed and laid out lazily according to layout requirements. As the user slides between pages, any pages that are no longer needed are dynamically removed.
Behind the scenes to limit
The API provided by PagerState allows the setting of initOffscreenLimit, which defines that when the number of pages on either side of the previous page exceeds this limit, the page will be removed and re-created as required. This value defaults to 1, but can be increased to accommodate more content.
val pagerState = rememberPagerState(
pageCount = 10,
initialOffscreenLimit = 2,
)
HorizontalPager(state = pagerState) { page ->
// ...
}
Copy the code
Child scroll effect
A common use case is to apply effects to page subitems that are triggered by scrolling.
HorizontalPagerTransitionSample example demonstrates how to do this.
The Pager component’s Content Scope allows the developer to easily retrieve the currentPage and currentPageOffset references. You can use these values to calculate the effect. We provide a calculateCurrentOffsetForPage () extension function to calculate the offset of a particular page.
import com.google.accompanist.pager.calculateCurrentOffsetForPage
HorizontalPager(state = pagerState) { page ->
Card(
Modifier
.graphicsLayer {
// Calculate the absolute offset for the current page from the
// scroll position. We use the absolute value which allows us to mirror
// any effects for both directions
val pageOffset = calculateCurrentOffsetForPage(page).absoluteValue
// We animate the scaleX + scaleY, between 85% and 100%
lerp(
start = 0.85 f,
stop = 1f,
fraction = 1f - pageOffset.coerceIn(0f.1f)
).also { scale ->
scaleX = scale
scaleY = scale
}
// We animate the alpha, between 50% and 100%
alpha = lerp(
start = 0.5 f,
stop = 1f,
fraction = 1f - pageOffset.coerceIn(0f.1f)}) {// Card content}}Copy the code
Page change response
The PagerState.CurrentPage property is updated whenever the selected page changes. You can use the snapshowFlow method to listen for changes through flow:
LaunchedEffect(pagerState) {
snapshotFlow { pagerState.currentPage }.collect { page ->
// Selected page has changed...}}Copy the code
indicator
We have also released a sibling library called Pager-Indicators that provides some simple indicator combinations for use with HorizontalPager and VerticalPager.
HorizontalPagerWithIndicatorSample and VerticalPagerWithIndicatorSample will show you how to use these indicators.
Integration Tab
A common use case for HorizontalPager is to be used in conjunction with TabRow or ScrollableTabRow.
There is a Modifier provided in the Pager-Indicators library that can be used on TAB indicators like this.
val pagerState = rememberPagerState(pageCount = pages.size)
TabRow(
// Our selected tab is our current page
selectedTabIndex = pagerState.currentPage,
// Override the indicator, using the provided pagerTabIndicatorOffset modifier
indicator = { tabPositions ->
TabRowDefaults.Indicator(
Modifier.pagerTabIndicatorOffset(pagerState, tabPositions)
)
}
) {
// Add tabs for all of our pages
pages.forEachIndexed { index, title ->
Tab(
text = { Text(title) },
selected = pagerState.currentPage == index,
onClick = { /* TODO */ },
)
}
}
HorizontalPager(state = pagerState) { page ->
// TODO: page content
}
Copy the code
usage
repositories {
mavenCentral()
}
dependencies {
implementation "com.google.accompanist:accompanist-pager:<version>"
// If using indicators, also depend on
implementation "com.google.accompanist:accompanist-pager-indicators:<version>"
}
Copy the code
download
repositories {
mavenCentral()
}
dependencies {
implementation "com.google.accompanist:accompanist-swiperefresh:<version>"
}
Copy the code
Each version can be found in the snapshot repository and updated with each commit.