所以,我需要一个应该可以自由滚动(即水平和垂直滚动)并且应该可以缩放(特别是缩小)的布局。
我已经为此实现了类似的东西:
var offset by remember { mutableStateOf(Offset.Zero) }
var zoom by remember { mutableFloatStateOf(1f) }
Column(
modifier = Modifier
.verticalScroll(rememberScrollState(), enabled = false)
.horizontalScroll(rememberScrollState(), enabled = false)
.pointerInput(Unit) {
detectTransformGestures(
onGesture = { centroid, pan, gestureZoom, gestureRotate ->
val oldScale = zoom
val newScale = zoom * gestureZoom
offset = (offset + centroid / oldScale) -
(centroid / newScale + pan / oldScale)
zoom = newScale
}
)
}
.graphicsLayer {
translationX = -offset.x * zoom
translationY = -offset.y * zoom
scaleX = zoom
scaleY = zoom
transformOrigin = TransformOrigin(0f, 0f)
},
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
repeat(40) { column ->
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
repeat(40) { row ->
Box(modifier = Modifier) {
Text(
modifier = Modifier
.align(Alignment.Center),
text = "($row, $column)",
textAlign = TextAlign.Center
)
}
}
}
}
}
但是,问题是拖动时内容远远超出了屏幕范围? 如何确保在缩小和拖动时内容保持在边界内?
通过
查找 maxX 和 maxYmaxX = (contentSize.width * scale - constraints.maxWidth)
.coerceAtLeast(0F)
maxY = (contentSize.height * scale - constraints.maxHeight)
.coerceAtLeast(0F)
offset = Offset(newOffset.x.coerceIn(-maxX, maxX),
newOffset.y.coerceIn(-maxY, maxY))
这里的约束是从 BoxWithConstraints 接收到的屏幕尺寸。