You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jetpack Compose Horizontal Pager中实现图片缩放效果

Jetpack Compose HorizontalPager 实现中间原图、两侧缩放的无限滚动效果

要实现中间图片保持原尺寸、滑动时两侧图片缩放的效果,核心是根据页面偏移量动态计算缩放比例,并通过动画让过渡更平滑。修改你的代码如下:

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun CustomSlider(
    modifier: Modifier = Modifier,
    sliderList: MutableList<String>,
    pagerPaddingValues: PaddingValues = PaddingValues(horizontal = 65.dp),
    imageCornerRadius: Dp = 16.dp,
    imageHeight: Dp = 240.dp,
    minScale: Float = 0.8f // 两侧图片最小缩放比例
) {
    val pageCount = Int.MAX_VALUE
    val pagerState = rememberPagerState(initialPage = pageCount / 2)

    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Row(
            modifier = modifier.fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.Center,
        ) {
            HorizontalPager(
                pageCount = pageCount,
                state = pagerState,
                contentPadding = pagerPaddingValues,
                modifier = modifier.weight(1f)
            ) { page ->
                // 计算当前页与目标页的偏移量,处理无限滚动的索引偏移
                val adjustedPage = page % sliderList.size
                val currentAdjustedPage = pagerState.currentPage % sliderList.size
                val pageOffset = when {
                    // 处理滚动到边界时的无限偏移计算
                    currentAdjustedPage == sliderList.size - 1 && adjustedPage == 0 -> {
                        pagerState.currentPageOffsetFraction - 1f
                    }
                    adjustedPage == sliderList.size - 1 && currentAdjustedPage == 0 -> {
                        pagerState.currentPageOffsetFraction + 1f
                    }
                    else -> {
                        (pagerState.currentPage - page) + pagerState.currentPageOffsetFraction
                    }
                }

                // 计算缩放值:偏移量绝对值越大,缩放比例越小,最小到minScale
                val scale = animateFloatAsState(
                    targetValue = 1f - (kotlin.math.abs(pageOffset) * (1f - minScale)),
                    animationSpec = tween(durationMillis = 200)
                ).value

                Box(
                    modifier = modifier
                        .padding(10.dp)
                        .clip(RoundedCornerShape(imageCornerRadius))
                ) {
                    AsyncImage(
                        model = ImageRequest.Builder(LocalContext.current)
                            .scale(Scale.FILL)
                            .crossfade(true)
                            .data(sliderList[adjustedPage])
                            .build(),
                        contentDescription = "轮播图片",
                        contentScale = ContentScale.Crop,
                        placeholder = painterResource(id = R.drawable.img),
                        modifier = modifier
                            .height(imageHeight)
                            .width(295.dp)
                            .scale(scale) // 应用缩放效果
                    )
                }
            }
        }
    }
}

关键修改说明:

  • 缩放比例计算:通过pageOffset的绝对值计算缩放值,当前选中页面的偏移量为0,缩放比例保持1f;两侧页面随偏移量增大,缩放比例线性减小到设置的minScale(默认0.8f)。
  • 平滑动画:使用animateFloatAsState让缩放过渡更自然,避免生硬的尺寸变化。
  • 无限滚动偏移修正:处理无限滚动时,当滚动到列表首尾衔接的位置,修正pageOffset的计算逻辑,避免缩放出现异常。

效果预览:
Slider Image

内容的提问来源于stack exchange,提问作者pepperlove

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 08:23:16