fix(ui): improve pan and scale for zoomable images

This commit is contained in:
Diego Beraldin 2023-09-26 22:16:49 +02:00
parent 31f34b03a3
commit b74a18a93f

View File

@ -1,7 +1,8 @@
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTransformGestures
import androidx.compose.foundation.gestures.rememberTransformableState
import androidx.compose.foundation.gestures.transformable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@ -9,6 +10,7 @@ import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@ -16,11 +18,13 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.toSize
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
import dev.icerock.moko.resources.compose.stringResource
@ -29,21 +33,36 @@ fun ZoomableImage(
modifier: Modifier = Modifier,
url: String,
) {
var size by remember { mutableStateOf(Size.Zero) }
var scale by remember { mutableStateOf(1f) }
var offsetX by remember { mutableStateOf(0f) }
var offsetY by remember { mutableStateOf(0f) }
val transformableState = rememberTransformableState { zoom, pan, _ ->
scale = (scale * zoom).coerceIn(0.5f, 3f)
offsetX = (offsetX + pan.x).coerceIn(-size.width / scale, size.width / scale)
offsetY = (offsetY + pan.y).coerceIn(-size.height / scale, size.height / scale)
}
LaunchedEffect(transformableState.isTransformInProgress) {
if (!transformableState.isTransformInProgress) {
if (scale < 1.1f) {
scale = 1f
offsetX = 0f
offsetY = 0f
}
}
}
Box(
modifier = modifier
.clip(RectangleShape)
.fillMaxSize()
.background(Color.Black)
.pointerInput(Unit) {
detectTransformGestures { _, pan, zoom, _ ->
scale = (scale * zoom).coerceIn(0.5f, 3f)
offsetX += pan.x
offsetY += pan.y
}
.onGloballyPositioned {
size = it.size.toSize()
}
.transformable(transformableState, lockRotationOnZoomPan = true)
) {
CustomImage(
modifier = Modifier