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

Jetpack Compose中HorizontalPager内图片缩放超出边界异常问题

Compose中HorizontalPager包裹图片时双指缩放异常问题

我尝试使用PointerEvent实现图片双指缩放功能,当图片包裹在Column组件中时,可正常超出Column边界(占屏幕高度0.4)进行缩放;但将其包裹在HorizontalPager中时,缩放表现不符合预期。

Column实现代码及效果

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ProductImageDialog(
    properties: DialogProperties = DialogProperties(usePlatformDefaultWidth = false),
    onDismissRequest: () -> Unit
) {
    var scale by remember { mutableFloatStateOf(1f) }
    var offset by remember { mutableStateOf(Offset.Zero) }
    val coroutineScope = rememberCoroutineScope()

    var userScrollEnabled by remember { mutableStateOf(true) }

    val pagerState = rememberPagerState { 2 }

    Dialog(
        properties = properties,
        onDismissRequest = onDismissRequest
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.Green),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.End
        ) {
            IconButton(onClick = onDismissRequest) {
                Icon(
                    imageVector = Icons.Default.Close,
                    tint = Color.White,
                    contentDescription = null
                )
            }

            Spacer(modifier = Modifier.height(8.dp))

            Column(
                modifier = Modifier
                    .background(color = Color.White)
                    .fillMaxWidth()
                    .fillMaxHeight(0.4f),
            ) {

//                items(2) { page ->
                    Image(
                        painter = painterResource(id = R.drawable.image_1),
                        contentDescription = null,
                        modifier = Modifier
                            .fillMaxSize()
                            .pointerInput(Unit) {
                                coroutineScope
                                    .launch {
                                        awaitPointerEventScope {
                                            while (true) {
                                                val event = awaitPointerEvent()
                                                when (event.changes.size) {
                                                    2 -> {
                                                        userScrollEnabled = false
                                                        val change1 = event.changes[0]
                                                        val change2 = event.changes[1]

                                                        val distanceCurrent = calculateDistance(
                                                            change1.position,
                                                            change2.position
                                                        )
                                                        val distancePrevious = calculateDistance(
                                                            change1.previousPosition,
                                                            change2.previousPosition
                                                        )
                                                        scale *= distanceCurrent / distancePrevious
                                                        offset += change1.positionChange()
                                                        Log.i(
                                                            "TAGTTTTTT",
                                                            "distanceCurrent: $distanceCurrent\ndistancePrevious: $distancePrevious\nscale: $scale\noffset: $offset"
                                                        )
                                                    }

                                                    else -> {
                                                        userScrollEnabled = true
                                                        scale = 1f
                                                        offset = Offset.Zero
                                                    }
                                                }
                                            }
                                        }
                                    }
                            }
                            .graphicsLayer(
                                scaleX = scale,
                                scaleY = scale,
                                translationX = offset.x,
                                translationY = offset.y
                            ),
                        contentScale = ContentScale.Inside
                    )
//                }

            }
        }
    }
}

private fun calculateDistance(point1: Offset, point2: Offset): Float {
    val dx = point1.x - point2.x
    val dy = point1.y - point2.y
    return sqrt(dx * dx + dy * dy)
}

Column实现缩放效果

HorizontalPager实现代码及效果

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ProductImageDialog(
    properties: DialogProperties = DialogProperties(usePlatformDefaultWidth = false),
    onDismissRequest: () -> Unit
) {
    var scale by remember { mutableFloatStateOf(1f) }
    var offset by remember { mutableStateOf(Offset.Zero) }
    val coroutineScope = rememberCoroutineScope()

    var userScrollEnabled by remember { mutableStateOf(true) }

    val pagerState = rememberPagerState { 2 }

    Dialog(
        properties = properties,
        onDismissRequest = onDismissRequest
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .background(Color.Green),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.End
        ) {
            IconButton(onClick = onDismissRequest) {
                Icon(
                    imageVector = Icons.Default.Close,
                    tint = Color.White,
                    contentDescription = null
                )
            }

            Spacer(modifier = Modifier.height(8.dp))

            HorizontalPager(
                modifier = Modifier
                    .background(color = Color.White)
                    .fillMaxWidth()
                    .fillMaxHeight(0.4f),
                state = pagerState,
                userScrollEnabled = userScrollEnabled,
            ) { page ->

                Image(
                    painter = if (page == 0) painterResource(id = R.drawable.image_1) else painterResource(id = R.drawable.image_2),
                    contentDescription = null,
                    modifier = Modifier
                        .fillMaxSize()
                        .pointerInput(Unit) {
                            coroutineScope
                                .launch {
                                    awaitPointerEventScope {
                                        while (true) {
                                            val event = awaitPointerEvent()
                                            when (event.changes.size) {
                                                2 -> {
                                                    userScrollEnabled = false
                                                    val change1 = event.changes[0]
                                                    val change2 = event.changes[1]

                                                    val distanceCurrent = calculateDistance(
                                                        change1.position,
                                                        change2.position
                                                    )
                                                    val distancePrevious = calculateDistance(
                                                        change1.previousPosition,
                                                        change2.previousPosition
                                                    )
                                                    scale *= distanceCurrent / distancePrevious
                                                    offset += change1.positionChange()
                                                    Log.i(
                                                        "TAGTTTTTT",
                                                        "distanceCurrent: $distanceCurrent\ndistancePrevious: $distancePrevious\nscale: $scale\noffset: $offset"
                                                    )
                                                }

                                                else -> {
                                                    userScrollEnabled = true
                                                    scale = 1f
                                                    offset = Offset.Zero
                                                }
                                            }
                                        }
                                    }
                                }
                        }
                        .graphicsLayer(
                            scaleX = scale,
                            scaleY = scale,
                            translationX = offset.x,
                            translationY = offset.y
                        ),
                    contentScale = ContentScale.Inside
                )
            }
        }
    }
}

HorizontalPager实现缩放效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 17:02:17