Compose 中的 "ViewPager" 详解 | 开发者说·DTalk
The following article is from 江江安卓 Author 江江安卓
本文原作者: 朱江,原文发布于: 江江安卓
什么是 ViewPager
上图中就是 ViewPager 作为轮播图的简单例子。
顺嘴提一下吧,之前 Android 的 ViewPager 确实只能实现左右的滑动,但是在 2019 年的时候谷歌就推出了 ViewPager2,ViewPager2 不但可以支持左右滑动,也可以实现竖向的滑动,这样可玩性又提高了许多,也不需要为了产品的一些特定需求而去自定义 ViewGroup 了。
Compose 中的 "ViewPager"
添加依赖
上面也提到了,Compose 中并没有 ViewPager,所以需要在 build.gradle 中添加下依赖:
repositories {
mavenCentral()
}
dependencies {
implementation "com.google.accompanist:accompanist-pager:<version>"
}
将上面的 version 替换成最新的版本号即可,笔者在写的时候最新版本为 0.24.2-alpha。
水平滑动 (左右)
添加好依赖来看看如何使用吧!
HorizontalPager(count = 10) { page ->
Text(text = "Page: $page")
}
下面来看下预览图吧,如果在 Android View 中想看 ViewPager 预览的话必须得运行到真机或者虚拟机才可以看到,但是在 Compose 中直接就可以进行预览。下面来写下预览代码吧:
@OptIn(ExperimentalPagerApi::class)
@Preview(name = "Test1", heightDp = 170)
@Composable
fun PagerTest1Preview() {
PagerTest1()
}
垂直滑动 (上下)
上面写了水平滑动,这里来看下垂直滑动吧:
VerticalPager(count = 10) { page ->
Text(text = "Page: $page")
}
很容易理解吧,水平滑动是 HorizontalPager,垂直滑动就是 VerticalPager,具体详细使用在下面篇幅中介绍,这里先来看看垂直滑动的预览效果吧:
@OptIn(ExperimentalPagerApi::class)
@Preview(name = "Test3", heightDp = 170, widthDp = 100)
@Composable
fun PagerTest3Preview() {
PagerTest3()
}
预览代码和刚才差不多,就不做过多解释了,直接来看效果图吧:
不错吧,很简单的代码就实现了之前在 Android View 中比较复杂的效果。
源码解析
下面咱们来简单看看 Pager 的源码吧。
水平滑动源码
先来看看水平滑动的源码:
count: 这是可组合项 HorizontalPager 必须要写的参数,顾名思义,就是 Page 的数量; Modifier: 这个在 Compose 中见的太多了,不再赘述,修饰符; state: 用于控制或观察 Pager 状态的状态对象; reverseLayout: 反转滚动和布局的方向,默认为 false,为 true 时第一项将在最后; itemSpacing: 添加项目之间的垂直间距; contentPadding: 内容的 Padding 值; verticalAlignment: 垂直对齐为居中; flingBehavior: 描述滑动行为的逻辑; key: 滚动的位置将根据键保持; userScrollEnabled: 是否允许通过用户手势或辅助功能进行滚动。即使它被禁用,仍然可以使用该状态以编程方式滚动; content: 具体可组合项的内容,在这里,可以引用 PagerScope.currentPage 和 PagerScope 中的其他属性。
垂直滑动源码
接下来再来看下垂直滑动的源码:
horizontalAlignment: 上面水平滑动的是 verticalAlignment 垂直对齐居中,这里是水平对齐居中; flingBehavior: 描述滑动行为的逻辑也有所不同。
剩下就基本一致了。
Pager 内部实现
下面来看下 Pager 内部的实现吧,同样因为这里是源码,所以还放成图片吧:
可以看出 Pager 可组合项中有一个 isVertical 参数,用来判断是垂直滑动还是水平滑动,如果是垂直滑动的话用的是 LazyColumn,水平滑动则用的是 LazyRow,还记得吗?在 Compose 中 LazyColumn 和 LazyRow 对标的是 Android View 中的 RecyclerView,值得一说的是,现在 Android View 中的 ViewPager2 也使用的是 RecyclerView。
进阶用法
上面大概说了下 Pager 的基本用法,但如果在生产环境中一般不会这么简单,这里来举几个生产环境中可能用到的例子吧。
添加指示器
什么是指示器呢?很简单,就是文章开头那张动图中间下方的小圆圈,用来告知用户当前在第几页以及一共有几页。
之前想在 Compose 中添加指示器需要自己来绘制,但现在官方也创建了一个库专门用来实现 Pager 的指示器,来看看吧。
第一步还是在 build.gradle 中添加依赖:
repositories {
mavenCentral()
}
dependencies {
implementation "com.google.accompanist:accompanist-pager:<version>"
// 指示器
implementation "com.google.accompanist:accompanist-pager-indicators:<version>"
}
同上面一样,使用的时候需要将 version 替换成当前最新的版本,笔者在写的时候最新版本为 0.24.2-alpha。
来看下如何使用指示器吧:
// 水平指示器
HorizontalPagerIndicator(
pagerState = pagerState,
modifier = Modifier
.align(Alignment.CenterHorizontally)
.padding(16.dp),
)
// 垂直指示器
VerticalPagerIndicator(
pagerState = pagerState,
modifier = Modifier
.align(Alignment.CenterHorizontally)
.padding(16.dp),
)
是不是 so easy,指示器也是一个可组合项,只需要您传入 Pager 的状态即可,总页数以及当前的页码在 PagerState 中都有。下面先来看下效果图吧:
上图就是水平指示器的源码。方法中的绘制代码不过多赘述,大家应该都能看懂,下面来说一下参数的含义吧:
pagerState: Pager 的状态;
modifier: 修饰符,不过多解释;
activeColor: 当前活跃的指示器颜色;
inactiveColor: 当前不活跃的指示器颜色;
indicatorWidth: 指示器的宽度;
indicatorHeight: 指示器的高度;
spacing: 指示器之间的宽度;
indicatorShape: 指示器的形状,默认为圆形,大家也可以自己进行定义。
监听页面更改
每当所选页面发生更改时,都会更新该 PagerState.currentPage 属性。您可以使用该 snapshotFlow 函数来观察流的变化:
val pagerState = rememberPagerState()
LaunchedEffect(pagerState) {
snapshotFlow { pagerState.currentPage }.collect { page ->
AnalyticsService.sendPageSelectedEvent(page)
}
}
VerticalPager(
count = 10,
state = pagerState,
) { page ->
Text(text = "Page: $page")
}
修改 Pager 切换效果
大家都知道,在 Android View 中,ViewPager 的切换效果可以通过设置 PageTransformer 来进行修改。来看下官方提供 Demo 的样例吧:
看着效果还不错吧,由于里面涉及知识点太多,想学习的可以去官方的源码中进行查看:
https://github.com/google/accompanist/blob/main/sample/src/main/java/com/google/accompanist/sample/pager/HorizontalPagerTransitionSample.kt
长按右侧二维码
查看更多开发者精彩分享
"开发者说·DTalk" 面向