diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/ZoomableImage.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/ZoomableImage.kt index 37e723b8..1e1176fc 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/ZoomableImage.kt +++ b/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 }) } } )