ZoomableBox small changes

This commit is contained in:
ganfra 2023-05-05 19:49:04 +02:00
parent 266d48b48b
commit fe246e0a7b

View file

@ -28,6 +28,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.RectangleShape
@ -39,27 +40,31 @@ import androidx.compose.ui.unit.IntSize
@Composable @Composable
fun ZoomableBox( fun ZoomableBox(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
minScale: Float = 1f, contentAlignment: Alignment = Alignment.TopStart,
maxScale: Float = 5f, minZoom: Float = 1f,
maxZoom: Float = 5f,
content: @Composable ZoomableBoxScope.() -> Unit content: @Composable ZoomableBoxScope.() -> Unit
) { ) {
var scale by remember { mutableStateOf(1f) } var zoom by remember { mutableStateOf(minZoom) }
var offsetX by remember { mutableStateOf(0f) } var offsetX by remember { mutableStateOf(0f) }
var offsetY by remember { mutableStateOf(0f) } var offsetY by remember { mutableStateOf(0f) }
var size by remember { mutableStateOf(IntSize.Zero) } var size by remember { mutableStateOf(IntSize.Zero) }
Box( Box(
modifier = modifier modifier = modifier
.clip(RectangleShape) .clip(RectangleShape)
.onSizeChanged { size = it } .onSizeChanged {
size = it
}
.pointerInput(Unit) { .pointerInput(Unit) {
detectTransformGestures { _, pan, zoom, _ -> detectTransformGestures { _, panChange, zoomChange, _ ->
scale = maxOf(minScale, minOf(scale * zoom, maxScale)) zoom = (zoom * zoomChange).coerceIn(minZoom, maxZoom)
val maxX = (size.width * (scale - 1)) / 2 val maxX = (size.width * (zoom - 1)) / 2f
val minX = -maxX val minX = -maxX
offsetX = maxOf(minX, minOf(maxX, offsetX + pan.x)) val maxY = (size.height * (zoom - 1)) / 2f
val maxY = (size.height * (scale - 1)) / 2
val minY = -maxY val minY = -maxY
offsetY = maxOf(minY, minOf(maxY, offsetY + pan.y)) offsetX = maxOf(minX, minOf(maxX, offsetX + panChange.x))
offsetY = maxOf(minY, minOf(maxY, offsetY + panChange.y))
} }
} }
.pointerInput(Unit) { .pointerInput(Unit) {
@ -67,17 +72,18 @@ fun ZoomableBox(
onDoubleTap = { onDoubleTap = {
offsetX = 0f offsetX = 0f
offsetY = 0f offsetY = 0f
scale = if (scale > minScale) { zoom = if (zoom > minZoom) {
minScale minZoom
} else { } else {
maxScale / 2f maxZoom / 2f
} }
} }
) )
} },
contentAlignment = contentAlignment,
) { ) {
DefaultZoomableBoxScope(this, scale, offsetX, offsetY).content() DefaultZoomableBoxScope(this, zoom, offsetX, offsetY).content()
} }
} }
@ -95,12 +101,12 @@ private class DefaultZoomableBoxScope(
private val offsetY: Float private val offsetY: Float
) : ZoomableBoxScope, BoxScope by parentScope { ) : ZoomableBoxScope, BoxScope by parentScope {
override fun Modifier.zoomable(): Modifier { override fun Modifier.zoomable() = this.then(
return graphicsLayer( graphicsLayer(
scaleX = scale, scaleX = scale,
scaleY = scale, scaleY = scale,
translationX = offsetX, translationX = offsetX,
translationY = offsetY translationY = offsetY,
) )
} )
} }