Compose 中的 "ViewPager" 详解 | 开发者说·DTalk

d938f48841564cffcd67d4eea0844dcb.jpeg

本文原作者: 朱江,原文发布于: 江江安卓

2054416ff092e377430a35a8832e899e.png

什么是 ViewPager

ViewPager 的功能是可以使视图滑动,就像桌面左右滑动那样。写过 Android 的对它可谓是非常熟悉了,不管是轮播图的使用、亦或是页面之间的切换,都离不开它,先来看看在 Android 中的 ViewPager 实现效果吧: 

ba4c357136604ec1a484034910c385ec.gif

上图中就是 ViewPager 作为轮播图的简单例子。

顺嘴提一下吧,之前 Android 的 ViewPager 确实只能实现左右的滑动,但是在 2019 年的时候谷歌就推出了 ViewPager2,ViewPager2 不但可以支持左右滑动,也可以实现竖向的滑动,这样可玩性又提高了许多,也不需要为了产品的一些特定需求而去自定义 ViewGroup 了。

dc484aa9b76eba216e4b7e42563fd27f.png

Compose 中的 "ViewPager"

其实 Compose 中并没有 ViewPager,而是谷歌在 Compose 的扩展库中写了一个名叫 Pager 的库,实现了类似 Android 中 ViewPager 的功能。

添加依赖

上面也提到了,Compose 中并没有 ViewPager,所以需要在 build.gradle 中添加下依赖: 

https://search.maven.org/search?q=g:com.google.accompanist

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 中只需要一行代码。

下面来看下预览图吧,如果在 Android View 中想看 ViewPager 预览的话必须得运行到真机或者虚拟机才可以看到,但是在 Compose 中直接就可以进行预览。下面来写下预览代码吧: 

@OptIn(ExperimentalPagerApi::class)
@Preview(name = "Test1", heightDp = 170)
@Composable
fun PagerTest1Preview() {
    PagerTest1()
}

简单介绍一下上面的预览代码吧,先看第一行注解 OptIn,这是由于 Pager 库目前处于试验阶段,API 随时都可能修改,所以所有 API 都标有 @ExperimentalPagerApi 注释,第二行注解 Preview,设定了预览图的名字和高度。来看下效果吧: 

4907decb5c91610eb0769d4a9b58bbea.gif

这里由于是直接在 as 中进行的预览互动,所以看着可能有些卡顿,但在真机上没有问题,非常丝滑。

垂直滑动 (上下) 

上面写了水平滑动,这里来看下垂直滑动吧: 

VerticalPager(count = 10) { page ->
    Text(text = "Page: $page")
}

很容易理解吧,水平滑动是 HorizontalPager,垂直滑动就是 VerticalPager,具体详细使用在下面篇幅中介绍,这里先来看看垂直滑动的预览效果吧: 

@OptIn(ExperimentalPagerApi::class)
@Preview(name = "Test3", heightDp = 170, widthDp = 100)
@Composable
fun PagerTest3Preview() {
    PagerTest3()
}

预览代码和刚才差不多,就不做过多解释了,直接来看效果图吧: 

1e095cf80457b1c2016563ffe4369689.gif

不错吧,很简单的代码就实现了之前在 Android View 中比较复杂的效果。

44487e0c238e0b51c13ca1f22f47269f.png

源码解析

下面咱们来简单看看 Pager 的源码吧。

水平滑动源码

先来看看水平滑动的源码: 

1e876c8aa234b8b801370a4f8ca5b1f9.png

由于怕大家看着不舒服,所以这里的代码放成了图片,下面来看下可组合项 HorizontalPager 的参数都有什么作用吧,或者说可组合项 HorizontalPager 都有什么功能。

  • count: 这是可组合项 HorizontalPager 必须要写的参数,顾名思义,就是 Page 的数量;

  • Modifier: 这个在 Compose 中见的太多了,不再赘述,修饰符;

  • state: 用于控制或观察 Pager 状态的状态对象;

  • reverseLayout: 反转滚动和布局的方向,默认为 false,为 true 时第一项将在最后;

  • itemSpacing: 添加项目之间的垂直间距;

  • contentPadding: 内容的 Padding 值;

  • verticalAlignment: 垂直对齐为居中;

  • flingBehavior: 描述滑动行为的逻辑;

  • key: 滚动的位置将根据键保持;

  • userScrollEnabled: 是否允许通过用户手势或辅助功能进行滚动。即使它被禁用,仍然可以使用该状态以编程方式滚动;

  • content: 具体可组合项的内容,在这里,可以引用 PagerScope.currentPage 和 PagerScope 中的其他属性。

