Show legend

View on GitHub

Build a legend for all the operational layers in the map.

Image of show legend

Use case

Legends are used to describe what each symbol on a map represents. A common format is to show an image of the symbol alongside of a text description of what that symbol represents. This sample demonstrates how a simple legend can be built up in code using the LayerContent interface.

How to use the sample

  1. Open the sample
  2. Flick through the legend control to see the various elements that represent features on the map.

How it works

  1. Layers implement the LayerContent interface, which contain a list of LegendInfo. LegendInfo contains a Symbol and a name string. layer.fetchLegendInfos() must be called on each Layer instance to fetch the info from the data.
  2. For each symbol in the LegendInfo list, symbol.createSwatch() must be called so that an image of the Symbol is returned.
  3. The names and images are then displayed next to each other in a list view UI control.

Relevant API

  • LayerContent
  • LegendInfo

Tags

legend, legend info, symbol swatch

Sample Code

show_legend.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
//
// 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 'package:arcgis_maps/arcgis_maps.dart';
import 'package:flutter/material.dart';

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

class ShowLegend extends StatefulWidget {
  const ShowLegend({super.key});
  @override
  State<ShowLegend> createState() => _ShowLegendState();
}

class _ShowLegendState extends State<ShowLegend> with SampleStateSupport {
  // Create a map view controller.
  final _mapViewController = ArcGISMapView.createController();
  // Create a map with a basemap style.
  final _map = ArcGISMap.withBasemapStyle(BasemapStyle.arcGISTopographic);
  // Create a list to store dropdown items.
  var _legendsDropDown = <DropdownMenuItem<LegendInfo>>[];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        top: false,
        child: Column(
          // Add the map view and dropdown button to a column.
          children: [
            Expanded(
              // Add a map view to the widget tree and set a controller.
              child: ArcGISMapView(
                controllerProvider: () => _mapViewController,
                onMapViewReady: onMapViewReady,
              ),
            ),
            // Add a dropdown button to the widget tree.
            DropdownButtonHideUnderline(
              child: DropdownButton(
                menuMaxHeight: 200,
                alignment: Alignment.center,
                hint: const Text(
                  'Legend',
                  style: TextStyle(
                    color: Colors.deepPurple,
                  ),
                ),
                elevation: 16,
                style: const TextStyle(color: Colors.deepPurple),
                // No need to set up onChanged callback.
                onChanged: (_) {},
                items: _legendsDropDown,
              ),
            ),
          ],
        ),
      ),
    );
  }

  void onMapViewReady() async {
    // Get the screen scale.
    final screenScale = MediaQuery.of(context).devicePixelRatio;
    // Create an image layer.
    final imageLayer = ArcGISMapImageLayer.withUri(
      Uri.parse(
        'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer',
      ),
    );
    // Create a feature table.
    final featureTable = ServiceFeatureTable.withUri(
      Uri.parse(
        'https://sampleserver6.arcgisonline.com/arcgis/rest/services/Recreation/FeatureServer/0',
      ),
    );
    // Create a feature layer.
    final featureLayer = FeatureLayer.withFeatureTable(featureTable);
    // Add image and feature layers to the operational layers list of the map.
    _map.operationalLayers.addAll([imageLayer, featureLayer]);
    // Load the image and feature layers.
    await featureLayer.load();
    await imageLayer.load();
    // Create a list to store operational layers and populate it with image and feature layers.
    final operationalLayersList = <LayerContent>[
      ...imageLayer.subLayerContents,
      featureLayer,
    ];

    // Create a list to store dropdown items.
    final legendsDropDown = <DropdownMenuItem<LegendInfo>>[];
    // Get the legend info for each layer and add it to the legends dropdown list.
    for (final layer in operationalLayersList) {
      // Get the legend info for the current layer.
      final layerLegends = await layer.fetchLegendInfos();
      // Add the name of the current layer.
      legendsDropDown.add(
        DropdownMenuItem(
          value: layerLegends.first,
          child: Text(
            layer.name,
            style: const TextStyle(
              fontSize: 15,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      );

      // Add current layer's legends to the dropdown list.
      for (final legend in layerLegends) {
        ArcGISImage? arcGISImage;
        const symbolSize = Size.square(6);
        // Create a swatch for the legend if the legend exists.
        if (legend.symbol != null) {
          arcGISImage = await legend.symbol!.createSwatch(
            screenScale: screenScale,
            backgroundColor: Colors.transparent,
            width: symbolSize.width,
            height: symbolSize.height,
          );
        }
        // Add the legend to the legends list.
        legendsDropDown.add(
          DropdownMenuItem(
            value: legend,
            child: Row(
              children: [
                // Add the legend image to the dropdown list if the image exists.
                arcGISImage != null
                    ? Image.memory(
                        arcGISImage.getEncodedBuffer(),
                      )
                    : Container(),
                const SizedBox(width: 8),
                // Add the legend name to the dropdown list.
                Text(
                  legend.name,
                  style: const TextStyle(fontSize: 12),
                ),
              ],
            ),
          ),
        );
      }
    }
    // Reset the state once the dropdown list is updated.
    setState(() => _legendsDropDown = legendsDropDown);

    // Set the map to the map view controller.
    _mapViewController.arcGISMap = _map;
    // Set the initial viewpoint of the map.
    _map.initialViewpoint = Viewpoint.fromCenter(
      ArcGISPoint(
        x: -11e6,
        y: 6e6,
        spatialReference: SpatialReference.webMercator,
      ),
      scale: 9e7,
    );
  }
}

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