-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[google_maps_flutter] Ground overlay support - platform impls #8563
base: main
Are you sure you want to change the base?
Changes from 5 commits
174caf4
12792be
37d71fb
b84b657
43522ae
8f1be2b
323326b
26d8c93
cdf4d25
29a8e41
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
## 2.15.0 | ||
|
||
* Adds support for ground overlay. | ||
|
||
## 2.14.12 | ||
|
||
* Updates androidx.annotation:annotation to 1.9.1. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,7 @@ | |
import com.google.android.gms.maps.model.Dash; | ||
import com.google.android.gms.maps.model.Dot; | ||
import com.google.android.gms.maps.model.Gap; | ||
import com.google.android.gms.maps.model.GroundOverlay; | ||
import com.google.android.gms.maps.model.JointType; | ||
import com.google.android.gms.maps.model.LatLng; | ||
import com.google.android.gms.maps.model.LatLngBounds; | ||
|
@@ -849,6 +850,139 @@ static Tile tileFromPigeon(Messages.PlatformTile tile) { | |
return new Tile(tile.getWidth().intValue(), tile.getHeight().intValue(), tile.getData()); | ||
} | ||
|
||
/** | ||
* Set the options in the given ground overlay object to the given sink. | ||
* | ||
* @param groundOverlay the object expected to be a PlatformGroundOverlay containing the ground | ||
* overlay options. | ||
* @param sink the GroundOverlaySink where the options will be set. | ||
* @param assetManager An instance of Android's AssetManager, which provides access to any raw | ||
* asset files stored in the application's assets directory. | ||
* @param density the density of the display, used to calculate pixel dimensions. | ||
* @param wrapper the BitmapDescriptorFactoryWrapper to create BitmapDescriptor. | ||
* @return the identifier of the ground overlay. | ||
* @throws IllegalArgumentException if required fields are missing or invalid. | ||
*/ | ||
static String interpretGroundOverlayOptions( | ||
Messages.PlatformGroundOverlay groundOverlay, | ||
GroundOverlaySink sink, | ||
AssetManager assetManager, | ||
float density, | ||
BitmapDescriptorFactoryWrapper wrapper) { | ||
sink.setTransparency(groundOverlay.getTransparency().floatValue()); | ||
sink.setZIndex(groundOverlay.getZIndex().floatValue()); | ||
sink.setVisible(groundOverlay.getVisible()); | ||
if (groundOverlay.getAnchor() != null) { | ||
sink.setAnchor( | ||
groundOverlay.getAnchor().getX().floatValue(), | ||
groundOverlay.getAnchor().getY().floatValue()); | ||
} | ||
sink.setBearing(groundOverlay.getBearing().floatValue()); | ||
sink.setClickable(groundOverlay.getClickable()); | ||
sink.setImage(toBitmapDescriptor(groundOverlay.getImage(), assetManager, density, wrapper)); | ||
if (groundOverlay.getPosition() != null) { | ||
assert groundOverlay.getWidth() != null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should have an assertion message indicating why it is required or at least log an error saying that width is required. |
||
if (groundOverlay.getHeight() != null) { | ||
sink.setPosition( | ||
latLngFromPigeon(groundOverlay.getPosition()), | ||
groundOverlay.getWidth().floatValue(), | ||
groundOverlay.getHeight().floatValue()); | ||
} else { | ||
sink.setPosition( | ||
latLngFromPigeon(groundOverlay.getPosition()), | ||
groundOverlay.getWidth().floatValue(), | ||
null); | ||
} | ||
} else if (groundOverlay.getBounds() != null) { | ||
sink.setPositionFromBounds(latLngBoundsFromPigeon(groundOverlay.getBounds())); | ||
} | ||
return groundOverlay.getGroundOverlayId(); | ||
} | ||
|
||
/** | ||
* Converts a GroundOverlay object to a PlatformGroundOverlay Pigeon object. | ||
* | ||
* @param groundOverlay the GroundOverlay object to convert. | ||
* @param groundOverlayId the identifier of the GroundOverlay. | ||
* @param isCreatedWithBounds indicates if the GroundOverlay was created with bounds. | ||
* @return the converted PlatformGroundOverlay object. | ||
*/ | ||
static @NonNull Messages.PlatformGroundOverlay groundOverlayToPigeon( | ||
@NonNull GroundOverlay groundOverlay, | ||
@NonNull String groundOverlayId, | ||
boolean isCreatedWithBounds) { | ||
|
||
// Dummy image is used as image is required field of PlatformGroundOverlay and converting image | ||
// back to image descriptor is not currently supported. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a link to what layer of the stack does not support this functionality? Also why is it safe to use a dummy image? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is used only by inpector api, for testing purposes. App facing widget stores groundoverlays on dart implementation, and there is no real reason to fetch the data back, other than testing. |
||
Messages.PlatformBitmap dummyImage = | ||
new Messages.PlatformBitmap.Builder() | ||
.setBitmap( | ||
new Messages.PlatformBitmapBytesMap.Builder() | ||
.setByteData(new byte[] {0}) | ||
.setImagePixelRatio(1.0) | ||
.setBitmapScaling(Messages.PlatformMapBitmapScaling.NONE) | ||
.build()) | ||
.build(); | ||
|
||
Messages.PlatformGroundOverlay.Builder builder = | ||
new Messages.PlatformGroundOverlay.Builder() | ||
.setGroundOverlayId(groundOverlayId) | ||
.setImage(dummyImage) | ||
.setWidth((double) groundOverlay.getWidth()) | ||
.setHeight((double) groundOverlay.getHeight()) | ||
.setBearing((double) groundOverlay.getBearing()) | ||
.setTransparency((double) groundOverlay.getTransparency()) | ||
.setZIndex((long) groundOverlay.getZIndex()) | ||
.setVisible(groundOverlay.isVisible()) | ||
.setClickable(groundOverlay.isClickable()); | ||
|
||
if (isCreatedWithBounds) { | ||
builder.setBounds(Convert.latLngBoundsToPigeon(groundOverlay.getBounds())); | ||
} else { | ||
builder.setPosition(Convert.latLngToPigeon(groundOverlay.getPosition())); | ||
} | ||
|
||
builder.setAnchor(Convert.buildGroundOverlayAnchorForPigeon(groundOverlay)); | ||
return builder.build(); | ||
} | ||
|
||
/** | ||
* Builds a PlatformDoublePair representing the anchor point for a GroundOverlay. | ||
* | ||
* @param groundOverlay the GroundOverlay object. | ||
* @return the PlatformDoublePair representing the anchor point. | ||
*/ | ||
@VisibleForTesting | ||
public static @NonNull Messages.PlatformDoublePair buildGroundOverlayAnchorForPigeon( | ||
GroundOverlay groundOverlay) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
Messages.PlatformDoublePair.Builder anchorBuilder = new Messages.PlatformDoublePair.Builder(); | ||
|
||
// Position is overlays anchor point. Calculate normalized anchor point based on position and bounds. | ||
LatLng position = groundOverlay.getPosition(); | ||
LatLngBounds bounds = groundOverlay.getBounds(); | ||
|
||
// Calculate normalized latitude. | ||
double height = bounds.northeast.latitude - bounds.southwest.latitude; | ||
double normalizedLatitude = 1.0 - ((position.latitude - bounds.southwest.latitude) / height); | ||
|
||
// Calculate normalized longitude. | ||
// For longitude, if the bounds cross the antimeridian (west > east), | ||
// adjust the width accordingly. | ||
double west = bounds.southwest.longitude; | ||
double east = bounds.northeast.longitude; | ||
double width = (west <= east) ? (east - west) : (360.0 - (west - east)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we extract these constants into local constants with good naming so it's easier to understand why we need these magic numbers? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ash-google is this what you were looking for? cdf4d25 |
||
|
||
// Adjust the position longitude if it is less than west by adding 360, | ||
// then compute the normalized value. | ||
double normalizedLongitude = | ||
((position.longitude < west ? position.longitude + 360.0 : position.longitude) - west) | ||
/ width; | ||
|
||
anchorBuilder.setX(normalizedLongitude); | ||
anchorBuilder.setY(normalizedLatitude); | ||
return anchorBuilder.build(); | ||
} | ||
|
||
static class BitmapDescriptorFactoryWrapper { | ||
/** | ||
* Creates a BitmapDescriptor from the provided asset key using the {@link | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return and the parameters should get nullability annotations.