垂直滑动源码

接下来再来看下垂直滑动的源码:

d209df9ff567b1cb464a554dc9db5be7.png

发现点什么没有,水平滑动和垂直滑动的源码是不是非常像,而且都是直接调用的 Pager 可组合项。这里有很多参数和水平滑动的一样,就不再赘述,来看看不同的参数吧。

  • horizontalAlignment: 上面水平滑动的是 verticalAlignment 垂直对齐居中,这里是水平对齐居中;

  • flingBehavior: 描述滑动行为的逻辑也有所不同。

剩下就基本一致了。

Pager 内部实现

下面来看下 Pager 内部的实现吧,同样因为这里是源码,所以还放成图片吧: 

e5d3b7858101a32ceb92f27ec9c7e69a.png

可以看出 Pager 可组合项中有一个 isVertical 参数,用来判断是垂直滑动还是水平滑动,如果是垂直滑动的话用的是 LazyColumn,水平滑动则用的是 LazyRow,还记得吗?在 Compose 中 LazyColumn 和 LazyRow 对标的是 Android View 中的 RecyclerView,值得一说的是,现在 Android View 中的 ViewPager2 也使用的是 RecyclerView。

56241ba0e642c4cbe25b0eee7c83dacc.png

进阶用法

上面大概说了下 Pager 的基本用法,但如果在生产环境中一般不会这么简单,这里来举几个生产环境中可能用到的例子吧。

添加指示器

什么是指示器呢?很简单,就是文章开头那张动图中间下方的小圆圈,用来告知用户当前在第几页以及一共有几页。

之前想在 Compose 中添加指示器需要自己来绘制,但现在官方也创建了一个库专门用来实现 Pager 的指示器,来看看吧。

添加依赖

第一步还是在 build.gradle 中添加依赖:

https://search.maven.org/search?q=g:com.google.accompanist

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 中都有。下面先来看下效果图吧:

b01beb05c8ad3f35921e3d6bccbda32c.gif

通过上面代码可以发现指示器也分为水平和垂直的,由于水平的指示器使用较多,所以本文以水平指示器作为讲解对象。

e9d59ae90f8c860b65399b4cab9beb9c.png

上图就是水平指示器的源码。方法中的绘制代码不过多赘述,大家应该都能看懂,下面来说一下参数的含义吧: 

  • pagerState: Pager 的状态;

  • modifier: 修饰符,不过多解释;

  • activeColor: 当前活跃的指示器颜色;

  • inactiveColor: 当前不活跃的指示器颜色;

  • indicatorWidth: 指示器的宽度;

  • indicatorHeight: 指示器的高度;

  • spacing: 指示器之间的宽度;

  • indicatorShape: 指示器的形状,默认为圆形,大家也可以自己进行定义。

指示器还可以与 TabRow 进行结合使用,效果和微信的页面切换效果基本一致,大家感兴趣的可以自己下去试一下。

监听页面更改

在 Android View 中咱们如果想监听 ViewPager 的话只需要通过 registerOnPageChangeCallback 方法即可进行监听,那么在 Compose 中咱们应该如何监听 Pager 的页面更改呢?

每当所选页面发生更改时,都会更新该 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 的样例吧: 

b2bb924796bcbf910d31ce09c1c3433d.gif

看着效果还不错吧,由于里面涉及知识点太多,想学习的可以去官方的源码中进行查看: 

https://github.com/google/accompanist/blob/main/sample/src/main/java/com/google/accompanist/sample/pager/HorizontalPagerTransitionSample.kt


长按右侧二维码

查看更多开发者精彩分享

fa25704a1fb58901c86ee435130091eb.png

"开发者说·DTalk" 面向778905005e0b0c7f08b5d8f877d59961.png中国开发者们征集 Google 移动应用 (apps & games) 相关的产品/技术内容。欢迎大家前来分享您对移动应用的行业洞察或见解、移动开发过程中的心得或新发现、以及应用出海的实战经验总结和相关产品的使用反馈等。我们由衷地希望可以给这些出众的中国开发者们提供更好展现自己、充分发挥自己特长的平台。我们将通过大家的技术内容着重选出优秀案例进行谷歌开发技术专家 (GDE) 的推荐。

814db9cfd633b779fd3774e3acdeca3a.gif 点击屏末 | 阅读原文 | 即刻报名参与 "开发者说·DTalk" 


2fe2c19418fd20488a16c2f001b7ebbb.png

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值