From d8513961133b01901afb00dbe47a36b25b86b1c4 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Wed, 2 Nov 2022 13:26:19 +0300 Subject: [PATCH] android: Better scroll of zoomed images in gallery (#1283) --- .../app/views/chat/item/ImageFullScreenView.kt | 13 +++++++++++-- .../simplex/app/views/helpers/GestureDetector.kt | 5 +++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ImageFullScreenView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ImageFullScreenView.kt index 8c9f812e7a..63b70e740e 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ImageFullScreenView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/item/ImageFullScreenView.kt @@ -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 } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt index bb81d1974e..dcfcf6e7c6 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt @@ -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() } }