[google_maps_flutter] Add methods to programmatically show/hide marker's infowindow (#2181)
diff --git a/AUTHORS b/AUTHORS
index b693b0b..ffc4e5a 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -49,3 +49,4 @@
Quentin Le Guennec <quentin@tengio.com>
Koushik Ravikumar <koushik@tengio.com>
Nissim Dsilva <nissim@tengio.com>
+Giancarlo Rocha <giancarloiff@gmail.com>
diff --git a/packages/google_maps_flutter/CHANGELOG.md b/packages/google_maps_flutter/CHANGELOG.md
index a51d924..9e87ada 100644
--- a/packages/google_maps_flutter/CHANGELOG.md
+++ b/packages/google_maps_flutter/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.5.23
+
+* Add methods to programmatically control markers info windows.
+
## 0.5.22+3
* Fix polygon and circle stroke width according to device density
diff --git a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java
index fe3960f..2b96e3c 100644
--- a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java
+++ b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/GoogleMapController.java
@@ -303,6 +303,24 @@
result.success(null);
break;
}
+ case "markers#showInfoWindow":
+ {
+ Object markerId = call.argument("markerId");
+ markersController.showMarkerInfoWindow((String) markerId, result);
+ break;
+ }
+ case "markers#hideInfoWindow":
+ {
+ Object markerId = call.argument("markerId");
+ markersController.hideMarkerInfoWindow((String) markerId, result);
+ break;
+ }
+ case "markers#isInfoWindowShown":
+ {
+ Object markerId = call.argument("markerId");
+ markersController.isInfoWindowShown((String) markerId, result);
+ break;
+ }
case "polygons#update":
{
Object polygonsToAdd = call.argument("polygonsToAdd");
diff --git a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkerController.java b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkerController.java
index 6f3089b..412daee 100644
--- a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkerController.java
+++ b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkerController.java
@@ -93,4 +93,16 @@
boolean consumeTapEvents() {
return consumeTapEvents;
}
+
+ public void showInfoWindow() {
+ marker.showInfoWindow();
+ }
+
+ public void hideInfoWindow() {
+ marker.hideInfoWindow();
+ }
+
+ public boolean isInfoWindowShown() {
+ return marker.isInfoWindowShown();
+ }
}
diff --git a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java
index 1f86346..70feb97 100644
--- a/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java
+++ b/packages/google_maps_flutter/android/src/main/java/io/flutter/plugins/googlemaps/MarkersController.java
@@ -63,6 +63,35 @@
}
}
+ void showMarkerInfoWindow(String markerId, MethodChannel.Result result) {
+ MarkerController markerController = markerIdToController.get(markerId);
+ if (markerController != null) {
+ markerController.showInfoWindow();
+ result.success(null);
+ } else {
+ result.error("Invalid markerId", "showInfoWindow called with invalid markerId", null);
+ }
+ }
+
+ void hideMarkerInfoWindow(String markerId, MethodChannel.Result result) {
+ MarkerController markerController = markerIdToController.get(markerId);
+ if (markerController != null) {
+ markerController.hideInfoWindow();
+ result.success(null);
+ } else {
+ result.error("Invalid markerId", "hideInfoWindow called with invalid markerId", null);
+ }
+ }
+
+ void isInfoWindowShown(String markerId, MethodChannel.Result result) {
+ MarkerController markerController = markerIdToController.get(markerId);
+ if (markerController != null) {
+ result.success(markerController.isInfoWindowShown());
+ } else {
+ result.error("Invalid markerId", "isInfoWindowShown called with invalid markerId", null);
+ }
+ }
+
boolean onMarkerTap(String googleMarkerId) {
String markerId = googleMapsMarkerIdToDartMarkerId.get(googleMarkerId);
if (markerId == null) {
diff --git a/packages/google_maps_flutter/example/test_driver/google_maps_e2e.dart b/packages/google_maps_flutter/example/test_driver/google_maps_e2e.dart
index 474f605..2697e38 100644
--- a/packages/google_maps_flutter/example/test_driver/google_maps_e2e.dart
+++ b/packages/google_maps_flutter/example/test_driver/google_maps_e2e.dart
@@ -753,4 +753,39 @@
final LatLngBounds bounds2 = await controller.getVisibleRegion();
expect(bounds1, bounds2);
});
+
+ testWidgets('testToggleInfoWindow', (WidgetTester tester) async {
+ final Marker marker = Marker(
+ markerId: MarkerId("marker"),
+ infoWindow: InfoWindow(title: "InfoWindow"));
+ final Set<Marker> markers = <Marker>{marker};
+
+ Completer<GoogleMapController> controllerCompleter =
+ Completer<GoogleMapController>();
+
+ await tester.pumpWidget(Directionality(
+ textDirection: TextDirection.ltr,
+ child: GoogleMap(
+ initialCameraPosition: const CameraPosition(target: LatLng(10.0, 15.0)),
+ markers: markers,
+ onMapCreated: (GoogleMapController googleMapController) {
+ controllerCompleter.complete(googleMapController);
+ },
+ ),
+ ));
+
+ GoogleMapController controller = await controllerCompleter.future;
+
+ bool iwVisibleStatus =
+ await controller.isMarkerInfoWindowShown(marker.markerId);
+ expect(iwVisibleStatus, false);
+
+ await controller.showMarkerInfoWindow(marker.markerId);
+ iwVisibleStatus = await controller.isMarkerInfoWindowShown(marker.markerId);
+ expect(iwVisibleStatus, true);
+
+ await controller.hideMarkerInfoWindow(marker.markerId);
+ iwVisibleStatus = await controller.isMarkerInfoWindowShown(marker.markerId);
+ expect(iwVisibleStatus, false);
+ });
}
diff --git a/packages/google_maps_flutter/ios/Classes/GoogleMapController.m b/packages/google_maps_flutter/ios/Classes/GoogleMapController.m
index 37e0ad0..d694f6f 100644
--- a/packages/google_maps_flutter/ios/Classes/GoogleMapController.m
+++ b/packages/google_maps_flutter/ios/Classes/GoogleMapController.m
@@ -185,6 +185,33 @@
[_markersController removeMarkerIds:markerIdsToRemove];
}
result(nil);
+ } else if ([call.method isEqualToString:@"markers#showInfoWindow"]) {
+ id markerId = call.arguments[@"markerId"];
+ if ([markerId isKindOfClass:[NSString class]]) {
+ [_markersController showMarkerInfoWindow:markerId result:result];
+ } else {
+ result([FlutterError errorWithCode:@"Invalid markerId"
+ message:@"showInfoWindow called with invalid markerId"
+ details:nil]);
+ }
+ } else if ([call.method isEqualToString:@"markers#hideInfoWindow"]) {
+ id markerId = call.arguments[@"markerId"];
+ if ([markerId isKindOfClass:[NSString class]]) {
+ [_markersController hideMarkerInfoWindow:markerId result:result];
+ } else {
+ result([FlutterError errorWithCode:@"Invalid markerId"
+ message:@"hideInfoWindow called with invalid markerId"
+ details:nil]);
+ }
+ } else if ([call.method isEqualToString:@"markers#isInfoWindowShown"]) {
+ id markerId = call.arguments[@"markerId"];
+ if ([markerId isKindOfClass:[NSString class]]) {
+ [_markersController isMarkerInfoWindowShown:markerId result:result];
+ } else {
+ result([FlutterError errorWithCode:@"Invalid markerId"
+ message:@"isInfoWindowShown called with invalid markerId"
+ details:nil]);
+ }
} else if ([call.method isEqualToString:@"polygons#update"]) {
id polygonsToAdd = call.arguments[@"polygonsToAdd"];
if ([polygonsToAdd isKindOfClass:[NSArray class]]) {
diff --git a/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.h b/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.h
index 24d4253..593d2ff 100644
--- a/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.h
+++ b/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.h
@@ -30,6 +30,9 @@
- (instancetype)initMarkerWithPosition:(CLLocationCoordinate2D)position
markerId:(NSString*)markerId
mapView:(GMSMapView*)mapView;
+- (void)showInfoWindow;
+- (void)hideInfoWindow;
+- (BOOL)isInfoWindowShown;
- (BOOL)consumeTapEvents;
- (void)removeMarker;
@end
@@ -44,6 +47,9 @@
- (BOOL)onMarkerTap:(NSString*)markerId;
- (void)onMarkerDragEnd:(NSString*)markerId coordinate:(CLLocationCoordinate2D)coordinate;
- (void)onInfoWindowTap:(NSString*)markerId;
+- (void)showMarkerInfoWindow:(NSString*)markerId result:(FlutterResult)result;
+- (void)hideMarkerInfoWindow:(NSString*)markerId result:(FlutterResult)result;
+- (void)isMarkerInfoWindowShown:(NSString*)markerId result:(FlutterResult)result;
@end
NS_ASSUME_NONNULL_END
\ No newline at end of file
diff --git a/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.m b/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.m
index 76a420f..cd51b2f 100644
--- a/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.m
+++ b/packages/google_maps_flutter/ios/Classes/GoogleMapMarkerController.m
@@ -26,6 +26,17 @@
}
return self;
}
+- (void)showInfoWindow {
+ _mapView.selectedMarker = _marker;
+}
+- (void)hideInfoWindow {
+ if (_mapView.selectedMarker == _marker) {
+ _mapView.selectedMarker = nil;
+ }
+}
+- (BOOL)isInfoWindowShown {
+ return _mapView.selectedMarker == _marker;
+}
- (BOOL)consumeTapEvents {
return _consumeTapEvents;
}
@@ -300,6 +311,38 @@
[_methodChannel invokeMethod:@"infoWindow#onTap" arguments:@{@"markerId" : markerId}];
}
}
+- (void)showMarkerInfoWindow:(NSString*)markerId result:(FlutterResult)result {
+ FLTGoogleMapMarkerController* controller = _markerIdToController[markerId];
+ if (controller) {
+ [controller showInfoWindow];
+ result(nil);
+ } else {
+ result([FlutterError errorWithCode:@"Invalid markerId"
+ message:@"showInfoWindow called with invalid markerId"
+ details:nil]);
+ }
+}
+- (void)hideMarkerInfoWindow:(NSString*)markerId result:(FlutterResult)result {
+ FLTGoogleMapMarkerController* controller = _markerIdToController[markerId];
+ if (controller) {
+ [controller hideInfoWindow];
+ result(nil);
+ } else {
+ result([FlutterError errorWithCode:@"Invalid markerId"
+ message:@"hideInfoWindow called with invalid markerId"
+ details:nil]);
+ }
+}
+- (void)isMarkerInfoWindowShown:(NSString*)markerId result:(FlutterResult)result {
+ FLTGoogleMapMarkerController* controller = _markerIdToController[markerId];
+ if (controller) {
+ result(@([controller isInfoWindowShown]));
+ } else {
+ result([FlutterError errorWithCode:@"Invalid markerId"
+ message:@"isInfoWindowShown called with invalid markerId"
+ details:nil]);
+ }
+}
+ (CLLocationCoordinate2D)getPosition:(NSDictionary*)marker {
NSArray* position = marker[@"position"];
diff --git a/packages/google_maps_flutter/lib/src/controller.dart b/packages/google_maps_flutter/lib/src/controller.dart
index c6c64a5..d451e3b 100644
--- a/packages/google_maps_flutter/lib/src/controller.dart
+++ b/packages/google_maps_flutter/lib/src/controller.dart
@@ -236,4 +236,46 @@
'map#getLatLng', screenCoordinate._toJson());
return LatLng(latLng[0], latLng[1]);
}
+
+ /// Programmatically show the Info Window for a [Marker].
+ ///
+ /// The `markerId` must match one of the markers on the map.
+ /// An invalid `markerId` triggers an "Invalid markerId" error.
+ ///
+ /// * See also:
+ /// * [hideMarkerInfoWindow] to hide the Info Window.
+ /// * [isMarkerInfoWindowShown] to check if the Info Window is showing.
+ Future<void> showMarkerInfoWindow(MarkerId markerId) async {
+ assert(markerId != null);
+ await channel.invokeMethod<void>(
+ 'markers#showInfoWindow', <String, String>{'markerId': markerId.value});
+ }
+
+ /// Programmatically hide the Info Window for a [Marker].
+ ///
+ /// The `markerId` must match one of the markers on the map.
+ /// An invalid `markerId` triggers an "Invalid markerId" error.
+ ///
+ /// * See also:
+ /// * [showMarkerInfoWindow] to show the Info Window.
+ /// * [isMarkerInfoWindowShown] to check if the Info Window is showing.
+ Future<void> hideMarkerInfoWindow(MarkerId markerId) async {
+ assert(markerId != null);
+ await channel.invokeMethod<void>(
+ 'markers#hideInfoWindow', <String, String>{'markerId': markerId.value});
+ }
+
+ /// Returns `true` when the [InfoWindow] is showing, `false` otherwise.
+ ///
+ /// The `markerId` must match one of the markers on the map.
+ /// An invalid `markerId` triggers an "Invalid markerId" error.
+ ///
+ /// * See also:
+ /// * [showMarkerInfoWindow] to show the Info Window.
+ /// * [hideMarkerInfoWindow] to hide the Info Window.
+ Future<bool> isMarkerInfoWindowShown(MarkerId markerId) async {
+ assert(markerId != null);
+ return await channel.invokeMethod<bool>('markers#isInfoWindowShown',
+ <String, String>{'markerId': markerId.value});
+ }
}
diff --git a/packages/google_maps_flutter/pubspec.yaml b/packages/google_maps_flutter/pubspec.yaml
index 31d0f82..d3e751e 100644
--- a/packages/google_maps_flutter/pubspec.yaml
+++ b/packages/google_maps_flutter/pubspec.yaml
@@ -1,7 +1,7 @@
name: google_maps_flutter
description: A Flutter plugin for integrating Google Maps in iOS and Android applications.
homepage: https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter
-version: 0.5.22+3
+version: 0.5.23
dependencies:
flutter: