Skip to content

Commit 366acfc

Browse files
Merge pull request #73 from Esri/PaulAllanSturm/identifyLayerFeatures
Update "Identify layer features"
2 parents 10ac581 + 59f3432 commit 366acfc

File tree

5 files changed

+167
-36
lines changed

5 files changed

+167
-36
lines changed

assets/generated_samples_list.json

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -630,11 +630,29 @@
630630
"category": "Search and Query",
631631
"description": "Identify features in all layers in a map.",
632632
"ignore": false,
633-
"images": [],
634-
"keywords": [],
633+
"images": [
634+
"identify_layer_features.png"
635+
],
636+
"keywords": [
637+
"identify",
638+
"recursion",
639+
"recursive",
640+
"sublayers",
641+
"ArcGISMapViewController.identifyLayers",
642+
"IdentifyLayerResult",
643+
"IdentifyLayerResult.layerContent.name",
644+
"IdentifyLayerResult.sublayerResults"
645+
],
635646
"redirect_from": [],
636-
"relevant_apis": [],
637-
"snippets": [],
647+
"relevant_apis": [
648+
"ArcGISMapViewController.identifyLayers",
649+
"IdentifyLayerResult",
650+
"IdentifyLayerResult.layerContent.name",
651+
"IdentifyLayerResult.sublayerResults"
652+
],
653+
"snippets": [
654+
"identify_layer_features_sample.dart"
655+
],
638656
"title": "Identify layer features",
639657
"key": "identify_layer_features"
640658
},
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Identify layer features
2+
3+
Identify features in all layers in a map.
4+
5+
![Image of identify layer features](identify_layer_features.png)
6+
7+
## Use case
8+
9+
`identifyLayers` allows users to tap on a map, returning features at that location across multiple layers. Because some layer types have sublayers, the sample recursively counts results for sublayers within each layer.
10+
11+
## How to use the sample
12+
13+
Tap to identify features. A banner will list layers with features under the tapped location, as well as a layer count.
14+
15+
## How it works
16+
17+
1. The tapped position is passed to `ArcGISMapViewController.identifyLayers`.
18+
2. For each `IdentifyLayerResult` in the results, features are counted.
19+
20+
Note: there is one identify result per layer with matching features; if the feature count is 0, that means a sublayer contains the matching features.
21+
22+
## Relevant API
23+
24+
* ArcGISMapViewController.identifyLayers
25+
* IdentifyLayerResult
26+
* IdentifyLayerResult.layerContent.name
27+
* IdentifyLayerResult.sublayerResults
28+
29+
## Additional information
30+
31+
The `GeoViewController` supports two methods of identify: `identifyLayer()`, which identifies features within a specific layer, and `identifyLayers()`, which identifies features for all layers in the current view.
32+
33+
## Tags
34+
35+
identify, recursion, recursive, sublayers

lib/samples/identify_layer_features/README.metadata.json

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,28 @@
22
"category": "Search and Query",
33
"description": "Identify features in all layers in a map.",
44
"ignore": false,
5-
"images": [],
6-
"keywords": [],
5+
"images": [
6+
"identify_layer_features.png"
7+
],
8+
"keywords": [
9+
"identify",
10+
"recursion",
11+
"recursive",
12+
"sublayers",
13+
"ArcGISMapViewController.identifyLayers",
14+
"IdentifyLayerResult",
15+
"IdentifyLayerResult.layerContent.name",
16+
"IdentifyLayerResult.sublayerResults"
17+
],
718
"redirect_from": [],
8-
"relevant_apis": [],
9-
"snippets": [],
19+
"relevant_apis": [
20+
"ArcGISMapViewController.identifyLayers",
21+
"IdentifyLayerResult",
22+
"IdentifyLayerResult.layerContent.name",
23+
"IdentifyLayerResult.sublayerResults"
24+
],
25+
"snippets": [
26+
"identify_layer_features_sample.dart"
27+
],
1028
"title": "Identify layer features"
1129
}
242 KB
Loading

lib/samples/identify_layer_features/identify_layer_features_sample.dart

