arcgis_maps 200.7.0+4560
arcgis_maps: ^200.7.0+4560 copied to clipboard
Use ArcGIS Maps SDK for Flutter to incorporate capabilities such as location, 2D viewing and editing, geocoding, and routing into your iOS and Android apps.
example/lib/main.dart
//
// COPYRIGHT © 2023 Esri
//
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
//
// This material is licensed for use under the Esri Master
// Agreement (MA) and is bound by the terms and conditions
// of that agreement.
//
// You may redistribute and use this code without modification,
// provided you adhere to the terms and conditions of the MA
// and include this copyright notice.
//
// See use restrictions at http://www.esri.com/legal/pdfs/mla_e204_e300/english
//
// For additional information, contact:
// Environmental Systems Research Institute, Inc.
// Attn: Contracts and Legal Department
// 380 New York Street
// Redlands, California 92373
// USA
//
// email: legal@esri.com
//
import 'package:arcgis_maps/arcgis_maps.dart';
import 'package:flutter/material.dart';
void main() async {
// Supply your apiKey using the --dart-define-from-file command line argument.
const apiKey = String.fromEnvironment('API_KEY');
// Alternatively, replace the above line with the following and hard-code your apiKey here:
// const apiKey = ''; // Your API Key here.
if (apiKey.isEmpty) {
throw Exception('apiKey undefined');
} else {
ArcGISEnvironment.apiKey = apiKey;
}
// ArcGISMapsExample is the main widget for this example application.
runApp(const MaterialApp(home: ArcGISMapsExample()));
}
/// ArcGISMapsExample demonstrates how to get started with a basic 2D mapping application using arcgis_maps.
/// This application:
/// - Creates and displays an [ArcGISMapView] widget with an [ArcGISMapViewController].
/// - Sets an [ArcGISMap] to [ArcGISMapViewController.arcGISMap].
/// - Adds a list of [FeatureLayer] to [ArcGISMap.operationalLayers].
/// - Adds a [GraphicsOverlay] to [ArcGISMapViewController.graphicsOverlays].
/// - Configures a [GeometryEditor] to create a new [Graphic] and add to [GraphicsOverlay.graphics].
class ArcGISMapsExample extends StatefulWidget {
const ArcGISMapsExample({super.key});
@override
State<ArcGISMapsExample> createState() => _ArcGISMapsExampleState();
}
class _ArcGISMapsExampleState extends State<ArcGISMapsExample> {
// Create a controller for the map view.
final _mapViewController = ArcGISMapView.createController();
// Create a map with a basemap style.
final _map = ArcGISMap.withBasemapStyle(BasemapStyle.arcGISImageryStandard);
// Create a graphics overlay for displaying graphics.
final _graphicsOverlay = GraphicsOverlay();
// Create a geometry editor to create new geometries.
final _geometryEditor = GeometryEditor();
// A flag that indicates if the UI is ready to be used.
var _ready = false;
// A flag that controls the UI based on whether editing is in progress.
var _editingInProgress = false;
// A flag that controls the UI based on layer visibility.
var _layersVisible = true;
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
top: false,
child: Stack(
children: [
Column(
children: [
Expanded(
// Add an ArcGISMapView widget to the widget tree, and set a controller.
child: ArcGISMapView(
controllerProvider: () => _mapViewController,
// Configure actions when the map view is ready to be used.
onMapViewReady: onMapViewReady,
// Configure actions when a user taps on the map view widget.
onTap: !_editingInProgress ? onTap : null,
),
),
],
),
// Add buttons to the UI to toggle layer visibility and create new graphics.
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 30),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Tooltip(
message: 'Toggle layer visibility',
child: ElevatedButton(
onPressed: _ready ? toggleLayerVisibility : null,
child: Icon(
_layersVisible
? Icons.visibility
: Icons.visibility_off,
),
),
),
Tooltip(
message: 'Create a new graphic',
child: ElevatedButton(
onPressed:
_ready
? _editingInProgress
? saveEdits
: startEditing
: null,
child: Icon(
_editingInProgress ? Icons.save : Icons.draw,
),
),
),
],
),
),
],
),
],
),
),
);
}
Future<void> onMapViewReady() async {
// Create feature layers using the ArcGISOnline portal and the required item IDs and layer IDs, where relevant.
final arcGISOnlinePortal = Portal.arcGISOnline();
final buildings = FeatureLayer.withFeatureLayerItem(
PortalItem.withPortalAndItemId(
portal: arcGISOnlinePortal,
itemId: '0ec8512ad21e4bb987d7e848d14e7e24',
),
);
final primaryRoads = FeatureLayer.withItem(
item: PortalItem.withPortalAndItemId(
portal: arcGISOnlinePortal,
itemId: 'f42ecc08a3634182b8678514af35fac3',
),
layerId: 2,
);
final secondaryRoads = FeatureLayer.withItem(
item: PortalItem.withPortalAndItemId(
portal: arcGISOnlinePortal,
itemId: 'f42ecc08a3634182b8678514af35fac3',
),
layerId: 6,
);
final localRoads = FeatureLayer.withItem(
item: PortalItem.withPortalAndItemId(
portal: arcGISOnlinePortal,
itemId: 'f42ecc08a3634182b8678514af35fac3',
),
layerId: 8,
);
// Add the layers to the map's operational layers.
_map.operationalLayers.addAll([
buildings,
primaryRoads,
secondaryRoads,
localRoads,
]);
// Define a renderer for the graphics overlay to style any graphics added to it.
_graphicsOverlay.renderer = SimpleRenderer(
symbol: SimpleFillSymbol(
color: Colors.cyanAccent.withValues(alpha: 0.4),
outline: SimpleLineSymbol(
style: SimpleLineSymbolStyle.dash,
color: Colors.cyan,
width: 2,
),
),
);
// Add some initial graphics to the graphics overlay to display at start up.
_graphicsOverlay.graphics.addAll(createGraphics());
// Add the graphics overlay to the map view controller to display it.
_mapViewController.graphicsOverlays.add(_graphicsOverlay);
// Assign the map to the map view controller.
_mapViewController.arcGISMap = _map;
// Set an initial viewpoint to show at start up.
_mapViewController.setViewpoint(
Viewpoint.fromCenter(
ArcGISPoint(x: -13310927.924, y: 4367840.399),
scale: 5000,
),
);
// Assign the geometry editor to the map view controller.
_mapViewController.geometryEditor = _geometryEditor;
// Configure some geometry editor settings.
await configureGeometryEditor();
// Enable the UI once all configuration is completed.
setState(() => _ready = true);
}
Future<void> onTap(Offset offset) async {
// Perform an identify operation on the graphics overlay at the tapped screen point provided by the onTap callback.
final identifyGraphicsOverlayResult = await _mapViewController
.identifyGraphicsOverlay(
_graphicsOverlay,
screenPoint: offset,
tolerance: 22,
);
// If a graphic is identified at the tap location, display a dialog.
if (identifyGraphicsOverlayResult.graphics.isNotEmpty) {
final identifiedGraphic = identifyGraphicsOverlayResult.graphics.first;
if (mounted) {
await showDialog(
context: context,
builder: (context) {
return AlertDialog(
alignment: Alignment.center,
title: const Text('Tapped on Graphic'),
content: Text(
'Center point:\n'
'x: ${identifiedGraphic.geometry?.extent.center.x}\n'
'y: ${identifiedGraphic.geometry?.extent.center.y}',
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('OK'),
),
],
);
},
);
}
}
}
// Create an initial list of graphics to display.
List<Graphic> createGraphics() {
const largePolygonJson = '''
{"rings":[[[-13311062.662636876,4368080.2952499595],[-13311057.127783449,4368076.3178643389],
[-13311061.634682227,4367769.666227323],[-13311103.149254397,4367767.9142679712],
[-13311104.043995325,4367698.8852444943],[-13311091.295635514,4367692.5083970781],
[-13311089.376387239,4367666.5662346007],[-13311068.132243464,4367666.3481658408],
[-13311067.365961147,4367656.5642296085],[-13311058.564161845,4367655.1021004347],
[-13311060.260100655,4367569.1472102059],[-13311314.397355149,4367569.6304349722],
[-13311329.11803535,4367581.7673969641],[-13311325.279430484,4368078.8186992826],
[-13311229.822984351,4368080.2299739141],[-13311228.715676585,4367907.4899566751],
[-13311146.872602904,4367905.7258633124],[-13311145.543586506,4368081.7248991122],
[-13311062.662636876,4368080.2952499595]]],
"spatialReference":{"latestWkid":3857,"wkid":102100}}''';
// Create a polygon geometry using the provided JSON string.
final largePolygonGeometry = Geometry.fromJsonString(largePolygonJson);
// Create a new graphic using the geometry.
final largeGraphic = Graphic(geometry: largePolygonGeometry);
const mediumPolygonJson = '''
{"rings":[[[-13310930.109359179,4367955.6946535213],[-13310939.951467492,4367565.1394895678],
[-13311052.146218125,4367566.2247806583],[-13311050.523812089,4367957.6713874312],
[-13310930.109359179,4367955.6946535213]]],
"spatialReference":{"latestWkid":3857,"wkid":102100}}''';
// Create a polygon geometry using the provided JSON string.
final mediumPolygonGeometry = Geometry.fromJsonString(mediumPolygonJson);
// Create a new graphic using the geometry.
final mediumGraphic = Graphic(geometry: mediumPolygonGeometry);
const smallPolygonJson = '''
{"rings":[[[-13311036.736801982,4368106.8208614551],[-13311035.197346671,4368240.6001734752],
[-13310765.222839184,4368239.1766897719],[-13310763.479211008,4368109.3070116714],
[-13311036.736801982,4368106.8208614551]]],
"spatialReference":{"latestWkid":3857,"wkid":102100}}''';
// Create a polygon geometry using the provided JSON string.
final smallPolygonGeometry = Geometry.fromJsonString(smallPolygonJson);
// Create a new graphic using the geometry.
final smallGraphic = Graphic(geometry: smallPolygonGeometry);
return [largeGraphic, mediumGraphic, smallGraphic];
}
// Configures some geometry editor settings.
Future<void> configureGeometryEditor() async {
// Use a reticle vertex tool.
_geometryEditor.tool = ReticleVertexTool();
// Set the feature tiling mode on the map.
// Snapping is used to maintain data integrity between different sources of data when editing,
// so full resolution is needed for valid snapping.
_map.loadSettings.featureTilingMode =
FeatureTilingMode.enabledWithFullResolutionWhenSupported;
// Ensure the map and each layer loads in order to synchronize snap settings.
await _map.load();
await Future.wait(_map.operationalLayers.map((layer) => layer.load()));
// Enable snapping on the geometry editor.
_geometryEditor.snapSettings.isEnabled = true;
_geometryEditor.snapSettings.isGeometryGuidesEnabled = true;
// Add the graphics overlay and feature layers to the snap sources and enable snapping for each source.
_geometryEditor.snapSettings.syncSourceSettings();
for (final snapSourceSetting
in _geometryEditor.snapSettings.sourceSettings) {
snapSourceSetting.isEnabled = true;
}
}
// Starts the geometry editor to create new geometries.
void startEditing() {
// Start the geometry editor with the polygon geometry type to create new polygon geometries.
_geometryEditor.startWithGeometryType(GeometryType.polygon);
setState(() => _editingInProgress = true);
}
// Saves the geometry created by the geometry editor to the graphics overlay.
void saveEdits() {
// Stop the geometry editor and get the returned geometry.
final geometry = _geometryEditor.stop();
setState(() => _editingInProgress = false);
if (geometry != null) {
// If there is a valid geometry, create a new graphic using it.
final graphic = Graphic(geometry: geometry);
// Add the graphic to the graphics overlay.
_graphicsOverlay.graphics.add(graphic);
}
}
// Toggle the visibility of the map's operational layers.
void toggleLayerVisibility() {
setState(() => _layersVisible = !_layersVisible);
if (_mapViewController.arcGISMap != null) {
// Get each layer from the list of operational layers on the map and toggle the isVisible property.
for (final layer in _mapViewController.arcGISMap!.operationalLayers) {
layer.isVisible = _layersVisible;
}
}
}
}