diff --git a/ios/Classes/MapboxMapController.swift b/ios/Classes/MapboxMapController.swift index 3d19f1fc6..ed4fa101d 100644 --- a/ios/Classes/MapboxMapController.swift +++ b/ios/Classes/MapboxMapController.swift @@ -421,6 +421,12 @@ class MapboxMapController: NSObject, FlutterPlatformView, MGLMapViewDelegate, Ma } } + func mapViewDidBecomeIdle(_ mapView: MGLMapView) { + if let channel = channel { + channel.invokeMethod("map#onIdle", arguments: []); + } + } + func mapView(_ mapView: MGLMapView, regionWillChangeAnimated animated: Bool) { if let channel = channel { channel.invokeMethod("camera#onMoveStarted", arguments: []); diff --git a/lib/src/controller.dart b/lib/src/controller.dart index d58132096..a5ace12fe 100644 --- a/lib/src/controller.dart +++ b/lib/src/controller.dart @@ -11,6 +11,8 @@ typedef void OnStyleLoadedCallback(); typedef void OnCameraTrackingDismissedCallback(); typedef void OnCameraTrackingChangedCallback(MyLocationTrackingMode mode); +typedef void OnMapIdleCallback(); + /// Controller for a single MapboxMap instance running on the host platform. /// /// Change listeners are notified upon changes to any of @@ -32,7 +34,8 @@ class MapboxMapController extends ChangeNotifier { {this.onStyleLoadedCallback, this.onMapClick, this.onCameraTrackingDismissed, - this.onCameraTrackingChanged}) + this.onCameraTrackingChanged, + this.onMapIdle}) : assert(_id != null), assert(channel != null), _channel = channel { @@ -45,7 +48,8 @@ class MapboxMapController extends ChangeNotifier { {OnStyleLoadedCallback onStyleLoadedCallback, OnMapClickCallback onMapClick, OnCameraTrackingDismissedCallback onCameraTrackingDismissed, - OnCameraTrackingChangedCallback onCameraTrackingChanged}) async { + OnCameraTrackingChangedCallback onCameraTrackingChanged, + OnMapIdleCallback onMapIdle}) async { assert(id != null); final MethodChannel channel = MethodChannel('plugins.flutter.io/mapbox_maps_$id'); @@ -54,7 +58,8 @@ class MapboxMapController extends ChangeNotifier { onStyleLoadedCallback: onStyleLoadedCallback, onMapClick: onMapClick, onCameraTrackingDismissed: onCameraTrackingDismissed, - onCameraTrackingChanged: onCameraTrackingChanged); + onCameraTrackingChanged: onCameraTrackingChanged, + onMapIdle: onMapIdle); } final MethodChannel _channel; @@ -66,6 +71,8 @@ class MapboxMapController extends ChangeNotifier { final OnCameraTrackingDismissedCallback onCameraTrackingDismissed; final OnCameraTrackingChangedCallback onCameraTrackingChanged; + final OnMapIdleCallback onMapIdle; + /// Callbacks to receive tap events for symbols placed on this map. final ArgumentCallbacks onSymbolTapped = ArgumentCallbacks(); @@ -175,6 +182,11 @@ class MapboxMapController extends ChangeNotifier { onCameraTrackingDismissed(); } break; + case 'map#onIdle': + if (onMapIdle != null) { + onMapIdle(); + } + break; default: throw MissingPluginException(); } diff --git a/lib/src/mapbox_map.dart b/lib/src/mapbox_map.dart index eedcda940..6cf587667 100644 --- a/lib/src/mapbox_map.dart +++ b/lib/src/mapbox_map.dart @@ -31,6 +31,7 @@ class MapboxMap extends StatefulWidget { this.onMapClick, this.onCameraTrackingDismissed, this.onCameraTrackingChanged, + this.onMapIdle, }) : assert(initialCameraPosition != null); final MapCreatedCallback onMapCreated; @@ -130,6 +131,14 @@ class MapboxMap extends StatefulWidget { final OnCameraTrackingDismissedCallback onCameraTrackingDismissed; final OnCameraTrackingChangedCallback onCameraTrackingChanged; + /// Called when map view is entering an idle state, and no more drawing will + /// be necessary until new data is loaded or there is some interaction with + /// the map. + /// * No camera transitions are in progress + /// * All currently requested tiles have loaded + /// * All fade/transition animations have completed + final OnMapIdleCallback onMapIdle; + @override State createState() => _MapboxMapState(); } @@ -198,7 +207,8 @@ class _MapboxMapState extends State { onStyleLoadedCallback: widget.onStyleLoadedCallback, onMapClick: widget.onMapClick, onCameraTrackingDismissed: widget.onCameraTrackingDismissed, - onCameraTrackingChanged: widget.onCameraTrackingChanged); + onCameraTrackingChanged: widget.onCameraTrackingChanged, + onMapIdle: widget.onMapIdle); _controller.complete(controller); if (widget.onMapCreated != null) { widget.onMapCreated(controller);