diff --git a/demo/src/main/java/ovh/plrapps/mapcompose/demo/viewmodels/SimpleDemoVM.kt b/demo/src/main/java/ovh/plrapps/mapcompose/demo/viewmodels/SimpleDemoVM.kt index 14035163..d230e76e 100644 --- a/demo/src/main/java/ovh/plrapps/mapcompose/demo/viewmodels/SimpleDemoVM.kt +++ b/demo/src/main/java/ovh/plrapps/mapcompose/demo/viewmodels/SimpleDemoVM.kt @@ -2,8 +2,15 @@ package ovh.plrapps.mapcompose.demo.viewmodels import android.app.Application import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.launch import ovh.plrapps.mapcompose.api.addLayer import ovh.plrapps.mapcompose.api.enableRotation +import ovh.plrapps.mapcompose.api.maxScale +import ovh.plrapps.mapcompose.api.minScale +import ovh.plrapps.mapcompose.api.onDoubleTap +import ovh.plrapps.mapcompose.api.scale +import ovh.plrapps.mapcompose.api.scrollTo import ovh.plrapps.mapcompose.api.shouldLoopScale import ovh.plrapps.mapcompose.demo.providers.makeTileStreamProvider import ovh.plrapps.mapcompose.ui.state.MapState @@ -17,5 +24,17 @@ class SimpleDemoVM(application: Application) : AndroidViewModel(application) { addLayer(tileStreamProvider) shouldLoopScale = true enableRotation() + /** + * Example [onDoubleTap] callback that implements a different zoom behavior + */ + onDoubleTap { x, y -> + viewModelScope.launch { + if(scale < maxScale) { + scrollTo(x, y, maxScale) + } else { + scrollTo(x, y, minScale) + } + } + } } -} \ No newline at end of file +} diff --git a/mapcompose/src/main/java/ovh/plrapps/mapcompose/api/GesturesApi.kt b/mapcompose/src/main/java/ovh/plrapps/mapcompose/api/GesturesApi.kt index 8c08f4ca..fddc921a 100644 --- a/mapcompose/src/main/java/ovh/plrapps/mapcompose/api/GesturesApi.kt +++ b/mapcompose/src/main/java/ovh/plrapps/mapcompose/api/GesturesApi.kt @@ -85,6 +85,16 @@ fun MapState.onTap(tapCb: (x: Double, y: Double) -> Unit) { this.tapCb = tapCb } +/** + * Registers a callback for double-tap gestures. The callback is invoked with the relative + * coordinates of the double-tapped point on the map. + * + * When a callback is registered, it overrides the default double-tap zoom behavior. + */ +fun MapState.onDoubleTap(doubleTapCb: (x: Double, y: Double) -> Unit) { + this.doubleTapCb = doubleTapCb +} + /** * Registers a callback for long press gestures. The callback is invoked with the relative coordinates * of the pressed point on the map. @@ -98,4 +108,4 @@ fun MapState.onLongPress(longPressCb: (x: Double, y: Double) -> Unit) { */ fun MapState.onTouchDown(cb: () -> Unit) { touchDownCb = cb -} \ No newline at end of file +} diff --git a/mapcompose/src/main/java/ovh/plrapps/mapcompose/ui/state/MapState.kt b/mapcompose/src/main/java/ovh/plrapps/mapcompose/ui/state/MapState.kt index c9096709..26e2b0b6 100644 --- a/mapcompose/src/main/java/ovh/plrapps/mapcompose/ui/state/MapState.kt +++ b/mapcompose/src/main/java/ovh/plrapps/mapcompose/ui/state/MapState.kt @@ -88,6 +88,7 @@ class MapState( internal var stateChangeListener: (MapState.() -> Unit)? = null internal var touchDownCb: (() -> Unit)? = null internal var tapCb: LayoutTapCb? = null + internal var doubleTapCb: LayoutTapCb? = null internal var longPressCb: LayoutTapCb? = null internal var mapBackground by mutableStateOf(Color.Transparent) internal var isFilteringBitmap: () -> Boolean by mutableStateOf( @@ -133,6 +134,13 @@ class MapState( tapCb?.invoke(x, y) } + override fun onDoubleTap(x: Double, y: Double): Boolean { + return doubleTapCb?.let { + it(x, y) + true + } ?: false + } + override fun detectsTap(): Boolean = tapCb != null override fun detectsLongPress(): Boolean = longPressCb != null @@ -332,4 +340,4 @@ class InitialValues internal constructor() { } } -internal typealias LayoutTapCb = (x: Double, y: Double) -> Unit \ No newline at end of file +internal typealias LayoutTapCb = (x: Double, y: Double) -> Unit diff --git a/mapcompose/src/main/java/ovh/plrapps/mapcompose/ui/state/ZoomPanRotateState.kt b/mapcompose/src/main/java/ovh/plrapps/mapcompose/ui/state/ZoomPanRotateState.kt index e323cd6b..62cd0afc 100644 --- a/mapcompose/src/main/java/ovh/plrapps/mapcompose/ui/state/ZoomPanRotateState.kt +++ b/mapcompose/src/main/java/ovh/plrapps/mapcompose/ui/state/ZoomPanRotateState.kt @@ -483,6 +483,11 @@ internal class ZoomPanRotateState( } override fun onDoubleTap(focalPt: Offset) { + val isHandled = offsetToRelative(focalPt) { x, y -> + stateChangeListener.onDoubleTap(x, y) + } + if (isHandled) return + if (!isZoomingEnabled) return val destScale = ( @@ -717,8 +722,9 @@ interface ZoomPanRotateStateListener { fun onPress() fun onLongPress(x: Double, y: Double) fun onTap(x: Double, y: Double) + fun onDoubleTap(x: Double, y: Double): Boolean fun detectsTap(): Boolean fun detectsLongPress(): Boolean fun interceptsTap(x: Double, y: Double, xPx: Int, yPx: Int): Boolean fun interceptsLongPress(x: Double, y: Double, xPx: Int, yPx: Int): Boolean -} \ No newline at end of file +}