这是我参与更文挑战的第11天,活动详情查看: 更文挑战
本文翻译自 Accompanist 官方文档 – Pager layouts
目前有一个正在进行的 Jetpack Compose中文手册 项目,旨在帮助开发者更好的理解和掌握 Compose 框架,目前仍还在开荒中,欢迎大家进行关注与加入!
这篇文章由本人翻译撰写,目前已经发布到该手册中,欢迎进行查阅。
请关注微信公众号
Jetpack Compose 博物馆
获取更多 Compose 技术信息。
概述
这个库为 Jetpack Compose 提供了 pager 组件,如果你之前使用过 ViewPager,那么这类组件有着相似的特性。
⚠️ 注意
分页类组件现在还处于试验阶段,相关API随时会发生改变。所有API都被标记了@ExperimentalPagerApi
注解
HorizontalPager
HorizontalPager
是其中一种布局,他将所有子项摆放在一条水平行上,允许用户在子项之间水平滑动。
最简单用法如下所示:
// Display 10 items
val pagerState = rememberPagerState(pageCount = 10)
HorizontalPager(state = pagerState) { page ->
// Our page content
Text(
text = "Page: $page",
modifier = Modifier.fillMaxWidth()
)
}
复制代码
如果你想跳转到某一个特定页面,你可以在 CoroutineScope
中选择使用 pagerState.scrollToPage(index)
或 pagerState.animateScrollToPage(index)
二者其一即可。
VerticalPager
VerticalPager
与 HorizontalPager
非常相似,他将所有子项摆放在一条垂直列上,允许用户在子项之间垂直滑动。
// Display 10 items
val pagerState = rememberPagerState(pageCount = 10)
VerticalPager(state = pagerState) { page ->
// Our page content
Text(
text = "Page: $page",
modifier = Modifier.fillMaxWidth()
)
}
复制代码
延迟创建
HorizontalPager
与 VerticalPager
中的所有页面都是按照布局的要求延迟的组成与布置的。当用户在页面间滑动时,任何不再被需要的页面都会被动态移除。
幕后限制
PagerState
所提供 API 允许 initOffscreenLimit
的设置,这定义了当前页两侧的页数,超过这个限制的页面将会被移除,根据需求重新创建。这个值默认为1,但可以增加以承载更多的内容。
val pagerState = rememberPagerState(
pageCount = 10,
initialOffscreenLimit = 2,
)
HorizontalPager(state = pagerState) { page ->
// ...
}
复制代码
子项滚动效果
一个常见的用例是将效果施加到页面子项中,通过滚动来触发这些效果。
HorizontalPagerTransitionSample 示例中演示如何做到这一点。
在 pager 组件的 content scope 中允许开发者很轻松地拿到 currentPage
与 currentPageOffset
引用。可以使用这些值来计算效果。我们提供了 calculateCurrentOffsetForPage()
扩展函数去计算某一个特定页面的偏移量。
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.85f,
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.5f,
stop = 1f,
fraction = 1f - pageOffset.coerceIn(0f, 1f)
)
}
) {
// Card content
}
}
复制代码
页面改变响应
每当选定的页面发生变化时,PagerState.currentPage
属性就会更新。你可以使用 snapshowFlow
方法去监听改变通过 flow:
LaunchedEffect(pagerState) {
snapshotFlow { pagerState.currentPage }.collect { page ->
// Selected page has changed...
}
}
复制代码
指示器
我们还发布了一个名为 pager-indicators
的兄弟库,它提供了一些简单指示器组合,供 HorizontalPager
和 VerticalPager
使用。
HorizontalPagerWithIndicatorSample 与 VerticalPagerWithIndicatorSample 将向你展示如何去使用这些指示器。
集成Tab
对于 HorizontalPager
来说一个常见的用例是被用来与 TabRow
或 ScrollableTabRow
结合使用。
在 pager-indicators
库中提供了一个Modifier修饰符,可以像这样用在 tab 指示器上。
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
}
复制代码
用法
repositories {
mavenCentral()
}
dependencies {
implementation "com.google.accompanist:accompanist-pager:<version>"
// If using indicators, also depend on
implementation "com.google.accompanist:accompanist-pager-indicators:<version>"
}
复制代码
下载
repositories {
mavenCentral()
}
dependencies {
implementation "com.google.accompanist:accompanist-swiperefresh:<version>"
}
复制代码
每个版本可以在 快照仓库 中被找到,每次提交时都会更新。