diff --git a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapPlugin.kt b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapPlugin.kt index a59ce78f4..34a46ee86 100644 --- a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapPlugin.kt +++ b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapPlugin.kt @@ -8,7 +8,7 @@ class ArcgisMapPlugin : FlutterPlugin { .platformViewRegistry .registerViewFactory( "", - ArcgisMapViewFactory(flutterPluginBinding.binaryMessenger) + ArcgisMapViewFactory(flutterPluginBinding) ) } 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 5dc953b97..276ce423b 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 @@ -4,9 +4,7 @@ import android.content.Context import android.view.LayoutInflater import android.view.View import com.esri.arcgisruntime.ArcGISRuntimeEnvironment -import com.esri.arcgisruntime.geometry.Geometry import com.esri.arcgisruntime.geometry.GeometryEngine -import com.esri.arcgisruntime.geometry.Multipoint import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.PointCollection import com.esri.arcgisruntime.geometry.Polyline @@ -35,7 +33,7 @@ import dev.fluttercommunity.arcgis_map_sdk_android.model.LatLng import dev.fluttercommunity.arcgis_map_sdk_android.model.UserPosition import dev.fluttercommunity.arcgis_map_sdk_android.model.ViewPadding import dev.fluttercommunity.arcgis_map_sdk_android.util.GraphicsParser -import io.flutter.plugin.common.BinaryMessenger +import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel @@ -52,20 +50,21 @@ import kotlin.math.roundToInt internal class ArcgisMapView( private val context: Context, private val viewId: Int, - private val binaryMessenger: BinaryMessenger, private val mapOptions: ArcgisMapOptions, + private val binding: FlutterPluginBinding, ) : PlatformView { private val view: View = LayoutInflater.from(context).inflate(R.layout.vector_map_view, null) private var mapView: MapView private val map = ArcGISMap() private val defaultGraphicsOverlay = GraphicsOverlay() + private val graphicsParser = GraphicsParser(binding) private lateinit var zoomStreamHandler: ZoomStreamHandler private lateinit var centerPositionStreamHandler: CenterPositionStreamHandler private val methodChannel = - MethodChannel(binaryMessenger, "dev.fluttercommunity.arcgis_map_sdk/$viewId") + MethodChannel(binding.binaryMessenger, "dev.fluttercommunity.arcgis_map_sdk/$viewId") override fun getView(): View = view @@ -302,7 +301,7 @@ internal class ArcgisMapView( ) { try { val map = call.arguments as Map - val symbol = GraphicsParser.parseSymbol(map) + val symbol = graphicsParser.parseSymbol(map) function(symbol) result.success(true) } catch (e: Throwable) { @@ -315,16 +314,23 @@ internal class ArcgisMapView( zoomStreamHandler = ZoomStreamHandler() centerPositionStreamHandler = CenterPositionStreamHandler() - EventChannel(binaryMessenger, "dev.fluttercommunity.arcgis_map_sdk/$viewId/zoom") + EventChannel(binding.binaryMessenger, "dev.fluttercommunity.arcgis_map_sdk/$viewId/zoom") .setStreamHandler(zoomStreamHandler) - EventChannel(binaryMessenger, "dev.fluttercommunity.arcgis_map_sdk/$viewId/centerPosition") + EventChannel( + binding.binaryMessenger, + "dev.fluttercommunity.arcgis_map_sdk/$viewId/centerPosition" + ) .setStreamHandler(centerPositionStreamHandler) } private fun onZoomIn(call: MethodCall, result: MethodChannel.Result) { if (mapView.mapScale.isNaN()) { - result.error("Error", "MapView.mapScale is NaN. Maybe the map is not completely loaded.", null) + result.error( + "Error", + "MapView.mapScale is NaN. Maybe the map is not completely loaded.", + null + ) return } @@ -348,7 +354,11 @@ internal class ArcgisMapView( private fun onZoomOut(call: MethodCall, result: MethodChannel.Result) { if (mapView.mapScale.isNaN()) { - result.error("Error", "MapView.mapScale is NaN. Maybe the map is not completely loaded.", null) + result.error( + "Error", + "MapView.mapScale is NaN. Maybe the map is not completely loaded.", + null + ) return } @@ -396,7 +406,7 @@ internal class ArcgisMapView( val graphicArguments = call.arguments as Map lateinit var newGraphic: List try { - newGraphic = GraphicsParser.parse(graphicArguments) + newGraphic = graphicsParser.parse(graphicArguments) } catch (e: Throwable) { result.error("unknown_error", "Error while adding graphic. $e)", null) return @@ -480,8 +490,9 @@ internal class ArcgisMapView( SpatialReferences.getWgs84() ) - val future = if (padding != null) mapView.setViewpointGeometryAsync(polyline.extent, padding) - else mapView.setViewpointGeometryAsync(polyline.extent) + val future = + if (padding != null) mapView.setViewpointGeometryAsync(polyline.extent, padding) + else mapView.setViewpointGeometryAsync(polyline.extent) future.addDoneListener { try { diff --git a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapViewFactory.kt b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapViewFactory.kt index c13ab05a4..8daa76c4b 100644 --- a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapViewFactory.kt +++ b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/ArcgisMapViewFactory.kt @@ -2,18 +2,17 @@ package dev.fluttercommunity.arcgis_map_sdk_android import android.content.Context import dev.fluttercommunity.arcgis_map_sdk_android.model.ArcgisMapOptions -import io.flutter.embedding.engine.FlutterEngine -import io.flutter.plugin.common.BinaryMessenger +import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding import io.flutter.plugin.common.StandardMessageCodec import io.flutter.plugin.platform.PlatformView import io.flutter.plugin.platform.PlatformViewFactory -class ArcgisMapViewFactory(private val binaryMessenger: BinaryMessenger) : +class ArcgisMapViewFactory(private val flutterPluginBinding: FlutterPluginBinding) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { override fun create(context: Context?, viewId: Int, args: Any?): PlatformView { val optionParams = args as Map val params = optionParams.parseToClass() - return ArcgisMapView(context!!, viewId, binaryMessenger, params) + return ArcgisMapView(context!!, viewId, params, flutterPluginBinding) } } diff --git a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/model/symbol/PictureMarkerSymbolPayload.kt b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/model/symbol/PictureMarkerSymbolPayload.kt index 34fbfbae3..1a5a372f0 100644 --- a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/model/symbol/PictureMarkerSymbolPayload.kt +++ b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/model/symbol/PictureMarkerSymbolPayload.kt @@ -1,7 +1,7 @@ package dev.fluttercommunity.arcgis_map_sdk_android.model.symbol data class PictureMarkerSymbolPayload( - val url: String, + val assetUri: String, val width: Double, val height: Double, val xOffset: Int, diff --git a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/util/GraphicsParser.kt b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/util/GraphicsParser.kt index cff99e2e3..b6a66e9b1 100644 --- a/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/util/GraphicsParser.kt +++ b/arcgis_map_sdk_android/android/src/main/kotlin/dev/fluttercommunity/arcgis_map_sdk_android/util/GraphicsParser.kt @@ -1,5 +1,6 @@ package dev.fluttercommunity.arcgis_map_sdk_android.util +import android.graphics.drawable.BitmapDrawable import com.esri.arcgisruntime.geometry.Point import com.esri.arcgisruntime.geometry.PointCollection import com.esri.arcgisruntime.geometry.Polygon @@ -18,110 +19,113 @@ import dev.fluttercommunity.arcgis_map_sdk_android.model.symbol.SimpleLineSymbol import dev.fluttercommunity.arcgis_map_sdk_android.model.symbol.SimpleMarkerSymbolPayload import dev.fluttercommunity.arcgis_map_sdk_android.model.toAGSPoint import dev.fluttercommunity.arcgis_map_sdk_android.parseToClass +import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding +import java.io.InputStream -class GraphicsParser { - companion object { - fun parse(map: Map): List { +class GraphicsParser(private val binding: FlutterPluginBinding) { - val graphics = when (val type = map["type"] as String) { - "point" -> parsePoint(map) - "polygon" -> parsePolygon(map) - "polyline" -> parsePolyline(map) - else -> throw Exception("No type for $type") - } + fun parse(map: Map): List { + val graphics = when (val type = map["type"] as String) { + "point" -> parsePoint(map) + "polygon" -> parsePolygon(map) + "polyline" -> parsePolyline(map) + else -> throw Exception("No type for $type") + } - val attributes = map["attributes"] as? Map + val attributes = map["attributes"] as? Map - if (attributes != null) { - return graphics.map { - attributes.forEach { (key, value) -> - it.attributes[key] = value - } - it + if (attributes != null) { + return graphics.map { + attributes.forEach { (key, value) -> + it.attributes[key] = value } + it } - - return graphics } - private fun parsePoint(map: Map): List { - val point = (map["point"] as Map).parseToClass() - val symbolMap = map["symbol"] as Map + return graphics + } - val pointGraphic = Graphic().apply { - geometry = point.toAGSPoint() - symbol = parseSymbol(symbolMap) - } + private fun parsePoint(map: Map): List { + val point = (map["point"] as Map).parseToClass() + val symbolMap = map["symbol"] as Map - return listOf(pointGraphic) + val pointGraphic = Graphic().apply { + geometry = point.toAGSPoint() + symbol = parseSymbol(symbolMap) } - private fun parsePolyline(map: Map): List { - val points = parseToClass>>>(map["paths"]!!) - val symbolMap = map["symbol"] as Map - - return points.map { subPoints -> - Graphic().apply { - geometry = Polyline(PointCollection(subPoints.map { coordinateArray -> - val x = coordinateArray.elementAtOrNull(0) - val y = coordinateArray.elementAtOrNull(1) - val z = coordinateArray.elementAtOrNull(2) - if (x == null || y == null) { - throw Exception("Coordinate array needs at least 2 doubles. Got $coordinateArray") - } - - if (z != null) Point(x, y, z, SpatialReferences.getWgs84()) - else Point(x, y, SpatialReferences.getWgs84()) - })) - symbol = parseSymbol(symbolMap) - } - } - } + return listOf(pointGraphic) + } - private fun parsePolygon(map: Map): List { - val rings = parseToClass>>>(map["rings"]!!) - val symbolMap = map["symbol"] as Map + private fun parsePolyline(map: Map): List { + val points = parseToClass>>>(map["paths"]!!) + val symbolMap = map["symbol"] as Map + + return points.map { subPoints -> + Graphic().apply { + geometry = Polyline(PointCollection(subPoints.map { coordinateArray -> + val x = coordinateArray.elementAtOrNull(0) + val y = coordinateArray.elementAtOrNull(1) + val z = coordinateArray.elementAtOrNull(2) + if (x == null || y == null) { + throw Exception("Coordinate array needs at least 2 doubles. Got $coordinateArray") + } - return rings.map { ring -> - Graphic().apply { - geometry = - Polygon(PointCollection(ring.map { LatLng(it[0], it[1]).toAGSPoint() })) - symbol = parseSymbol(symbolMap) - } + if (z != null) Point(x, y, z, SpatialReferences.getWgs84()) + else Point(x, y, SpatialReferences.getWgs84()) + })) + symbol = parseSymbol(symbolMap) } } + } - fun parseSymbol(symbolMap: Map): Symbol { - val symbol = when (val type = symbolMap["type"]) { - "simple-marker" -> parseSimpleMarkerSymbol(symbolMap) - "picture-marker" -> parsePictureMarkerSymbol(symbolMap) - "simple-fill" -> parseSimpleFillSymbol(symbolMap) - "simple-line" -> parseSimpleLineSymbol(symbolMap) - else -> throw Exception("No type for $type") + private fun parsePolygon(map: Map): List { + val rings = parseToClass>>>(map["rings"]!!) + val symbolMap = map["symbol"] as Map + + return rings.map { ring -> + Graphic().apply { + geometry = + Polygon(PointCollection(ring.map { LatLng(it[0], it[1]).toAGSPoint() })) + symbol = parseSymbol(symbolMap) } + } + } - return symbol + fun parseSymbol(symbolMap: Map): Symbol { + val symbol = when (val type = symbolMap["type"]) { + "simple-marker" -> parseSimpleMarkerSymbol(symbolMap) + "picture-marker" -> parsePictureMarkerSymbol(symbolMap) + "simple-fill" -> parseSimpleFillSymbol(symbolMap) + "simple-line" -> parseSimpleLineSymbol(symbolMap) + else -> throw Exception("No type for $type") } - private fun parseSimpleMarkerSymbol(map: Map): Symbol { - val payload = map.parseToClass() + return symbol + } - return SimpleMarkerSymbol().apply { - color = payload.color.toHexInt() - size = payload.size.toFloat() - outline = SimpleLineSymbol().apply { - style = SimpleLineSymbol.Style.SOLID - color = payload.outlineColor.toHexInt() - width = payload.outlineWidth.toFloat() - } + private fun parseSimpleMarkerSymbol(map: Map): Symbol { + val payload = map.parseToClass() + + return SimpleMarkerSymbol().apply { + color = payload.color.toHexInt() + size = payload.size.toFloat() + outline = SimpleLineSymbol().apply { + style = SimpleLineSymbol.Style.SOLID + color = payload.outlineColor.toHexInt() + width = payload.outlineWidth.toFloat() } } + } - private fun parsePictureMarkerSymbol(map: Map): Symbol { - val payload = map.parseToClass() + private fun parsePictureMarkerSymbol(map: Map): Symbol { + val payload = map.parseToClass() - return PictureMarkerSymbol(payload.url).apply { + // return local asset in case its a local path + if (!payload.assetUri.isWebUrl()) { + return PictureMarkerSymbol(getBitmapFromAssetPath(payload.assetUri)).apply { width = payload.width.toFloat() height = payload.height.toFloat() offsetX = payload.xOffset.toFloat() @@ -129,34 +133,58 @@ class GraphicsParser { } } - private fun parseSimpleFillSymbol(map: Map): Symbol { - val payload = map.parseToClass() + return PictureMarkerSymbol(payload.assetUri).apply { + width = payload.width.toFloat() + height = payload.height.toFloat() + offsetX = payload.xOffset.toFloat() + offsetY = payload.yOffset.toFloat() + } + } - return SimpleFillSymbol().apply { - color = payload.fillColor.toHexInt() - outline = SimpleLineSymbol().apply { - style = SimpleLineSymbol.Style.SOLID - color = payload.outlineColor.toHexInt() - width = payload.outlineWidth.toFloat() - } - } + private fun getBitmapFromAssetPath(asset: String): BitmapDrawable? { + val assetPath: String = binding + .flutterAssets + .getAssetFilePathBySubpath(asset) + + var inputStream: InputStream? = null + val drawable: BitmapDrawable? + try { + inputStream = binding.applicationContext.assets.open(assetPath) + drawable = BitmapDrawable.createFromStream(inputStream, assetPath) as BitmapDrawable + } finally { + inputStream?.close() } + return drawable + } - private fun parseSimpleLineSymbol(map: Map): Symbol { - val payload = map.parseToClass() + private fun parseSimpleFillSymbol(map: Map): Symbol { + val payload = map.parseToClass() - return SimpleLineSymbol().apply { - if (payload.color != null) color = payload.color.toHexInt() - payload.marker?.let { - markerStyle = it.style - markerPlacement = it.placement - } + return SimpleFillSymbol().apply { + color = payload.fillColor.toHexInt() + outline = SimpleLineSymbol().apply { + style = SimpleLineSymbol.Style.SOLID + color = payload.outlineColor.toHexInt() + width = payload.outlineWidth.toFloat() + } + } + } - style = payload.style - width = payload.width.toFloat() + private fun parseSimpleLineSymbol(map: Map): Symbol { + val payload = map.parseToClass() + + return SimpleLineSymbol().apply { + if (payload.color != null) color = payload.color.toHexInt() + payload.marker?.let { + markerStyle = it.style + markerPlacement = it.placement } + style = payload.style + width = payload.width.toFloat() } - } + } } + +fun String.isWebUrl(): Boolean = this.startsWith("https://") || this.startsWith("http://") diff --git a/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift b/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift index a27e54a2c..45ba2f65e 100644 --- a/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift +++ b/arcgis_map_sdk_ios/ios/Classes/ArcgisMapView.swift @@ -10,6 +10,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView { private let zoomStreamHandler = ZoomStreamHandler() private let centerPositionEventChannel: FlutterEventChannel private let centerPositionStreamHandler = CenterPositionStreamHandler() + private let flutterPluginRegistrar: FlutterPluginRegistrar private var mapLoadStatusObservation: NSKeyValueObservation? @@ -35,23 +36,24 @@ class ArcgisMapView: NSObject, FlutterPlatformView { } init( - frame: CGRect, - viewIdentifier viewId: Int64, - mapOptions: ArcgisMapOptions, - binaryMessenger messenger: FlutterBinaryMessenger + frame: CGRect, + viewIdentifier viewId: Int64, + mapOptions: ArcgisMapOptions, + flutterPluginRegistrar registrar: FlutterPluginRegistrar ) { + flutterPluginRegistrar = registrar methodChannel = FlutterMethodChannel( - name: "dev.fluttercommunity.arcgis_map_sdk/\(viewId)", - binaryMessenger: messenger + name: "dev.fluttercommunity.arcgis_map_sdk/\(viewId)", + binaryMessenger: flutterPluginRegistrar.messenger() ) zoomEventChannel = FlutterEventChannel( - name: "dev.fluttercommunity.arcgis_map_sdk/\(viewId)/zoom", - binaryMessenger: messenger + name: "dev.fluttercommunity.arcgis_map_sdk/\(viewId)/zoom", + binaryMessenger: flutterPluginRegistrar.messenger() ) zoomEventChannel.setStreamHandler(zoomStreamHandler) centerPositionEventChannel = FlutterEventChannel( - name: "dev.fluttercommunity.arcgis_map_sdk/\(viewId)/centerPosition", - binaryMessenger: messenger + name: "dev.fluttercommunity.arcgis_map_sdk/\(viewId)/centerPosition", + binaryMessenger: flutterPluginRegistrar.messenger() ) centerPositionEventChannel.setStreamHandler(centerPositionStreamHandler) @@ -240,7 +242,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView { } private func onAddGraphic(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { - let parser = GraphicsParser() + let parser = GraphicsParser(registrar: flutterPluginRegistrar) var newGraphics = [AGSGraphic]() do { newGraphics.append(contentsOf: try parser.parse(dictionary: call.arguments as! Dictionary)) @@ -441,7 +443,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView { result(FlutterError(code: "missing_data", message: "Invalid arguments", details: nil)) return } - let symbol = try GraphicsParser().parseSymbol(args) + let symbol = try GraphicsParser(registrar: flutterPluginRegistrar).parseSymbol(args) handler(symbol) result(true) } diff --git a/arcgis_map_sdk_ios/ios/Classes/ArcgisMapViewFactory.swift b/arcgis_map_sdk_ios/ios/Classes/ArcgisMapViewFactory.swift index 78279fdfc..1f92d78a3 100644 --- a/arcgis_map_sdk_ios/ios/Classes/ArcgisMapViewFactory.swift +++ b/arcgis_map_sdk_ios/ios/Classes/ArcgisMapViewFactory.swift @@ -2,10 +2,10 @@ import Flutter import UIKit class ArcgisMapViewFactory: NSObject, FlutterPlatformViewFactory { - private var messenger: FlutterBinaryMessenger + private var registrar: FlutterPluginRegistrar - init(messenger: FlutterBinaryMessenger) { - self.messenger = messenger + init(registrar: FlutterPluginRegistrar) { + self.registrar = registrar super.init() } @@ -21,7 +21,7 @@ class ArcgisMapViewFactory: NSObject, FlutterPlatformViewFactory { frame: frame, viewIdentifier: viewId, mapOptions: mapOptions, - binaryMessenger: messenger + flutterPluginRegistrar: registrar ) } diff --git a/arcgis_map_sdk_ios/ios/Classes/GraphicsParser.swift b/arcgis_map_sdk_ios/ios/Classes/GraphicsParser.swift index 4b771a015..a671614be 100644 --- a/arcgis_map_sdk_ios/ios/Classes/GraphicsParser.swift +++ b/arcgis_map_sdk_ios/ios/Classes/GraphicsParser.swift @@ -9,6 +9,12 @@ import Foundation import ArcGIS class GraphicsParser { + let registrar: FlutterPluginRegistrar + + init(registrar: FlutterPluginRegistrar) { + self.registrar = registrar + } + func parse(dictionary: Dictionary) throws -> [AGSGraphic] { let type = dictionary["type"] as! String @@ -129,7 +135,17 @@ class GraphicsParser { private func parsePictureMarkerSymbol(_ dictionary: [String: Any]) -> AGSSymbol { let payload: PictureMarkerSymbolPayload = try! JsonUtil.objectOfJson(dictionary) - let symbol = AGSPictureMarkerSymbol(url: URL(string: payload.url)!) + if(!payload.assetUri.isWebUrl()) { + let uiImage = getFlutterUiImage(payload.assetUri) + let symbol = AGSPictureMarkerSymbol(image: uiImage!) + symbol.width = payload.width + symbol.height = payload.height + symbol.offsetX = payload.xOffset + symbol.offsetY = payload.yOffset + return symbol + } + + let symbol = AGSPictureMarkerSymbol(url: URL(string: payload.assetUri)!) symbol.width = payload.width symbol.height = payload.height symbol.offsetX = payload.xOffset @@ -138,6 +154,12 @@ class GraphicsParser { return symbol } + private func getFlutterUiImage(_ fileName: String) -> UIImage? { + let key = registrar.lookupKey(forAsset: fileName) + let path = Bundle.main.path(forResource: key, ofType: nil) + return UIImage(named: path!) + } + private func parseSimpleLineSymbol(_ dictionary: [String: Any]) -> AGSSymbol { let payload: SimpleLineSymbolPayload = try! JsonUtil.objectOfJson(dictionary) let symbol = AGSSimpleLineSymbol() @@ -166,3 +188,9 @@ private struct PathPayload: Codable { private struct PolygonPayload: Codable { let rings: [[[Double]]] } + +extension String { + func isWebUrl()-> Bool { + return starts(with: "https://") || starts(with: "http://") + } +} diff --git a/arcgis_map_sdk_ios/ios/Classes/Models/Symbols/PictureMarkerSymbolPayload.swift b/arcgis_map_sdk_ios/ios/Classes/Models/Symbols/PictureMarkerSymbolPayload.swift index 2791f8f8e..4a2e5a076 100644 --- a/arcgis_map_sdk_ios/ios/Classes/Models/Symbols/PictureMarkerSymbolPayload.swift +++ b/arcgis_map_sdk_ios/ios/Classes/Models/Symbols/PictureMarkerSymbolPayload.swift @@ -5,7 +5,7 @@ import Foundation struct PictureMarkerSymbolPayload: Codable { - let url: String + let assetUri: String let width: Double let height: Double let xOffset: Double diff --git a/arcgis_map_sdk_ios/ios/Classes/SwiftArcgisMapPlugin.swift b/arcgis_map_sdk_ios/ios/Classes/SwiftArcgisMapPlugin.swift index 5b513eb8c..20ec718d8 100644 --- a/arcgis_map_sdk_ios/ios/Classes/SwiftArcgisMapPlugin.swift +++ b/arcgis_map_sdk_ios/ios/Classes/SwiftArcgisMapPlugin.swift @@ -5,7 +5,7 @@ import ArcGIS public class SwiftArcgisMapPlugin: NSObject, FlutterPlugin { public static func register(with registrar: FlutterPluginRegistrar) { - registrar.register(ArcgisMapViewFactory(messenger: registrar.messenger()), withId: "") + registrar.register(ArcgisMapViewFactory(registrar: registrar), withId: "") let instance = SwiftArcgisMapPlugin() let channel = FlutterMethodChannel( diff --git a/arcgis_map_sdk_method_channel/lib/src/model_extension.dart b/arcgis_map_sdk_method_channel/lib/src/model_extension.dart index f2b4a529e..5a7fa33e0 100644 --- a/arcgis_map_sdk_method_channel/lib/src/model_extension.dart +++ b/arcgis_map_sdk_method_channel/lib/src/model_extension.dart @@ -129,7 +129,7 @@ extension on SimpleMarkerSymbol { extension on PictureMarkerSymbol { Map convertToJson() => { 'type': 'picture-marker', - 'url': mobileUri, + 'assetUri': assetUri, 'width': width, 'height': height, 'xOffset': xOffset, diff --git a/arcgis_map_sdk_platform_interface/lib/src/types/symbol.dart b/arcgis_map_sdk_platform_interface/lib/src/types/symbol.dart index d24746148..25844b00b 100644 --- a/arcgis_map_sdk_platform_interface/lib/src/types/symbol.dart +++ b/arcgis_map_sdk_platform_interface/lib/src/types/symbol.dart @@ -91,26 +91,33 @@ class SimpleMarkerSymbol extends Symbol { /// [xOffset] The offset on the x-axis in pixels /// [yOffset] The offset on the y-axis in pixels class PictureMarkerSymbol extends Symbol { - const PictureMarkerSymbol({ - required this.webUri, - required this.mobileUri, + PictureMarkerSymbol({ + required this.assetUri, required this.width, required this.height, this.xOffset = 0, this.yOffset = 0, - }); + }) : assert( + assertLocalAssetIsPng(assetUri), + "Local assetUri must have type .png. Got $assetUri.", + ); - /// Add a [webUri] of an image to display it as a marker in the whole feature layer + /// Add a [assetUri] of an image to display it as a marker in the whole feature layer /// This can be a url or a local path in which the image is stored locally. /// For example 'web/icons/Icon-192.png' or 'https://[someUrl].png' - final String webUri; - - /// This uri refers to a remote image url only. - final String mobileUri; + /// Local assets must have the type .png. + final String assetUri; final double width; final double height; final int xOffset; final int yOffset; + + static bool assertLocalAssetIsPng(String assetUri) { + if (assetUri.startsWith("https://") || assetUri.startsWith("http://")) { + return true; + } + return assetUri.endsWith(".png"); + } } /// Set the [fillColor] and other attributes of the polygon displayed in the map diff --git a/arcgis_map_sdk_web/lib/src/model_extension.dart b/arcgis_map_sdk_web/lib/src/model_extension.dart index 66d8fdd5c..c9f601f50 100644 --- a/arcgis_map_sdk_web/lib/src/model_extension.dart +++ b/arcgis_map_sdk_web/lib/src/model_extension.dart @@ -130,7 +130,7 @@ extension on SimpleMarkerSymbol { extension on PictureMarkerSymbol { Map convertToJson() => { 'type': 'picture-marker', - 'url': webUri, + 'url': assetUri, 'width': '${width}px', 'height': '${height}px', 'xoffset': '${xOffset}px', diff --git a/example/assets/navPointer.png b/example/assets/navPointer.png new file mode 100644 index 000000000..4c4dfdd1e Binary files /dev/null and b/example/assets/navPointer.png differ diff --git a/example/lib/main.dart b/example/lib/main.dart index fda1bde80..af6e55310 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:core'; +import 'dart:io'; import 'package:arcgis_example/location_indicator_example_page.dart'; import 'package:arcgis_example/map_elements.dart'; @@ -688,6 +689,13 @@ class _ExampleMapState extends State { ], ), ), + if (!kIsWeb) + ElevatedButton( + onPressed: () => _makePolylineVisible( + points: [_firstPinCoordinates, _secondPinCoordinates], + ), + child: const Text('Zoom to polyline'), + ), Row( children: [ const Text( @@ -709,10 +717,16 @@ class _ExampleMapState extends State { } /// Marker for searched address - final _markerSymbol = const PictureMarkerSymbol( - webUri: 'assets/pin_filled.svg', - mobileUri: - "https://github.com/google/material-design-icons/raw/6ebe181c634f9ced978b526e13db6d7d5cb1c1ba/ios/content/flag/materialiconstwotone/black/twotone_flag_black_48pt.xcassets/twotone_flag_black_48pt.imageset/twotone_flag_black_48pt_3x.png", + // final _markerSymbol = const PictureMarkerSymbol( + // webUri: 'assets/pin_filled.svg', + // mobileUri: + // "https://github.com/google/material-design-icons/raw/6ebe181c634f9ced978b526e13db6d7d5cb1c1ba/ios/content/flag/materialiconstwotone/black/twotone_flag_black_48pt.xcassets/twotone_flag_black_48pt.imageset/twotone_flag_black_48pt_3x.png", + // width: 56, + // height: 56, + // ); + + final _markerSymbol = PictureMarkerSymbol( + assetUri: 'assets/navPointer.png', width: 56, height: 56, ); diff --git a/example/lib/map_elements.dart b/example/lib/map_elements.dart index 2ae4c90bf..3ebc8b219 100644 --- a/example/lib/map_elements.dart +++ b/example/lib/map_elements.dart @@ -109,10 +109,8 @@ const simpleMarkerSymbol = SimpleMarkerSymbol( outlineColor: Color(0xFF598DD8), ); -const pictureMarkerSymbol = PictureMarkerSymbol( - webUri: 'web/icons/Icon-192.png', - mobileUri: - "https://github.com/google/material-design-icons/raw/6ebe181c634f9ced978b526e13db6d7d5cb1c1ba/ios/content/flag/materialiconstwotone/black/twotone_flag_black_48pt.xcassets/twotone_flag_black_48pt.imageset/twotone_flag_black_48pt_3x.png", +final pictureMarkerSymbol = PictureMarkerSymbol( + assetUri: 'web/icons/Icon-192.png', width: 32, height: 32, );