Add feature layers

View on GitHub

Display feature layers from various data sources.

Image of add feature layers

Use case

Feature layers, like all layers, are visual representations of data and are used on a map or scene. In the case of feature layers, the underlying data is held in a feature table or feature service.

Feature services are useful for sharing vector GIS data with clients so that individual features can be queried, displayed, and edited. There are various online and offline methods to load feature services.

How to use the sample

Tap the button on the toolbar to add feature layers, from different sources, to the map. Pan and zoom the map to view the feature layers.

How it works

  1. Set the basemap with a BasemapStyle.
  2. Load a feature layer with a URL.
    i. Create a ServiceFeatureTable from a URL.
    ii. Create a FeatureLayer with the feature table.
  3. Load a feature layer with a portal item.
    i. Create a PortalItem with the portal and item ID.
    ii. Create a FeatureLayer with the portal item and layer ID.
  4. Load a feature layer with a geodatabase.
    i. Instantiate and load a Geodatabase using the file name.
    ii. Get the feature table from the geodatabase with the feature table's name.
    iii. Create a FeatureLayer from the feature table.
  5. Load a feature layer with a geopackage.
    i. Instantiate and load a geopackage using its file name.
    ii. Get the first GeoPackageFeatureTable from the GeoPackageFeatureTables list.
    iii. Create a FeatureLayer from the feature table.
  6. Load a feature layer with a shapefile.
    i. Create a ShapefileFeatureTable using the shapefile name.
    ii. Create a FeatureLayer from the feature table and load it.
  7. Add the feature layer to the map's operationalLayers.

Relevant API

  • FeatureLayer
  • Geodatabase
  • GeoPackage
  • Portal
  • ServiceFeatureTable
  • ShapefileFeatureTable

About the data

This sample uses the Naperville damage assessment service, Trees of Portland portal item, Los Angeles Trailheads geodatabase, Aurora, Colorado GeoPackage and Scottish Wildlife Trust Reserves Shapefile.

The Scottish Wildlife Trust shapefile data is provided from Scottish Wildlife Trust under CC-BY licence. Data © Scottish Wildlife Trust (2022).

Tags

feature, geodatabase, geopackage, layers, service, shapefile, table

Sample Code

add_feature_layers.dart
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
//
// Copyright 2024 Esri
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import 'dart:io';

import 'package:arcgis_maps/arcgis_maps.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';

import '../../utils/sample_data.dart';
import '../../utils/sample_state_support.dart';

// Create an enumeration to define the feature layer sources.
enum Source { url, portalItem, geodatabase, geopackage, shapefile }

class AddFeatureLayers extends StatefulWidget {
  const AddFeatureLayers({super.key});

  @override
  State<AddFeatureLayers> createState() => _AddFeatureLayersState();
}

