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

Jetpack Compose实现Facebook式图片预览滑动关闭效果咨询

Jetpack Compose实现任意方向滑动关闭图片预览

实现思路

  • 以全屏Composable作为图片预览容器,通过pointerInput监听全局拖动手势,替代仅支持定向的滑动组件(如SwipeToDismiss)
  • 结合Animatable实时同步拖动状态:拖动时让图片跟随手指偏移,同时逐步缩小尺寸、降低透明度,背景层同步从半透明过渡到完全透明
  • 设置关闭触发阈值:当拖动的总偏移距离超过屏幕短边的1/3,或拖动速度达到设定值时,执行预览界面退出逻辑;若未达阈值,松手后通过动画将图片回弹至初始状态
  • 不限制拖动方向:仅计算拖动偏移向量的长度,无需判断上下左右方向,实现任意方向滑动触发关闭的效果

核心代码片段示例

@Composable
fun SwipeDismissImagePreview(imageUrl: String) {
    val offsetX = remember { Animatable(0f) }
    val offsetY = remember { Animatable(0f) }
    val scale = remember { Animatable(1f) }
    val alpha = remember { Animatable(1f) }
    val backgroundAlpha = remember { Animatable(0.8f) }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Black.copy(alpha = backgroundAlpha.value))
            .pointerInput(Unit) {
                detectDragGestures(
                    onDrag = { change, dragAmount ->
                        change.consume()
                        offsetX.snapTo(offsetX.value + dragAmount.x)
                        offsetY.snapTo(offsetY.value + dragAmount.y)
                        // 根据偏移量计算缩放和透明度参数
                        val maxOffset = minOf(size.width, size.height) * 0.3f
                        val offsetRatio = minOf(
                            sqrt(offsetX.value.pow(2) + offsetY.value.pow(2)) / maxOffset,
                            1f
                        )
                        scale.snapTo(1f - offsetRatio * 0.2f)
                        alpha.snapTo(1f - offsetRatio)
                        backgroundAlpha.snapTo(0.8f - offsetRatio * 0.8f)
                    },
                    onDragEnd = {
                        val totalOffset = sqrt(offsetX.value.pow(2) + offsetY.value.pow(2))
                        val maxOffset = minOf(size.width, size.height) * 0.3f
                        if (totalOffset > maxOffset) {
                            // 此处执行关闭逻辑,如导航回上一页
                        } else {
                            // 回弹至初始状态的动画
                            coroutineScope.launch {
                                launch { offsetX.animateTo(0f) }
                                launch { offsetY.animateTo(0f) }
                                launch { scale.animateTo(1f) }
                                launch { alpha.animateTo(1f) }
                                launch { backgroundAlpha.animateTo(0.8f) }
                            }
                        }
                    }
                )
            }
    ) {
        Image(
            painter = rememberAsyncImagePainter(imageUrl),
            contentDescription = "Preview Image",
            modifier = Modifier
                .align(Alignment.Center)
                .offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) }
                .scale(scale.value)
                .alpha(alpha.value)
                .fillMaxWidth(0.9f)
                .fillMaxHeight(0.9f)
                .clip(RoundedCornerShape(16.dp))
        )
    }
}

研究关键词

  • Jetpack Compose 任意方向滑动关闭
  • Compose 拖动手势处理
  • Compose Animatable 动画同步
  • Facebook 图片预览滑动关闭
  • Compose 全屏预览手势交互

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 07:02:37