Skip to content

Commit d604ca5

Browse files
authored
Workaround for duplicate move motion events on Android (#1041) (#1043)
1 parent 9dca0f0 commit d604ca5

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
### 2.12.0-rc.1
2+
3+
* Fix multi-touch gestures not working in map widget when being nested in `GestureDetector`.
4+
15
### 2.12.0-beta.1
26

37
* Use Maps SDK Android dependency with NDK 27 support and [support for 16 KB page sizes](https://developer.android.com/guide/practices/page-sizes).

android/src/main/kotlin/com/mapbox/maps/mapbox_maps/MapboxMapController.kt

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package com.mapbox.maps.mapbox_maps
22

3+
import android.annotation.SuppressLint
34
import android.content.Context
45
import android.graphics.Bitmap
6+
import android.util.AttributeSet
7+
import android.util.Log
8+
import android.view.MotionEvent
59
import android.view.View
610
import androidx.lifecycle.DefaultLifecycleObserver
711
import androidx.lifecycle.Lifecycle
@@ -38,6 +42,52 @@ import io.flutter.plugin.common.MethodChannel
3842
import io.flutter.plugin.platform.PlatformView
3943
import java.io.ByteArrayOutputStream
4044

45+
class FlutterMapView : MapView {
46+
constructor(context: Context, mapInitOptions: MapInitOptions) : super(context, mapInitOptions)
47+
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
48+
49+
// Track expected pointer count to detect wrong events
50+
private var expectedPointerCount = 0
51+
52+
// Here we have workaround for issue introduced in Flutter SDK 3.19,
53+
// when map widget is nested inside a gesture detector with e.g. long press callbacks,
54+
// then platform view receives following motion event sequence for a zoom(pinch) gesture:
55+
// DOWN -> MOVE(3-5 events) -> POINTER_DOWN -> MOVE(duplicates of previous move events) -> MOVE(new move events) -> POINTER_UP -> UP
56+
// While the correct sequence is:
57+
// DOWN -> POINTER_DOWN -> MOVE -> POINTER_UP -> UP
58+
@SuppressLint("ClickableViewAccessibility")
59+
override fun onTouchEvent(event: MotionEvent): Boolean {
60+
val actionMasked = event.actionMasked
61+
val actionString = MotionEvent.actionToString(event.action)
62+
val pointerCount = event.pointerCount
63+
64+
// For MOVE events, check if pointer count matches expected
65+
// This filters out both the early MOVE events AND their duplicates
66+
if (actionMasked == MotionEvent.ACTION_MOVE && expectedPointerCount > 0 && pointerCount != expectedPointerCount) {
67+
Log.d("NativeView", "✗ Filtered: $actionString, Expected: $expectedPointerCount, Got: $pointerCount, Time: ${event.eventTime}")
68+
return false // Skip wrong count
69+
}
70+
71+
// Update expected pointer count based on action
72+
when (actionMasked) {
73+
MotionEvent.ACTION_DOWN -> {
74+
expectedPointerCount = 1
75+
}
76+
MotionEvent.ACTION_POINTER_DOWN -> {
77+
expectedPointerCount = pointerCount
78+
}
79+
MotionEvent.ACTION_POINTER_UP -> {
80+
expectedPointerCount = pointerCount - 1
81+
}
82+
MotionEvent.ACTION_UP -> {
83+
expectedPointerCount = 0
84+
}
85+
}
86+
87+
return super.onTouchEvent(event)
88+
}
89+
}
90+
4191
class MapboxMapController(
4292
context: Context,
4393
mapInitOptions: MapInitOptions,
@@ -50,7 +100,7 @@ class MapboxMapController(
50100
DefaultLifecycleObserver,
51101
MethodChannel.MethodCallHandler {
52102

53-
private var mapView: MapView? = null
103+
private var mapView: FlutterMapView? = null
54104
private var mapboxMap: MapboxMap? = null
55105

56106
private val methodChannel: MethodChannel
@@ -136,7 +186,7 @@ class MapboxMapController(
136186
this.messenger = messenger
137187
this.channelSuffix = channelSuffix.toString()
138188

139-
val mapView = MapView(context, mapInitOptions)
189+
val mapView = FlutterMapView(context, mapInitOptions)
140190
val mapboxMap = mapView.mapboxMap
141191
this.mapView = mapView
142192
this.mapboxMap = mapboxMap

0 commit comments

Comments
 (0)