onPress/onLongPress `position` is in device pixels on Android, points on iOS
Summary
Map events that carry a position (onPress, onLongPress, onPanDrag, onPoiClick, marker presses) report it in device pixels on Android and in UIKit points on iOS. Anything an app positions from that value — a context menu, a tooltip, a custom callout — therefore lands PixelRatio.get() times too far right and down on Android. On a 420 dpi device that is 2.625x, which is usually far enough to leave the screen.
docs/mapview.md documents these props as { coordinate: LatLng, position: Point } without stating a unit, so there is nothing that says which platform is right — but the two disagree, and the library itself is not consistent either: MapModule.pointForCoordinate() divides by the display density before resolving its promise, so the two ways of getting a frame point out of the same map answer in different units.
Version
react-native-maps 1.27.2, also present on master (1.29.0) and on beta.
Steps to reproduce
- Render a
MapViewwithprovider={PROVIDER_GOOGLE}on an Android device whose density is not 1. - In
onLongPress, storenativeEvent.positionand absolutely position a small view at that{x, y}. - Long-press somewhere near the middle of the map.
Expected: the view appears under the finger, as it does on iOS.
Actual: it appears at position * density — down and to the right, usually clamped at the edge of the screen.
Cause
MapView.makeClickEventData() puts projection.toScreenLocation(point) into the event as is:
Projection projection = map.getProjection();
Point screenPoint = projection.toScreenLocation(point);
WritableMap position = new WritableNativeMap();
position.putDouble("x", screenPoint.x);
position.putDouble("y", screenPoint.y);toScreenLocation() answers in device pixels. MapModule.pointForCoordinate(), a few files over, divides the very same call by getResources().getDisplayMetrics().density. On iOS the same events carry locationInView: results, which are already points.
Suggested fix
Divide by the display density in makeClickEventData(), the way pointForCoordinate() already does. PR follows.
Source: react-native-maps/react-native-maps