前言
在此之前如果我们想要在Compose中实现轮播图的效果,一般需要借助HorizontalPager来实现,需要自己额外处理定时刷新的逻辑。在m3中官方为我们提供了标准的轮播图Carousel组件,现在Carousel也支持Compose了,借助Carousel可以轻松在Compose中实现轮播图的效果。
Carousel分类
在原生View系统中,Carousel为我们提供了四种布局,分别为:
- Multi-browse
- Uncontained
- Hero
- Full-screen
提供了两种滚动方式:
- Default: 默认值: 标准滚动。
- Snap-scrolling: 对齐滚动: 滚动条对齐Carousel的布局。推荐用于多浏览
而在Compose中提供了HorizontalMultiBrowseCarousel、HorizontalUncontainedCarousel 两个方法。 今天我们只来了解如何在Compose中使用Carousel组件。
使用方法
准备工作
新建Compose项目,将m3升级到最新版本,因为部分API仍处于实验性阶段。
implementation("androidx.compose.material3:material3:1.3.0-beta05")
准备好要展示的图片,代码如下所示:
data class CarouselItem(
val id: Int,
@DrawableRes val imageResId: Int,
@StringRes val contentDescriptionResId: Int
)
val items =
listOf(
CarouselItem(0, R.drawable.carousel_image_1, R.string.carousel_image_1_description),
CarouselItem(1, R.drawable.carousel_image_2, R.string.carousel_image_2_description),
CarouselItem(2, R.drawable.carousel_image_3, R.string.carousel_image_3_description),
CarouselItem(3, R.drawable.carousel_image_4, R.string.carousel_image_4_description)
)
HorizontalMultiBrowseCarousel
HorizontalMultiBrowseCarousel的参数如下所示。
@ExperimentalMaterial3Api
@Composable
fun HorizontalMultiBrowseCarousel(
state: CarouselState,
preferredItemWidth: Dp,
modifier: Modifier = Modifier,
itemSpacing: Dp = 0.dp,
flingBehavior: TargetedFlingBehavior = CarouselDefaults.singleAdvanceFlingBehavior(state = state),
minSmallItemWidth: Dp = CarouselDefaults.MinSmallItemSize,
maxSmallItemWidth: Dp = CarouselDefaults.MaxSmallItemSize,
contentPadding: PaddingValues = PaddingValues(0.dp),
content: @Composable CarouselItemScope.(itemIndex: Int) -> Unit
): Unit
主要参数含义如下:
参数名 | 含义 |
---|---|
CarouselState | 用来控制Carousel的状态 |
preferredItemWidth | 水平轴上的宽度,这个宽度是一个目标,可能会通过Carousel来调整,以适应容器中的整个项目数量 |
itemSpacing | Item之间的分隔间距 |
content | Carousel中的内容 |
接下来我们实现HorizontalMultiBroseCarousel方法,代码如下所示:
@ExperimentalMaterial3Api
@Composable
fun Carouse(){
HorizontalMultiBrowseCarousel(
state = rememberCarouselState { items.count() } ,
modifier = Modifier.width(412.dp).height(221.dp),
preferredItemWidth = 186.dp,
itemSpacing = 8.dp,
contentPadding = PaddingValues(horizontal = 16.dp)
) { i ->
val item = items[i]
Image(
modifier = Modifier.height(205.dp).maskClip(MaterialTheme.shapes.extraLarge),
painter = painterResource(id = item.imageResId),
contentDescription = stringResource(item.contentDescriptionResId),
contentScale = ContentScale.Crop
)
}
}
运行程序,结果如下图所示。
这里需要注意,如果我们将preferredItemWidth改为0dp,即使给Image设置宽度自适应 也是无法生效的。
HorizontalUncontainedCarousel
HorizontalUncontainedCarousel的参数如下所示。
@ExperimentalMaterial3Api
@Composable
fun HorizontalUncontainedCarousel(
state: CarouselState,
itemWidth: Dp,
modifier: Modifier = Modifier,
itemSpacing: Dp = 0.dp,
flingBehavior: TargetedFlingBehavior = CarouselDefaults.noSnapFlingBehavior(),
contentPadding: PaddingValues = PaddingValues(0.dp),
content: @Composable CarouselItemScope.(itemIndex: Int) -> Unit
)
与HorizontalMultiBrowseCarousel不同的是preferredItemWidth变成了itemWidth参数。
实现代码,如下所示:
HorizontalUncontainedCarousel(
state = rememberCarouselState { items.count() } ,
modifier = Modifier.width(412.dp).height(221.dp),
itemWidth = 186.dp,
itemSpacing = 8.dp,
contentPadding = PaddingValues(horizontal = 16.dp)
) { i ->
val item = items[i]
Image(
modifier = Modifier.height(205.dp).maskClip(MaterialTheme.shapes.extraLarge),
painter = painterResource(id = item.imageResId),
contentDescription = stringResource(item.contentDescriptionResId),
contentScale = ContentScale.Crop
)
}
运行程序,结果如下图所示。
乍一看效果好像与HorizontalUncontainedCarousel没有什么区别,但是仔细一看,好像也没什么区别。
这里的itemWidth相当于指定了滚动项的固定宽度,但实际不会超过屏幕宽度。而preferredItemWidth是期望的宽度,Carouse会根据实际情况进行动态调整。
rememberCarouselState
在上述两个方法中都有一个rememberCarouselState,它的使用方法也很简单,除了itemCount参数之外还有一个initialItem参数,用于指定初始卡片的位置。用法如下所示。
state = rememberCarouselState(initialItem = 3) { items.count() }
最后
2024年了,还有人不会Compose吗?