class _AddFeatureLayersState extends State<AddFeatureLayers>
    with SampleStateSupport {
  // Create a map with a topographic basemap style.
  final _map = ArcGISMap.withBasemapStyle(BasemapStyle.arcGISTopographic);
  // Create a map view controller.
  final _mapViewController = ArcGISMapView.createController();
  // Create a list of feature layer sources.
  final _featureLayerSources = <DropdownMenuItem<Source>>[];
  // Create a variable to store the selected feature layer source.
  Source? _selectedFeatureLayerSource;

  @override
  void initState() {
    super.initState();

    // Add feature layer sources to the list.
    _featureLayerSources.addAll([
      // Add a dropdown menu item to load a feature service from a uri.
      DropdownMenuItem(
        onTap: loadFeatureServiceFromUri,
        value: Source.url,
        child: const Text('URL'),
      ),
      // Add a dropdown menu item to load a feature service from a portal item.
      DropdownMenuItem(
        onTap: loadPortalItem,
        value: Source.portalItem,
        child: const Text('Portal Item'),
      ),
      // Add a dropdown menu item to load a feature service from a geodatabase.
      DropdownMenuItem(
        onTap: loadGeodatabase,
        value: Source.geodatabase,
        child: const Text('Geodatabase'),
      ),
      // Add a dropdown menu item to load a feature service from a geopackage.
      DropdownMenuItem(
        onTap: loadGeopackage,
        value: Source.geopackage,
        child: const Text('Geopackage'),
      ),
      DropdownMenuItem(
        onTap: loadShapefile,
        value: Source.shapefile,
        child: const Text('Shapefile'),
      ),
    ]);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        top: false,
        // Create a column with a map view and a dropdown button.
        child: Column(
          children: [
            // Add a map view to the widget tree and set a controller.
            Expanded(
              child: ArcGISMapView(
                controllerProvider: () => _mapViewController,
                onMapViewReady: _onMapViewReady,
              ),
            ),
            // Create a dropdown button to select a feature layer source.
            DropdownButton(
              alignment: Alignment.center,
              hint: const Text(
                'Select a feature layer source',
                style: TextStyle(
                  color: Colors.deepPurple,
                ),
              ),
              // Set the selected feature layer source.
              value: _selectedFeatureLayerSource,
              icon: const Icon(
                Icons.arrow_drop_down,
                color: Colors.deepPurple,
              ),
              elevation: 16,
              style: const TextStyle(color: Colors.deepPurple),
              // Set the onChanged callback to update the selected feature layer source.
              onChanged: (featureLayerSource) {
                setState(() {
                  _selectedFeatureLayerSource = featureLayerSource;
                });
              },
              items: _featureLayerSources,
            ),
          ],
        ),
      ),
    );
  }

  void _onMapViewReady() async {
    // Set the map on the map view controller.
    _mapViewController.arcGISMap = _map;
  }

  void loadFeatureServiceFromUri() {
    // Create a uri to a feature service.
    final uri = Uri.parse(
      'https://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer/0',
    );
    // Create a service feature table with the uri.
    final serviceFeatureTables = ServiceFeatureTable.withUri(uri);
    // Create a feature layer with the service feature table.
    final serviceFeatureLayer =
        FeatureLayer.withFeatureTable(serviceFeatureTables);
    // Clear the operational layers and add the feature layer to the map.
    _map.operationalLayers.clear();
    _map.operationalLayers.add(serviceFeatureLayer);
    // Set the viewpoint to the feature layer.
    _mapViewController.setViewpoint(
      Viewpoint.withLatLongScale(
        latitude: 41.773519,
        longitude: -88.153104,
        scale: 6000,
      ),
    );
  }

  void loadGeodatabase() async {
    // Download the sample data.
    await downloadSampleData(['cb1b20748a9f4d128dad8a87244e3e37']);
    // Get the application documents directory.
    final appDir = await getApplicationDocumentsDirectory();
    // Create a file to the geodatabase.
    final geodatabaseFile =
        File('${appDir.absolute.path}/LA_Trails/LA_Trails.geodatabase');
    // Create a geodatabase with the file uri.
    final geodatabase = Geodatabase.withFileUri(geodatabaseFile.uri);
    // Load the geodatabase.
    await geodatabase.load();
    // Get the feature table with the table name.
    final geodatabaseFeatureTables =
        geodatabase.getGeodatabaseFeatureTable(tableName: 'Trailheads');
    // Check if the feature table is not null.
    if (geodatabaseFeatureTables != null) {
      // Create a feature layer with the feature table.
      final geodatabaseFeatureLayer =
          FeatureLayer.withFeatureTable(geodatabaseFeatureTables);
      // Clear the operational layers and add the feature layer to the map.
      _map.operationalLayers.clear();
      _map.operationalLayers.add(geodatabaseFeatureLayer);
      // Set the viewpoint to the feature layer.
      _mapViewController.setViewpoint(
        Viewpoint.fromCenter(
          ArcGISPoint(
            x: -13214155,
            y: 4040194,
            spatialReference: SpatialReference.webMercator,
          ),
          scale: 125000,
        ),
      );
    }
  }

  void loadPortalItem() async {
    // Set the portal.
    final portal = Portal.arcGISOnline();
    // Create the portal item with the item ID for the Portland tree service data.
    const itemId = '1759fd3e8a324358a0c58d9a687a8578';
    final portalItem =
        PortalItem.withPortalAndItemId(portal: portal, itemId: itemId);
    // Load the portal item.
    await portalItem.load();
    // Create a feature layer with the portal item and layer ID.
    final portalItemFeatureLayer = FeatureLayer.withItem(
      item: portalItem,
      layerId: 0,
    );
    // Clear the operational layers and add the feature layer to the map.
    _map.operationalLayers.clear();
    _map.operationalLayers.add(portalItemFeatureLayer);
    // Set the viewpoint to Portland, Oregon.
    _mapViewController.setViewpoint(
      Viewpoint.withLatLongScale(
        latitude: 45.5266,
        longitude: -122.6219,
        scale: 6000,
      ),
    );
  }

  void loadGeopackage() async {
    // Download the sample data.
    await downloadSampleData(['68ec42517cdd439e81b036210483e8e7']);
    // Get the application documents directory.
    final appDir = await getApplicationDocumentsDirectory();
    // Create a file to the geopackage.
    final geopackageFile =
        File('${appDir.absolute.path}/AuroraCO/AuroraCO.gpkg');
    // Create a geopackage with the file uri.
    final geopackage = GeoPackage.withFileUri(geopackageFile.uri);
    // Load the geopackage.
    await geopackage.load();
    // Get the feature table with the table name.
    final geopackageFeatureTables = geopackage.geoPackageFeatureTables;
    // Create a feature layer with the feature table.
    final geopackageFeatureLayer =
        FeatureLayer.withFeatureTable(geopackageFeatureTables.first);
    // Clear the operational layers and add the feature layer to the map.
    _map.operationalLayers.clear();
    _map.operationalLayers.add(geopackageFeatureLayer);
    // Set the viewpoint to the feature layer.
    _mapViewController.setViewpoint(
      Viewpoint.withLatLongScale(
        latitude: 39.7294,
        longitude: -104.8319,
        scale: 577790.554289,
      ),
    );
  }

  /// Load a feature layer with a local shapefile.
  void loadShapefile() async {
    // Download the sample data.
    await downloadSampleData(['15a7cbd3af1e47cfa5d2c6b93dc44fc2']);
    // Get the application documents directory.
    final appDir = await getApplicationDocumentsDirectory();
    // Get the Shapefile from the download resource.
    final shapefile = File(
      '${appDir.absolute.path}/ScottishWildlifeTrust_reserves/ScottishWildlifeTrust_ReserveBoundaries_20201102.shp',
    );
    // Create a feature table from the Shapefile URI.
    final shapefileFeatureTable =
        ShapefileFeatureTable.withFileUri(shapefile.uri);
    // Create a feature layer for the Shapefile feature table.
    final shapefileFeatureLayer =
        FeatureLayer.withFeatureTable(shapefileFeatureTable);
    // Clear the operational layers and add the feature layer to the map.
    _map.operationalLayers.clear();
    _map.operationalLayers.add(shapefileFeatureLayer);
    // Set the viewpoint to the feature layer.
    _mapViewController.setViewpoint(
      Viewpoint.withLatLongScale(
        latitude: 56.641344,
        longitude: -3.889066,
        scale: 6e6,
      ),
    );
  }
}

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.