Basti X
Basti X

Reputation: 81

KMP MapKit Gesture detection

I am using Kotlin Multiplatform with MapKit-Compose and would like to keep track of user gestures on the map like zooming/pinching, panning, etc.

So I thought I could create the MapView and add the GestureRecognizers.

val mkMapView =
    remember {
        MKMapView().apply {
            // Init.....
            setZoomEnabled(true)
            setScrollEnabled(true)
            userInteractionEnabled = true

            setDelegate(delegate)
            delegate.addGestureRecognizer(mkMapView = this)
        }
    }
@OptIn(BetaInteropApi::class)
@ObjCAction
fun handleUserInteraction() {
    Logger.d("userZoomScrollOverride triggered")
}

@OptIn(BetaInteropApi::class)
@ObjCAction
fun handleMapPan(recognizer: UIPanGestureRecognizer) {
    Logger.d("userZoomScrollOverride handleMapPan")
}

fun addGestureRecognizer(mkMapView: MKMapView) {
    val panGesture = UIPanGestureRecognizer(target = this, action = NSSelectorFromString("handleMapPan:"))
    val pinchGesture = UIPinchGestureRecognizer(target = this, action = NSSelectorFromString("handleUserInteraction:"))
    val selector = UIGestureRecognizer(target = this, action = NSSelectorFromString("handleUserInteraction:"))
    mkMapView.addGestureRecognizer(selector)
    mkMapView.addGestureRecognizer(panGesture)
    mkMapView.addGestureRecognizer(pinchGesture)
}

Of course the handleUserInteraction/handleMapPan functions are never called. I never before tried working with NSSelectorFromString or anything like that, but it was the only thing I found on the Web.

Anybody that can point me into the right direction?

Upvotes: 0

Views: 48

Answers (1)

Basti X
Basti X

Reputation: 81

As Phil Dukhov pointed out, shouldRecognizeSimultaneouslyWithGestureRecognizer is required for the map to register these events.

Define the delegate:

class GestureDelegate :
    NSObject(),
    UIGestureRecognizerDelegateProtocol {
    override fun gestureRecognizer(
        gestureRecognizer: UIGestureRecognizer,
        shouldRecognizeSimultaneouslyWithGestureRecognizer: UIGestureRecognizer,
    ): Boolean {
        return true 
    }
}

Set the delegate and add the gestureRecognizer to the map:

    fun addGestureRecognizer(mkMapView: MKMapView) {
        val gestureDelegate = GestureDelegate()

        val panGesture = UIPanGestureRecognizer(target = this, action = NSSelectorFromString("handleMapPan:"))
        panGesture.delegate = gestureDelegate

        mkMapView.addGestureRecognizer(panGesture)
    }

Handle the events:

    @OptIn(BetaInteropApi::class)
    @ObjCAction
    private fun handleMapPan(recognizer: UIPanGestureRecognizer) {
        Logger.d("Handling pan event.")
    }

Thank you for the help!

Upvotes: 0

Related Questions