Lines changed: 88 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,67 @@ class IdentifyLayerFeaturesSample extends StatefulWidget {
2929

3030
class _IdentifyLayerFeaturesSampleState
3131
extends State<IdentifyLayerFeaturesSample> with SampleStateSupport {
32+
// Create a controller for the map view.
3233
final _mapViewController = ArcGISMapView.createController();
34+
// A flag for when the map view is ready and controls can be used.
35+
var _ready = false;
36+
// The message to display in the result banner.
37+
var _message = '';
3338

3439
@override
35-
void initState() {
36-
super.initState();
40+
Widget build(BuildContext context) {
41+
return Scaffold(
42+
body: Stack(
43+
children: [
44+
// Add a map view to the widget tree and set a controller.
45+
ArcGISMapView(
46+
controllerProvider: () => _mapViewController,
47+
onMapViewReady: onMapViewReady,
48+
onTap: onTap,
49+
),
50+
// Add a banner to show the results of the identify operation.
51+
SafeArea(
52+
child: IgnorePointer(
53+
child: Container(
54+
color: Colors.white.withAlpha(230),
55+
padding: const EdgeInsets.all(10),
56+
child: Row(
57+
children: [Text(_message)],
58+
),
59+
),
60+
),
61+
),
62+
// Display a progress indicator and prevent interaction until state is ready.
63+
Visibility(
64+
visible: !_ready,
65+
child: SizedBox.expand(
66+
child: Container(
67+
color: Colors.white30,
68+
child: const Center(child: CircularProgressIndicator()),
69+
),
70+
),
71+
),
72+
],
73+
),
74+
);
75+
}
3776

38-
final map = ArcGISMap.withBasemapStyle(BasemapStyle.arcGISTopographic);
77+
void onMapViewReady() async {
78+
// Create a feature layer of damaged property data.
79+
final serviceFeatureTable = ServiceFeatureTable.withUri(Uri.parse(
80+
'https://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer/0'));
81+
final featureLayer = FeatureLayer.withFeatureTable(serviceFeatureTable);
82+
83+
// Create a layer with world cities data.
84+
final mapImageLayer = ArcGISMapImageLayer.withUri(Uri.parse(
85+
'https://sampleserver6.arcgisonline.com/arcgis/rest/services/SampleWorldCities/MapServer'));
86+
await mapImageLayer.load();
87+
// Hide continent and world layers.
88+
mapImageLayer.subLayerContents[1].isVisible = false;
89+
mapImageLayer.subLayerContents[2].isVisible = false;
3990

91+
// Create a map with a basemap style and an initial viewpoint.
92+
final map = ArcGISMap.withBasemapStyle(BasemapStyle.arcGISTopographic);
4093
map.initialViewpoint = Viewpoint.fromCenter(
4194
ArcGISPoint(
4295
x: -10977012.785807,
@@ -46,42 +99,49 @@ class _IdentifyLayerFeaturesSampleState
4699
scale: 68015210,
47100
);
48101

49-
final serviceFeatureTable = ServiceFeatureTable.withUri(Uri.parse(
50-
'https://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer/0'));
51-
final featureLayer = FeatureLayer.withFeatureTable(serviceFeatureTable);
52-
53-
map.operationalLayers.add(featureLayer);
102+
// Add the layers to the map.
103+
map.operationalLayers.addAll([featureLayer, mapImageLayer]);
54104

105+
// Add the map to the map view.
55106
_mapViewController.arcGISMap = map;
56107

57-
_mapViewController.magnifierEnabled = true;
58-
}
59-
60-
@override
61-
Widget build(BuildContext context) {
62-
return Scaffold(
63-
body: ArcGISMapView(
64-
controllerProvider: () => _mapViewController,
65-
onTap: onTap,
66-
onLongPressEnd: onTap,
67-
),
68-
);
108+
// Set the ready state variable to true to enable the sample UI.
109+
setState(() {
110+
_message = 'Tap on the map to identify layer features.';
111+
_ready = true;
112+
});
69113
}
70114

71115
void onTap(Offset localPosition) async {
116+
// Identify features at the tapped location.
72117
final identifyLayerResults = await _mapViewController.identifyLayers(
73118
screenPoint: localPosition,
74119
tolerance: 12.0,
120+
maximumResultsPerLayer: 10,
75121
);
76122

77-
if (identifyLayerResults.isNotEmpty && mounted) {
78-
int count = identifyLayerResults.length;
79-
showDialog(
80-
context: context,
81-
builder: (BuildContext context) {
82-
return AlertDialog(content: Text('Found $count'));
83-
},
84-
);
123+
// Count the number of identified features.
124+
var identifyTotal = 0;
125+
final layerCounts = <String>[];
126+
for (final result in identifyLayerResults) {
127+
final layerTotal = result.totalCount;
128+
identifyTotal += layerTotal;
129+
layerCounts.add('${result.layerContent.name}: $layerTotal');
85130
}
131+
132+
// Display the results in the banner.
133+
setState(() {
134+
_message = identifyTotal == 0
135+
? 'No features identified.'
136+
: layerCounts.join('\n');
137+
});
138+
}
139+
}
140+
141+
extension on IdentifyLayerResult {
142+
// The total count of features, recursively including all sublayers.
143+
int get totalCount {
144+
return sublayerResults.fold(geoElements.length,
145+
(previous, element) => previous + element.totalCount);
86146
}
87147
}

0 commit comments

Comments
 (0)