BUG: two finger gestures no longer work
~Suddenly~ After upgrading flutter to 3.19, I can no longer zoom using pinch to zoom or rotate the map using two fingers. When I do so I get:
W/MultiFingerGesture(18269): Some MotionEvents were not passed to the library or events from different view trees are merged.
which is created here: https://github.com/mapbox/mapbox-gestures-android/blob/60bcff932b6fc00d1fa4dab660af8787aaa48369/library/src/main/java/com/mapbox/android/gestures/MultiFingerGesture.java#L97-L100
Single finger gestures (like moving around or double tap to zoom in) still work.
I haven't changed anything related to mapbox in my app. ~Although I'm not completely sure this might have started after I upgraded flutter to 3.19 but I'm not quite sure it was not there before.~ After downgrading flutter to 3.16.9 it works again.
Do you have any ideas what might cause this?
Thanks for all the effort with this library :)
In our case we have a GestureDetecor above the map widget to catch long presses. After upgrading to Flutter to 3.19.x scale gestures no longer work for the mapbox widget.
We tested the GestureDetector behavior on a minimal example like this:
GestureDetector(
onLongPressDown: (details) => print("DOWN"),
onLongPressCancel: () => print("CANCEL"),
onLongPressMoveUpdate: (details) => print("UPDATE"),
onLongPressEnd: (details) => print("END"),
behavior: HitTestBehavior.translucent,
child: GestureDetector(
onScaleStart: (details) => print("SCALE START"),
onScaleEnd: (details) => print("SCALE END"),
behavior: HitTestBehavior.translucent,
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.blue,
),
),
),
This works as expected.
If you replace the second GestureDetector with the mapbox widget, it does not work.
Edit: It's also worth mentioning that it's only a problem on Android devices. iOS works fine.
Adding some more examples to the comment of @PaulPickhardt .
In the following example, zooming by doing the two-finger-gesture does not work (on Android). Only DOWN, CANCEL, UPDATE, END gets logged while doint the long press gestures. When doing the zoom-gesture, the following appears a lot in the log: W/MultiFingerGesture(29816): Some MotionEvents were not passed to the library or events from different view trees are merged.
GestureDetector(
onLongPressDown: (details) => print("DOWN"),
onLongPressCancel: () => print("CANCEL"),
onLongPressMoveUpdate: (details) => print("UPDATE"),
onLongPressEnd: (details) => print("END"),
child: MapWidget(
textureView: true,
),
)
The same behavior can be seen with the following example.
GestureDetector(
onLongPressDown: (details) => print("DOWN"),
onLongPressCancel: () => print("CANCEL"),
onLongPressMoveUpdate: (details) => print("UPDATE"),
onLongPressEnd: (details) => print("END"),
child: MapWidget(
textureView: true,
gestureRecognizers: {
Factory<ScaleGestureRecognizer>(() => ScaleGestureRecognizer()),
},
),
),
In the last example, the zoom gesture works and nothing gets logged while doing so. However, when doing the long-press, only DOWN but no other callbacks are triggered.
GestureDetector(
onLongPressDown: (details) => print("DOWN"),
onLongPressCancel: () => print("CANCEL"),
onLongPressMoveUpdate: (details) => print("UPDATE"),
onLongPressEnd: (details) => print("END"),
child: MapWidget(
textureView: true,
gestureRecognizers: {
Factory<EagerGestureRecognizer>(() => EagerGestureRecognizer()),
},
),
),
I think it's related to this : https://github.com/flutter/flutter/pull/136708
I found it with ctrl+F of "gesture" in flutter 3.19 changelogs : https://docs.flutter.dev/release/release-notes/release-notes-3.19.0
Update :
https://docs.flutter.dev/release/breaking-changes/multi-touch-scrolling I think this might be useful :)
Any update / workaround on this ?
As a workaround, we stick with Flutter 3.16.9 for now.
the same issue for me. i downgrade to 3.16.x get great.
try to add gestureRecognizers:<Factory<OneSequenceGestureRecognizer>>{ Factory<OneSequenceGestureRecognizer>(() => EagerGestureRecognizer()), Factory<ScaleGestureRecognizer>(() => ScaleGestureRecognizer()), }
With this parameter it's work for me. Flutter 3.19.3
gestureRecognizers: {
Factory<EagerGestureRecognizer>(() => EagerGestureRecognizer()),
},
This was already known (see my comment from March). @King-Korol @lantah-1
In the last example, the zoom gesture works and nothing gets logged while doing so. However, when doing the long-press, only DOWN but no other callbacks are triggered.
GestureDetector( onLongPressDown: (details) => print("DOWN"), onLongPressCancel: () => print("CANCEL"), onLongPressMoveUpdate: (details) => print("UPDATE"), onLongPressEnd: (details) => print("END"), child: MapWidget( textureView: true, gestureRecognizers: { Factory<EagerGestureRecognizer>(() => EagerGestureRecognizer()), }, ), ),
However, the problem is that by doing so the MapWidget consumes all gestures (even unecessary ones). Other widgets that may need to detect gestures as well may lose their functionality (see the example with the gesture detector). Therefore, this is a workaround that only works in some situations.
Is there any status update on this issue?
In my own case, I need the Android version of the app to behave as the iOS version does, in which a GestureDetector that consumes long press gestures has a child: MapWidget that consumes scale gestures. The reason I need to wrap the MapWidget in a GestureDetector is because MapWidget does not recognize a drag event on a feature.
- The scale gestures behave correctly if I use the workaround above:
MapWidget(gestureRecognizers: Platform.isAndroid ? { Factory<EagerGestureRecognizer>(() => EagerGestureRecognizer()), ..., but now MapWidget consumes everything so the GestureRecognizer no longer receives long presses. MapWidget(gestureRecognizers: Platform.isAndroid ? { Factory<ScaleGestureRecognizer>(() => ScaleGestureRecognizer()), ...just plain does nothing.- A MapWidget without a
gestureRecognizersparameter (i.e., passingnull) sees Scale Gestures not working but long press now able to be consumed by the GestureDetector.
So no solution yet.
Is there a way to create a custom recognizer that can be passed in the manner of Factory<PinchRecognizer>(() => PinchRecognizer()). I tried this, but it was not successful:
class PinchRecognizer extends ScaleGestureRecognizer {
PinchRecognizer({super.debugOwner});
@override
void addPointer(PointerDownEvent event) {
// Accept the pointer if it’s the start of a scale gesture
startTrackingPointer(event.pointer);
resolve(GestureDisposition.accepted);
super.addPointer(event);
}
}
Any thoughts appreciated.