Browse Source

Separate each Android gallery swipe from pinch and pan gestures

master
evgeny 4 days ago
parent
commit
cee3228e5f
  1. 28
      tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/ZoomableImage.kt

28
tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/ZoomableImage.kt

@ -2,7 +2,11 @@ package com.utun.chat.ui.components
import android.graphics.Bitmap
import androidx.compose.foundation.Image
import androidx.compose.foundation.gestures.detectTransformGestures
import androidx.compose.foundation.gestures.awaitEachGesture
import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.gestures.calculateCentroid
import androidx.compose.foundation.gestures.calculatePan
import androidx.compose.foundation.gestures.calculateZoom
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.fillMaxSize
@ -12,6 +16,7 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChanged
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalDensity
@ -31,6 +36,7 @@ fun ZoomableImage(bitmap: Bitmap, modifier: Modifier = Modifier, contentScale: C
onSwipe: ((Int) -> Unit)? = null) {
var zoomScale by remember(bitmap) { mutableStateOf(1f) }
var zoomOffset by remember(bitmap) { mutableStateOf(Offset.Zero) }
val navigate by rememberUpdatedState(onSwipe)
BoxWithConstraints(modifier) {
val density = LocalDensity.current
@ -60,13 +66,19 @@ fun ZoomableImage(bitmap: Bitmap, modifier: Modifier = Modifier, contentScale: C
Box(
modifier = Modifier
.fillMaxSize()
.pointerInput(bitmap,cW,cH,onSwipe) {
var swipe=0f
detectTransformGestures { centroid, pan, zoom, _ ->
if (onSwipe!=null && zoomScale==1f && zoom==1f && kotlin.math.abs(pan.x)>kotlin.math.abs(pan.y)) {
.pointerInput(bitmap,cW,cH) {
awaitEachGesture {
awaitFirstDown(requireUnconsumed=false)
var swipe=0f; var swiped=false; var canSwipe=zoomScale==1f
do {
val event=awaitPointerEvent()
val centroid=event.calculateCentroid(useCurrent=false)
val pan=event.calculatePan(); val zoom=event.calculateZoom()
if (event.changes.count { it.pressed }!=1 || zoom!=1f) canSwipe=false
if (canSwipe && !swiped && navigate!=null && kotlin.math.abs(pan.x)>kotlin.math.abs(pan.y)) {
swipe+=pan.x
if (kotlin.math.abs(swipe)>96*density.density) { onSwipe(if (swipe<0) 1 else -1); swipe=0f }
} else swipe=0f
if (kotlin.math.abs(swipe)>96*density.density) { navigate?.invoke(if (swipe<0) 1 else -1); swiped=true }
}
val old = zoomScale
val new = (zoomScale * zoom).coerceIn(1f, MAX_ZOOM)
val z = new / old
@ -77,6 +89,8 @@ fun ZoomableImage(bitmap: Bitmap, modifier: Modifier = Modifier, contentScale: C
)
zoomScale = new
zoomOffset = clampOffset(new, raw, cW, cH, iw, ih)
if (zoom!=1f || pan!=Offset.Zero) event.changes.forEach { if (it.positionChanged()) it.consume() }
} while (event.changes.any { it.pressed })
}
}
)

Loading…
Cancel
Save