android: Better scroll of zoomed images in gallery (#1283)

This commit is contained in:
Stanislav Dmitrenko
2022-11-02 10:26:19 +00:00
committed by GitHub
parent cbdd9b9e37
commit d851396113
2 changed files with 14 additions and 4 deletions
@@ -13,6 +13,7 @@ import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.input.pointer.*
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import chat.simplex.app.R
@@ -25,6 +26,7 @@ import coil.request.ImageRequest
import coil.size.Size
import com.google.accompanist.pager.*
import kotlinx.coroutines.launch
import kotlin.math.absoluteValue
interface ImageGalleryProvider {
val initialIndex: Int
@@ -88,6 +90,8 @@ fun ImageFullScreenView(imageProvider: () -> ImageGalleryProvider, close: () ->
var scale by remember { mutableStateOf(1f) }
var translationX by remember { mutableStateOf(0f) }
var translationY by remember { mutableStateOf(0f) }
var viewWidth by remember { mutableStateOf(0) }
var allowTranslate by remember { mutableStateOf(true) }
LaunchedEffect(settledCurrentPage) {
scale = 1f
translationX = 0f
@@ -113,6 +117,9 @@ fun ImageFullScreenView(imageProvider: () -> ImageGalleryProvider, close: () ->
contentDescription = stringResource(R.string.image_descr),
contentScale = ContentScale.Fit,
modifier = Modifier
.onGloballyPositioned {
viewWidth = it.size.width
}
.graphicsLayer(
scaleX = scale,
scaleY = scale,
@@ -121,12 +128,14 @@ fun ImageFullScreenView(imageProvider: () -> ImageGalleryProvider, close: () ->
)
.pointerInput(Unit) {
detectTransformGestures(
{ allowTranslate },
onGesture = { _, pan, gestureZoom, _ ->
scale = (scale * gestureZoom).coerceIn(1f, 20f)
if (scale > 1) {
allowTranslate = viewWidth * (scale - 1f) - ((translationX + pan.x * scale).absoluteValue * 2) > 0
if (scale > 1 && allowTranslate) {
translationX += pan.x * scale
translationY += pan.y * scale
} else {
} else if (allowTranslate) {
translationX = 0f
translationY = 0f
}
@@ -214,13 +214,14 @@ fun interactionSourceWithDetection(onClick: () -> Unit, onLongClick: () -> Unit)
}
suspend fun PointerInputScope.detectTransformGestures(
allowIntercept: () -> Boolean,
panZoomLock: Boolean = false,
onGesture: (centroid: Offset, pan: Offset, zoom: Float, rotation: Float) -> Unit
) {
var zoom = 1f
forEachGesture {
awaitPointerEventScope {
var rotation = 0f
var zoom = 1f
var pan = Offset.Zero
var pastTouchSlop = false
val touchSlop = viewConfiguration.touchSlop
@@ -264,7 +265,7 @@ suspend fun PointerInputScope.detectTransformGestures(
onGesture(centroid, panChange, zoomChange, effectiveRotation)
}
event.changes.fastForEach {
if (it.positionChanged() && zoomChange != 1f) {
if (it.positionChanged() && zoom != 1f && allowIntercept()) {
it.consume()
}
}