From e3cbced5adf88d77cbed12c328e68b7b5543ed6b Mon Sep 17 00:00:00 2001 From: sbergmair Date: Wed, 29 Nov 2023 08:44:30 +0100 Subject: [PATCH 01/11] add callback and reload android --- .../arcgis_map_sdk_android/ArcgisMapView.kt | 42 +++++++++++++++---- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt index 1c48047e..67ea579d 100644 --- a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt +++ b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt @@ -8,6 +8,7 @@ import com.esri.arcgisruntime.geometry.GeometryEngine import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.layers.ArcGISVectorTiledLayer +import com.esri.arcgisruntime.loadable.LoadStatusChangedEvent import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.BasemapStyle @@ -58,16 +59,20 @@ internal class ArcgisMapView( ArcGISRuntimeEnvironment.setApiKey(mapOptions.apiKey) mapView = view.findViewById(R.id.mapView) - if (mapOptions.basemap != null) { - map.basemap = Basemap(mapOptions.basemap) - } else { - val layers = mapOptions.vectorTilesUrls.map { url -> ArcGISVectorTiledLayer(url) } + map.apply { + + basemap = if (mapOptions.basemap != null) { + Basemap(mapOptions.basemap) + } else { + val layers = mapOptions.vectorTilesUrls.map { url -> ArcGISVectorTiledLayer(url) } + Basemap(layers, null) + } - map.basemap = Basemap(layers, null) + minScale = getMapScale(mapOptions.minZoom) + maxScale = getMapScale(mapOptions.maxZoom) + addLoadStatusChangedListener(::onLoadStatusChanged) } - map.minScale = getMapScale(mapOptions.minZoom) - map.maxScale = getMapScale(mapOptions.maxZoom) mapView.map = map mapView.graphicsOverlays.add(defaultGraphicsOverlay) @@ -100,7 +105,15 @@ internal class ArcgisMapView( setupEventChannel() } - override fun dispose() {} + private fun onLoadStatusChanged(event: LoadStatusChangedEvent?) { + if (event == null) return + methodChannel.invokeMethod("onStatusChanged", event.jsonValue()) + } + + override fun dispose() { + map.removeLoadStatusChangedListener(::onLoadStatusChanged) + mapView.dispose() + } // region helper @@ -115,6 +128,7 @@ internal class ArcgisMapView( "add_graphic" -> onAddGraphic(call = call, result = result) "remove_graphic" -> onRemoveGraphic(call = call, result = result) "toggle_base_map" -> onToggleBaseMap(call = call, result = result) + "reload" -> onReload(result = result) else -> result.notImplemented() } } @@ -270,6 +284,11 @@ internal class ArcgisMapView( result.success(true) } + private fun onReload(result: MethodChannel.Result) { + mapView.map.retryLoadAsync() + result.success(true) + } + /** * Convert map scale to zoom level * https://developers.arcgis.com/documentation/mapping-apis-and-services/reference/zoom-levels-and-scale/#conversion-tool @@ -312,4 +331,11 @@ internal class ArcgisMapView( // endregion } +private fun LoadStatusChangedEvent.jsonValue() = when (newLoadStatus) { + LOADED -> "loaded" + LOADING -> "loading" + FAILED_TO_LOAD -> "failedToLoad" + NOT_LOADED -> "notLoaded" + else -> "unknown" +} From fab65a5fe8b449e1cd0d173f9d5f45f8d8a23914 Mon Sep 17 00:00:00 2001 From: sbergmair Date: Wed, 29 Nov 2023 09:14:10 +0100 Subject: [PATCH 02/11] add mapstatus callback and reload on mobile --- .../lib/src/arcgis_map_controller.dart | 41 ++++++++++++++++++- arcgis_map_sdk/lib/src/model/map_status.dart | 1 + .../ios/Classes/ArcgisMapView.swift | 38 +++++++++++++++++ .../src/method_channel_arcgis_map_plugin.dart | 13 ++++++ .../arcgis_map_sdk_platform_interface.dart | 13 ++++++ 5 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 arcgis_map_sdk/lib/src/model/map_status.dart diff --git a/arcgis_map_sdk/lib/src/arcgis_map_controller.dart b/arcgis_map_sdk/lib/src/arcgis_map_controller.dart index 8b84a44d..0b57cb7b 100644 --- a/arcgis_map_sdk/lib/src/arcgis_map_controller.dart +++ b/arcgis_map_sdk/lib/src/arcgis_map_controller.dart @@ -1,13 +1,26 @@ +import 'package:arcgis_map_sdk/src/model/map_status.dart'; import 'package:arcgis_map_sdk_platform_interface/arcgis_map_sdk_platform_interface.dart'; import 'package:flutter/services.dart'; +typedef MapStatusListener = void Function(MapStatus status); + class ArcgisMapController { ArcgisMapController._({ required this.mapId, - }); + }) { + ArcgisMapPlatform.instance.setMethodCallHandler( + mapId: mapId, + onCall: _onCall, + ); + } final int mapId; + final _listeners = []; + MapStatus _mapStatus = MapStatus.unknown; + + MapStatus get mapStatus => _mapStatus; + static Future init( int id, ) async { @@ -60,6 +73,16 @@ class ArcgisMapController { ); } + Future _onCall(MethodCall call) async { + final method = call.method; + switch (method) { + case "onStatusChanged": + return _notifyStatusChanged(call); + default: + throw UnimplementedError('Method "$method" not implemented'); + } + } + Stream getZoom() { return ArcgisMapPlatform.instance.getZoom(mapId); } @@ -149,6 +172,22 @@ class ArcgisMapController { ); } + VoidCallback addStatusChangeListener(MapStatusListener listener) { + _listeners.add(listener); + return () => _listeners.removeWhere((l) => l == listener); + } + + Future reload() { + return ArcgisMapPlatform.instance.reload(mapId); + } + + void _notifyStatusChanged(MethodCall call) { + _mapStatus = MapStatus.values.byName(call.arguments as String); + for (final listener in _listeners) { + listener(_mapStatus); + } + } + Future setInteraction({required bool isEnabled}) { return ArcgisMapPlatform.instance .setInteraction(mapId, isEnabled: isEnabled); diff --git a/arcgis_map_sdk/lib/src/model/map_status.dart b/arcgis_map_sdk/lib/src/model/map_status.dart new file mode 100644 index 00000000..b9755be7 --- /dev/null +++ b/arcgis_map_sdk/lib/src/model/map_status.dart @@ -0,0 +1 @@ +enum MapStatus { loaded, loading, failedToLoad, notLoaded, unknown } diff --git a/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift b/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift index 72329348..f40e2095 100644 --- a/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift +++ b/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift @@ -11,6 +11,8 @@ class ArcgisMapView: NSObject, FlutterPlatformView { private let centerPositionEventChannel: FlutterEventChannel private let centerPositionStreamHandler = CenterPositionStreamHandler() + private var mapLoadStatusObservation: NSKeyValueObservation? + private var mapScaleObservation: NSKeyValueObservation? private var mapVisibleAreaObservation: NSKeyValueObservation? @@ -113,6 +115,13 @@ class ArcgisMapView: NSObject, FlutterPlatformView { setMapInteractive(mapOptions.isInteractive) setupMethodChannel() + + mapLoadStatusObservation = map.observe(\.loadStatus, options: .initial) { [weak self] (map, notifier) in + DispatchQueue.main.async { + let status = map.loadStatus + self?.notifyStatus(status) + } + } } private func setupMethodChannel() { @@ -126,6 +135,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView { case "add_graphic": onAddGraphic(call, result) case "remove_graphic": onRemoveGraphic(call, result) case "toggle_base_map" : onToggleBaseMap(call, result) + case "reload" : onReload(call, result) default: result(FlutterError(code: "Unimplemented", message: "No method matching the name\(call.method)", details: nil)) } @@ -243,6 +253,15 @@ class ArcgisMapView: NSObject, FlutterPlatformView { result(true) } + + private func onReload(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + mapView.map!.retryLoad() + result(true) + } + + private func notifyStatus(_ status: AGSLoadStatus) { + methodChannel.invokeMethod("onStatusChanged", arguments: status.jsonValue()) + } private func onSetInteraction(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { let enabled = (call.arguments! as! Dictionary)["enabled"]! as! Bool @@ -441,3 +460,22 @@ extension AGSBasemapStyle { } } } + +extension AGSLoadStatus { + func jsonValue() -> String { + switch self { + case .loaded: + return "loaded" + case .loading: + return "loading" + case .failedToLoad: + return "failedToLoad" + case .notLoaded: + return "notLoaded" + case .unknown: + return "unknown" + @unknown default: + return "unknown" + } + } +} diff --git a/arcgis_map_sdk_method_channel/lib/src/method_channel_arcgis_map_plugin.dart b/arcgis_map_sdk_method_channel/lib/src/method_channel_arcgis_map_plugin.dart index 552f6c89..52745ae0 100644 --- a/arcgis_map_sdk_method_channel/lib/src/method_channel_arcgis_map_plugin.dart +++ b/arcgis_map_sdk_method_channel/lib/src/method_channel_arcgis_map_plugin.dart @@ -161,6 +161,19 @@ class MethodChannelArcgisMapPlugin extends ArcgisMapPlatform { ).then((value) => value!); } + @override + Future reload(int mapId) async { + return _methodChannelBuilder(mapId).invokeMethod("reload"); + } + + @override + Future setMethodCallHandler({ + required int mapId, + required Future Function(MethodCall) onCall, + }) async { + return _methodChannelBuilder(mapId).setMethodCallHandler(onCall); + } + @override Stream getZoom(int mapId) { _zoomEventStream ??= diff --git a/arcgis_map_sdk_platform_interface/lib/src/arcgis_map_sdk_platform_interface.dart b/arcgis_map_sdk_platform_interface/lib/src/arcgis_map_sdk_platform_interface.dart index 7344db61..71d79549 100644 --- a/arcgis_map_sdk_platform_interface/lib/src/arcgis_map_sdk_platform_interface.dart +++ b/arcgis_map_sdk_platform_interface/lib/src/arcgis_map_sdk_platform_interface.dart @@ -154,6 +154,19 @@ class ArcgisMapPlatform extends PlatformInterface { throw UnimplementedError('zoomOut() has not been implemented.'); } + Future reload(int mapId) { + throw UnimplementedError('reload() has not been implemented.'); + } + + Future setMethodCallHandler({ + required int mapId, + required Future Function(MethodCall) onCall, + }) { + throw UnimplementedError( + 'setMethodCallHandler() has not been implemented.', + ); + } + Future setInteraction(int mapId, {required bool isEnabled}) { throw UnimplementedError('setInteraction() has not been implemented.'); } From 0f889a6a6f45ace6828e61d55c251bf99690611a Mon Sep 17 00:00:00 2001 From: sbergmair Date: Wed, 29 Nov 2023 09:57:16 +0100 Subject: [PATCH 03/11] add imports --- .../fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt index 67ea579d..08a7e405 100644 --- a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt +++ b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt @@ -8,6 +8,11 @@ import com.esri.arcgisruntime.geometry.GeometryEngine import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.SpatialReferences import com.esri.arcgisruntime.layers.ArcGISVectorTiledLayer +import com.esri.arcgisruntime.loadable.LoadStatus.FAILED_TO_LOAD +import com.esri.arcgisruntime.loadable.LoadStatus.LOADED +import com.esri.arcgisruntime.loadable.LoadStatus.LOADING +import com.esri.arcgisruntime.loadable.LoadStatus.NOT_LOADED +import com.esri.arcgisruntime.loadable.LoadStatusChangedEvent import com.esri.arcgisruntime.loadable.LoadStatusChangedEvent import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.Basemap From 56744c9d9441ba067e8120cc28d6503ea32d4796 Mon Sep 17 00:00:00 2001 From: sbergmair Date: Wed, 29 Nov 2023 10:07:42 +0100 Subject: [PATCH 04/11] fix imports --- .../dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt index 08a7e405..02c51b3e 100644 --- a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt +++ b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt @@ -13,7 +13,6 @@ import com.esri.arcgisruntime.loadable.LoadStatus.LOADED import com.esri.arcgisruntime.loadable.LoadStatus.LOADING import com.esri.arcgisruntime.loadable.LoadStatus.NOT_LOADED import com.esri.arcgisruntime.loadable.LoadStatusChangedEvent -import com.esri.arcgisruntime.loadable.LoadStatusChangedEvent import com.esri.arcgisruntime.mapping.ArcGISMap import com.esri.arcgisruntime.mapping.Basemap import com.esri.arcgisruntime.mapping.BasemapStyle From 5eeb80676ed6018f50ae2905a739b11a376a5022 Mon Sep 17 00:00:00 2001 From: Julian Bissekkou Date: Mon, 5 Feb 2024 08:26:03 +0100 Subject: [PATCH 05/11] fix null pointer on android --- .../arcgis_map_sdk_android/ArcgisMapView.kt | 4 +-- example/pubspec.lock | 26 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt index 43730fba..1126d27d 100644 --- a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt +++ b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt @@ -274,7 +274,7 @@ internal class ArcgisMapView( val animationOptionMap = (arguments["animationOptions"] as Map?) val animationOptions = - if (animationOptionMap == null || animationOptionMap.isEmpty()) null + if (animationOptionMap.isNullOrEmpty()) null else animationOptionMap.parseToClass() val scale = if (zoomLevel != null) { @@ -309,7 +309,7 @@ internal class ArcgisMapView( } private fun onReload(result: MethodChannel.Result) { - mapView.map.retryLoadAsync() + mapView.map?.retryLoadAsync() result.success(true) } diff --git a/example/pubspec.lock b/example/pubspec.lock index be84cb57..219468c9 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -79,10 +79,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" cupertino_icons: dependency: "direct main" description: @@ -166,10 +166,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" path: dependency: transitive description: @@ -203,18 +203,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -235,10 +235,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" vector_math: dependency: transitive description: @@ -251,10 +251,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" sdks: - dart: ">=3.1.0 <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.10.0" From 70a92a4e2d93e4daf481dc2b8b1b3c1b2155cce1 Mon Sep 17 00:00:00 2001 From: Julian Bissekkou Date: Mon, 5 Feb 2024 08:32:10 +0100 Subject: [PATCH 06/11] add example for reloading --- example/lib/vector_layer_example_page.dart | 27 +++++++++++++--------- example/pubspec.lock | 26 ++++++++++----------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/example/lib/vector_layer_example_page.dart b/example/lib/vector_layer_example_page.dart index 8358eec3..18d02013 100644 --- a/example/lib/vector_layer_example_page.dart +++ b/example/lib/vector_layer_example_page.dart @@ -10,22 +10,27 @@ class VectorLayerExamplePage extends StatefulWidget { } class _VectorLayerExamplePageState extends State { + ArcgisMapController? _controller; + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), - body: Stack( - children: [ - ArcgisMap( - apiKey: arcGisApiKey, - initialCenter: const LatLng(51.16, 10.45), - zoom: 13, - vectorTileLayerUrls: const [ - "https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer", - ], - mapStyle: MapStyle.twoD, - ), + floatingActionButton: FloatingActionButton( + child: Icon(Icons.refresh), + onPressed: () => _controller?.reload(), + ), + body: ArcgisMap( + apiKey: arcGisApiKey, + onMapCreated: (controller) { + _controller = controller; + }, + initialCenter: const LatLng(51.16, 10.45), + zoom: 13, + vectorTileLayerUrls: const [ + "https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer", ], + mapStyle: MapStyle.twoD, ), ); } diff --git a/example/pubspec.lock b/example/pubspec.lock index 219468c9..be84cb57 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -79,10 +79,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.17.2" cupertino_icons: dependency: "direct main" description: @@ -166,10 +166,10 @@ packages: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" path: dependency: transitive description: @@ -203,18 +203,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" string_scanner: dependency: transitive description: @@ -235,10 +235,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.6.0" vector_math: dependency: transitive description: @@ -251,10 +251,10 @@ packages: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.1.4-beta" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" + dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" From 2fd1963bf33b28e89dc609720768801667c6e9bf Mon Sep 17 00:00:00 2001 From: Julian Bissekkou Date: Mon, 5 Feb 2024 09:17:05 +0100 Subject: [PATCH 07/11] improve example --- example/lib/main.dart | 27 ++++++++++++++++++++++ example/lib/vector_layer_example_page.dart | 9 -------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index f0433577..c315d661 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -4,6 +4,7 @@ import 'dart:core'; import 'package:arcgis_example/map_elements.dart'; import 'package:arcgis_example/vector_layer_example_page.dart'; import 'package:arcgis_map_sdk/arcgis_map_sdk.dart'; +import 'package:arcgis_map_sdk/src/model/map_status.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -71,6 +72,10 @@ class _ExampleMapState extends State { final tappedHQ = const LatLng(48.1234963, 11.5910182); var _isInteractionEnabled = true; + VoidCallback? _removeStatusListener; + + final _scaffoldKey = GlobalKey(); + @override void dispose() { _boundingBoxSubscription?.cancel(); @@ -79,12 +84,17 @@ class _ExampleMapState extends State { _attributionTextSubscription?.cancel(); _zoomSubscription?.cancel(); _isGraphicHoveredSubscription?.cancel(); + _removeStatusListener?.call(); + super.dispose(); } Future _onMapCreated(ArcgisMapController controller) async { _controller = controller; + _removeStatusListener = + _controller!.addStatusChangeListener(_onMapStatusChanged); + // TODO: Remove when mobile implementation is complete if (kIsWeb) { _controller?.onClickListener().listen((Attributes? attributes) { @@ -360,6 +370,7 @@ class _ExampleMapState extends State { @override Widget build(BuildContext context) { return Scaffold( + key: _scaffoldKey, body: Stack( children: [ ArcgisMap( @@ -647,6 +658,10 @@ class _ExampleMapState extends State { ), child: const Text('Remove red polygon'), ), + ElevatedButton( + onPressed: () => _controller?.reload(), + child: const Text('Reload map'), + ), ], ), ), @@ -684,4 +699,16 @@ class _ExampleMapState extends State { MaterialPageRoute(builder: (_) => const VectorLayerExamplePage()), ); } + + void _onMapStatusChanged(MapStatus status) { + final scaffoldContext = _scaffoldKey.currentContext; + if (scaffoldContext == null) return; + + ScaffoldMessenger.of(scaffoldContext).showSnackBar( + SnackBar( + content: Text('Map status changed to: $status'), + duration: const Duration(seconds: 1), + ), + ); + } } diff --git a/example/lib/vector_layer_example_page.dart b/example/lib/vector_layer_example_page.dart index 18d02013..07276bc8 100644 --- a/example/lib/vector_layer_example_page.dart +++ b/example/lib/vector_layer_example_page.dart @@ -10,21 +10,12 @@ class VectorLayerExamplePage extends StatefulWidget { } class _VectorLayerExamplePageState extends State { - ArcgisMapController? _controller; - @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), - floatingActionButton: FloatingActionButton( - child: Icon(Icons.refresh), - onPressed: () => _controller?.reload(), - ), body: ArcgisMap( apiKey: arcGisApiKey, - onMapCreated: (controller) { - _controller = controller; - }, initialCenter: const LatLng(51.16, 10.45), zoom: 13, vectorTileLayerUrls: const [ From a1bc00ea7957a9ce31d3a6992a1868bd7650bd75 Mon Sep 17 00:00:00 2001 From: sbergmair Date: Wed, 7 Feb 2024 13:57:08 +0100 Subject: [PATCH 08/11] merge --- arcgis_map_sdk/lib/arcgis_map_sdk.dart | 1 + example/lib/main.dart | 1 - example/pubspec.lock | 26 +++++++++++++------------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arcgis_map_sdk/lib/arcgis_map_sdk.dart b/arcgis_map_sdk/lib/arcgis_map_sdk.dart index c1b43b7d..5f4dabec 100644 --- a/arcgis_map_sdk/lib/arcgis_map_sdk.dart +++ b/arcgis_map_sdk/lib/arcgis_map_sdk.dart @@ -3,4 +3,5 @@ library arcgis_map; export 'package:arcgis_map_sdk/src/arcgis_map_controller.dart'; export 'package:arcgis_map_sdk/src/arcgis_map_sdk.dart'; +export 'package:arcgis_map_sdk/src/model/map_status.dart'; export 'package:arcgis_map_sdk_platform_interface/arcgis_map_sdk_platform_interface.dart'; diff --git a/example/lib/main.dart b/example/lib/main.dart index 0adecf4a..11e7b6b9 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -4,7 +4,6 @@ import 'dart:core'; import 'package:arcgis_example/map_elements.dart'; import 'package:arcgis_example/vector_layer_example_page.dart'; import 'package:arcgis_map_sdk/arcgis_map_sdk.dart'; -import 'package:arcgis_map_sdk/src/model/map_status.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/example/pubspec.lock b/example/pubspec.lock index be84cb57..219468c9 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -79,10 +79,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" cupertino_icons: dependency: "direct main" description: @@ -166,10 +166,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" path: dependency: transitive description: @@ -203,18 +203,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -235,10 +235,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" vector_math: dependency: transitive description: @@ -251,10 +251,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" sdks: - dart: ">=3.1.0 <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.10.0" From 62a7472c94b5e2679398e7bf8ee5bfa6a4a21f08 Mon Sep 17 00:00:00 2001 From: sbergmair Date: Wed, 7 Feb 2024 14:25:04 +0100 Subject: [PATCH 09/11] feedback --- .../lib/src/arcgis_map_controller.dart | 8 ++++-- .../arcgis_map_sdk_android/ArcgisMapView.kt | 4 +-- .../ios/Classes/ArcgisMapView.swift | 4 +-- .../src/method_channel_arcgis_map_plugin.dart | 4 +-- .../arcgis_map_sdk_platform_interface.dart | 2 +- example/ios/Podfile.lock | 2 +- example/lib/main.dart | 2 +- example/pubspec.lock | 26 +++++++++---------- 8 files changed, 28 insertions(+), 24 deletions(-) diff --git a/arcgis_map_sdk/lib/src/arcgis_map_controller.dart b/arcgis_map_sdk/lib/src/arcgis_map_controller.dart index fd97dd39..39b1bb75 100644 --- a/arcgis_map_sdk/lib/src/arcgis_map_controller.dart +++ b/arcgis_map_sdk/lib/src/arcgis_map_controller.dart @@ -183,13 +183,17 @@ class ArcgisMapController { ); } + /// Adds a listener that gets notified if the map status changes VoidCallback addStatusChangeListener(MapStatusListener listener) { _listeners.add(listener); return () => _listeners.removeWhere((l) => l == listener); } - Future reload() { - return ArcgisMapPlatform.instance.reload(mapId); + /// Calling native `retryLoadAsync` (android) and `retryLoad` (swift) + /// https://developers.arcgis.com/kotlin/api-reference/arcgis-maps-kotlin/com.arcgismaps/-loadable/retry-load.html + /// This does not trigger `onMapCreated` since it will only try, if there is an error + Future retryLoad() { + return ArcgisMapPlatform.instance.retryLoad(mapId); } void _notifyStatusChanged(MethodCall call) { diff --git a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt index f0f0a594..06bce86b 100644 --- a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt +++ b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapView.kt @@ -141,7 +141,7 @@ internal class ArcgisMapView( "add_graphic" -> onAddGraphic(call = call, result = result) "remove_graphic" -> onRemoveGraphic(call = call, result = result) "toggle_base_map" -> onToggleBaseMap(call = call, result = result) - "reload" -> onReload(result = result) + "retryLoad" -> onRetryLoad(result = result) else -> result.notImplemented() } } @@ -337,7 +337,7 @@ internal class ArcgisMapView( result.success(true) } - private fun onReload(result: MethodChannel.Result) { + private fun onRetryLoad(result: MethodChannel.Result) { mapView.map?.retryLoadAsync() result.success(true) } diff --git a/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift b/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift index 55a8e7c8..13831095 100644 --- a/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift +++ b/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift @@ -138,7 +138,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView { case "add_graphic": onAddGraphic(call, result) case "remove_graphic": onRemoveGraphic(call, result) case "toggle_base_map" : onToggleBaseMap(call, result) - case "reload" : onReload(call, result) + case "retryLoad" : onRetryLoad(call, result) default: result(FlutterError(code: "Unimplemented", message: "No method matching the name \(call.method)", details: nil)) } @@ -291,7 +291,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView { result(true) } - private func onReload(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + private func onRetryLoad(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { mapView.map!.retryLoad() result(true) } diff --git a/arcgis_map_sdk_method_channel/lib/src/method_channel_arcgis_map_plugin.dart b/arcgis_map_sdk_method_channel/lib/src/method_channel_arcgis_map_plugin.dart index cfbb7945..508cb1f7 100644 --- a/arcgis_map_sdk_method_channel/lib/src/method_channel_arcgis_map_plugin.dart +++ b/arcgis_map_sdk_method_channel/lib/src/method_channel_arcgis_map_plugin.dart @@ -177,8 +177,8 @@ class MethodChannelArcgisMapPlugin extends ArcgisMapPlatform { } @override - Future reload(int mapId) async { - return _methodChannelBuilder(mapId).invokeMethod("reload"); + Future retryLoad(int mapId) async { + return _methodChannelBuilder(mapId).invokeMethod("retryLoad"); } @override diff --git a/arcgis_map_sdk_platform_interface/lib/src/arcgis_map_sdk_platform_interface.dart b/arcgis_map_sdk_platform_interface/lib/src/arcgis_map_sdk_platform_interface.dart index 117905f6..2347b935 100644 --- a/arcgis_map_sdk_platform_interface/lib/src/arcgis_map_sdk_platform_interface.dart +++ b/arcgis_map_sdk_platform_interface/lib/src/arcgis_map_sdk_platform_interface.dart @@ -162,7 +162,7 @@ class ArcgisMapPlatform extends PlatformInterface { throw UnimplementedError('zoomOut() has not been implemented.'); } - Future reload(int mapId) { + Future retryLoad(int mapId) { throw UnimplementedError('reload() has not been implemented.'); } diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 449844cb..daec7463 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -30,4 +30,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: cc1f88378b4bfcf93a6ce00d2c587857c6008d3b -COCOAPODS: 1.14.2 +COCOAPODS: 1.15.0 diff --git a/example/lib/main.dart b/example/lib/main.dart index 11e7b6b9..01eb41b2 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -665,7 +665,7 @@ class _ExampleMapState extends State { child: const Text('Remove red polygon'), ), ElevatedButton( - onPressed: () => _controller?.reload(), + onPressed: () => _controller?.retryLoad(), child: const Text('Reload map'), ), ], diff --git a/example/pubspec.lock b/example/pubspec.lock index 219468c9..be84cb57 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -79,10 +79,10 @@ packages: dependency: transitive description: name: collection - sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.18.0" + version: "1.17.2" cupertino_icons: dependency: "direct main" description: @@ -166,10 +166,10 @@ packages: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.9.1" path: dependency: transitive description: @@ -203,18 +203,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.11.0" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.1" string_scanner: dependency: transitive description: @@ -235,10 +235,10 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.6.0" vector_math: dependency: transitive description: @@ -251,10 +251,10 @@ packages: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.1.4-beta" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" + dart: ">=3.1.0 <4.0.0" flutter: ">=3.10.0" From b07b0e6b0981fe803c49fa62f913137af7fe8be7 Mon Sep 17 00:00:00 2001 From: sbergmair Date: Wed, 7 Feb 2024 14:48:35 +0100 Subject: [PATCH 10/11] feedback --- arcgis_map_sdk/lib/src/arcgis_map_controller.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arcgis_map_sdk/lib/src/arcgis_map_controller.dart b/arcgis_map_sdk/lib/src/arcgis_map_controller.dart index 39b1bb75..7fce8c26 100644 --- a/arcgis_map_sdk/lib/src/arcgis_map_controller.dart +++ b/arcgis_map_sdk/lib/src/arcgis_map_controller.dart @@ -183,7 +183,7 @@ class ArcgisMapController { ); } - /// Adds a listener that gets notified if the map status changes + /// Adds a listener that gets notified if the map status changes. VoidCallback addStatusChangeListener(MapStatusListener listener) { _listeners.add(listener); return () => _listeners.removeWhere((l) => l == listener); From d5a6c0f738dcf1c9a2a86060533764ff9d7468f0 Mon Sep 17 00:00:00 2001 From: sbergmair Date: Wed, 7 Feb 2024 15:16:45 +0100 Subject: [PATCH 11/11] remove not working buttons from mobile --- example/lib/main.dart | 113 ++++++++++++++++++++++-------------------- 1 file changed, 60 insertions(+), 53 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 01eb41b2..d8075ded 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -453,20 +453,21 @@ class _ExampleMapState extends State { ); }, ), - FloatingActionButton( - heroTag: "3d-map-button", - onPressed: () { - setState(() { - show3dMap = !show3dMap; - _controller?.switchMapStyle( - show3dMap ? MapStyle.threeD : MapStyle.twoD, - ); - }); - }, - backgroundColor: - show3dMap ? Colors.red : Colors.blue, - child: Text(show3dMap ? '3D' : '2D'), - ), + if (kIsWeb) + FloatingActionButton( + heroTag: "3d-map-button", + onPressed: () { + setState(() { + show3dMap = !show3dMap; + _controller?.switchMapStyle( + show3dMap ? MapStyle.threeD : MapStyle.twoD, + ); + }); + }, + backgroundColor: + show3dMap ? Colors.red : Colors.blue, + child: Text(show3dMap ? '3D' : '2D'), + ), ], ), ElevatedButton( @@ -592,38 +593,41 @@ class _ExampleMapState extends State { ? const Text("Stop pos") : const Text("Sub to pos"), ), - ElevatedButton( - onPressed: () { - if (_subscribedToBounds) { - _unsubscribeFromBounds(); - } else { - _subscribeToBounds(); - } - }, - child: _subscribedToBounds - ? const Text("Stop bounds") - : const Text("Sub to bounds"), - ), - ElevatedButton( - onPressed: () { - if (_subscribedToGraphicsInView) { - _unSubscribeToGraphicsInView(); - } else { - _subscribeToGraphicsInView(); - } - }, - child: _subscribedToGraphicsInView - ? const Text("Stop printing Graphics") - : const Text("Start printing Graphics"), - ), - ElevatedButton( - onPressed: () { - final graphicIdsInView = - _controller?.getVisibleGraphicIds(); - graphicIdsInView?.forEach(debugPrint); - }, - child: const Text("Print visible Graphics"), - ), + if (kIsWeb) + ElevatedButton( + onPressed: () { + if (_subscribedToBounds) { + _unsubscribeFromBounds(); + } else { + _subscribeToBounds(); + } + }, + child: _subscribedToBounds + ? const Text("Stop bounds") + : const Text("Sub to bounds"), + ), + if (kIsWeb) + ElevatedButton( + onPressed: () { + if (_subscribedToGraphicsInView) { + _unSubscribeToGraphicsInView(); + } else { + _subscribeToGraphicsInView(); + } + }, + child: _subscribedToGraphicsInView + ? const Text("Stop printing Graphics") + : const Text("Start printing Graphics"), + ), + if (kIsWeb) + ElevatedButton( + onPressed: () { + final graphicIdsInView = + _controller?.getVisibleGraphicIds(); + graphicIdsInView?.forEach(debugPrint); + }, + child: const Text("Print visible Graphics"), + ), ElevatedButton( onPressed: () { _addPolygon( @@ -668,16 +672,19 @@ class _ExampleMapState extends State { onPressed: () => _controller?.retryLoad(), child: const Text('Reload map'), ), + if (!kIsWeb) + ElevatedButton( + onPressed: () => _makePolylineVisible( + points: [ + _firstPinCoordinates, + _secondPinCoordinates + ], + ), + child: const Text('Zoom to polyline'), + ), ], ), ), - if (!kIsWeb) - ElevatedButton( - onPressed: () => _makePolylineVisible( - points: [_firstPinCoordinates, _secondPinCoordinates], - ), - child: const Text('Zoom to polyline'), - ), Row( children: [ const Text(