Learn how to apply renderers and label definitions to a feature layer based on attribute values.
Applications can display feature layer data with different styles to enhance the visualization. The type of Renderer
you choose depends on your application. A SimpleRenderer
applies the same symbol to all features, a UniqueValueRenderer
applies a different symbol to each unique attribute value, and a ClassBreaksRenderer
applies a symbol to a range of numeric values. Renderers are responsible for accessing the data and applying the appropriate symbol to each feature when the layer draws. You can also use a LabelDefinition
to show attribute information for features. Visit the Styles and data visualization documentation to learn more about styling layers.
You can also author, style and save web maps, web scenes, and layers as portal items and then add them to the map in your application. Visit the following tutorials to learn more about adding portal items.
In this tutorial, you will apply different renderers to enhance the visualization of three feature layers with data for the Santa Monica Mountains: Trailheads with a single symbol, Trails based on elevation change and bike use, and Parks and Open Spaces based on the type of park.
PrerequisitesBefore starting this tutorial, you need the following:
An ArcGIS Location Platform or ArcGIS Online account.
A development and deployment environment that meets the system requirements.
An IDE for Android development in Kotlin.
It is recommended that you use the latest stable version Android Studio to create this tutorial app. The code described in the steps below, however, should work in any up-to-date Android IDE that supports Kotlin.
Develop or downloadYou have two options for completing this tutorial:
Option 1: Develop the code Open an Android Studio projectOpen the project you created by completing the Display a map tutorial.
Continue with the following instructions to apply renderers and label definitions to a feature layer based on attribute values.
Modify the old project for use in this new tutorial.
On your file system, delete the .idea folder, if present, at the top level of your project.
In the Android view, open app > res > values > strings.xml.
In the <string name="app_name">
element, change the text content to Style a feature layer.
strings.xml
Use dark colors for code blocks
1
2
3
<resources>
<string name="app_name">Style a feature layer</string>
</resources>
In the Android view, open Gradle Scripts > settings.gradle.kts.
Change the value of rootProject.name
to "Style a feature layer".
settings.gradle.kts
Expand
Use dark colors for code blocks1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url = uri("https://esri.jfrog.io/artifactory/arcgis") }
}
}
rootProject.name = "Style a feature layer"
include(":app")
Click File > Sync Project with Gradle files. Android Studio will recognize your changes and create a new .idea folder.
In the Android view, open app > kotlin+java > com.example.app > MainScreen.kt. Replace the import statements with the imports needed for this tutorial.
MainScreen.kt
Use dark colors for code blocks
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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
@file:OptIn(ExperimentalMaterial3Api::class)
package com.example.app.screens
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.arcgismaps.Color
import com.arcgismaps.data.ServiceFeatureTable
import com.arcgismaps.mapping.ArcGISMap
import com.arcgismaps.mapping.BasemapStyle
import com.arcgismaps.mapping.Viewpoint
import com.arcgismaps.mapping.labeling.ArcadeLabelExpression
import com.arcgismaps.mapping.labeling.LabelDefinition
import com.arcgismaps.mapping.layers.FeatureLayer
import com.arcgismaps.mapping.symbology.ClassBreak
import com.arcgismaps.mapping.symbology.ClassBreaksRenderer
import com.arcgismaps.mapping.symbology.FontStyle
import com.arcgismaps.mapping.symbology.FontWeight
import com.arcgismaps.mapping.symbology.PictureMarkerSymbol
import com.arcgismaps.mapping.symbology.SimpleFillSymbol
import com.arcgismaps.mapping.symbology.SimpleFillSymbolStyle
import com.arcgismaps.mapping.symbology.SimpleLineSymbol
import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle
import com.arcgismaps.mapping.symbology.SimpleRenderer
import com.arcgismaps.mapping.symbology.TextSymbol
import com.arcgismaps.mapping.symbology.UniqueValue
import com.arcgismaps.mapping.symbology.UniqueValueRenderer
import com.arcgismaps.toolkit.geoviewcompose.MapView
import com.example.app.R
Create a function to add a feature layer
You can add a feature layer from a feature service hosted in ArcGIS. Each feature layer contains features with a single geometry type (point, line, or polygon), and a set of attributes. Once added to the map, feature layers can be symbolized, styled, and labeled in a variety of ways.
Define variables that store feature service URLs used by the app's layers, and then create a helper function to add a layer to the map's list of operational layers. You will use this code throughout the tutorial as you add and symbolize various layers.
In createMap()
add four read-only String
variables: three for accessing feature layers, and a fourth for accessing a static image for use in a picture marker symbol. You will use these resources in future steps.
MainScreen.kt
Expand
Use dark colors for code blocks53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 71 72 73 73 73 73 73 73 73 73 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -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
Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun createMap(): ArcGISMap {
val parksAndOpenSpaces =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Parks_and_Open_Space/FeatureServer/0"
val trails =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0"
val trailheads =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer/0"
val trailheadImage =
"https://static.arcgis.com/images/Symbols/NPS/npsPictograph_0231b.png"
return ArcGISMap(BasemapStyle.ArcGISTopographic).apply {
initialViewpoint = Viewpoint(
latitude = 34.0270,
longitude = -118.8050,
scale = 72000.0
)
}
}
In the apply
block for ArcGISMap
, insert code that adds FeatureLayer
s to the map's operationalLayers
. For now, the listOf()
function has no parameters. In this tutorial, you will be adding each new feature layer to the list of parameters.
MainScreen.kt
Expand
Use dark colors for code blocks53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 75 75 75 75 75 75 75 75 75 75 76 77 78 79 80 81 81 81 81 81 81 81 81 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -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
Add line. Add line. Add line. Add line. Add line. Add line. Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun createMap(): ArcGISMap {
val parksAndOpenSpaces =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Parks_and_Open_Space/FeatureServer/0"
val trails =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0"
val trailheads =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer/0"
val trailheadImage =
"https://static.arcgis.com/images/Symbols/NPS/npsPictograph_0231b.png"
return ArcGISMap(BasemapStyle.ArcGISTopographic).apply {
initialViewpoint = Viewpoint(
latitude = 34.0270,
longitude = -118.8050,
scale = 72000.0
)
operationalLayers.addAll(
listOf(
)
)
}
}
Add a top-level helper function named createFeatureLayer()
that takes a feature service URI as an argument and returns a FeatureLayer
created from the URI.
MainScreen.kt
Expand
Use dark colors for code blocks92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 92 91 90 89 88 87 86 85 84 83 82 82 82 82 82 82 82 82 83 84 85 86 87 88 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -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
Add line. Add line. Add line. Add line. Add line. Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun createFeatureLayer(featureServiceUri: String): FeatureLayer {
// Create a service feature table from a Uri
val serviceFeatureTable = ServiceFeatureTable(featureServiceUri)
// Return a feature layer created from the service feature table
return FeatureLayer.createWithFeatureTable(serviceFeatureTable)
}
Create a method to apply a different symbol for each type of park area to the Parks and Open Spaces feature layer.
Add a top-level function named createOpenSpaceLayer()
.
UniqueValue
assigns a symbol to a value or values. A unique value renderer uses a collection of unique values to assign the appropriate symbol for each feature it renderers.
For this example, the renderer uses a feature's TYPE
attribute value to apply the correct symbol.
MainScreen.kt
Expand
Use dark colors for code blocks99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 99 98 97 96 95 94 93 92 91 90 89 89 89 89 89 89 89 89 89 89 89 89 89 89 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 148 147 146 145 144 143 142 141 140 139 138 137 136 135 134 133 132 131 130 129 128 127 126 125 124 123 122 121 120 119 118 117 116 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6
Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun createOpenSpaceLayer(featureServiceUri: String): FeatureLayer {
// Create fill symbol objects to represent the parks and open spaces layer
val magentaFillSymbol = SimpleFillSymbol(SimpleFillSymbolStyle.Solid, Color.fromRgba(255, 0, 255), null)
val greenFillSymbol = SimpleFillSymbol(SimpleFillSymbolStyle.Solid, Color.green, null)
val blueFillSymbol = SimpleFillSymbol(SimpleFillSymbolStyle.Solid, Color.fromRgba(0, 0, 255), null)
val redFillSymbol = SimpleFillSymbol(SimpleFillSymbolStyle.Solid, Color.red, null)
// Create a unique value for natural areas, regional open spaces, local parks, and regional recreation parks
val naturalAreas = UniqueValue(
description = "Natural Areas",
label = "Natural Areas",
symbol = magentaFillSymbol,
values = listOf("Natural Areas")
)
val regionalOpenSpace = UniqueValue(
description = "Regional Open Space",
label = "Regional Open Space",
symbol = greenFillSymbol,
values = listOf("Regional Open Space")
)
val localPark = UniqueValue(
description = "Local Park",
label = "Local Park",
symbol = blueFillSymbol,
values = listOf("Local Park")
)
val regionalRecreationPark = UniqueValue(
description = "Regional Recreation Park",
label = "Regional Recreation Park",
symbol = redFillSymbol,
values = listOf("Regional Recreation Park")
)
// Create a unique value list with the fill symbols
val uniqueValuesList = listOf(
naturalAreas,
regionalOpenSpace,
localPark,
regionalRecreationPark
)
// Create and assign a unique value renderer to the feature layer
val openSpacesUniqueValueRenderer =
UniqueValueRenderer(
fieldNames = listOf("TYPE"),
uniqueValues = uniqueValuesList,
defaultLabel = "Open Spaces",
defaultSymbol = null
)
// Create a parks and open spaces feature layer
val featureLayer = createFeatureLayer(featureServiceUri).apply {
// Style the feature layer using the unique value renderer
renderer = openSpacesUniqueValueRenderer
// Set the layer opacity to semi-transparent
opacity = 0.2f
}
return featureLayer
}
In createMap()
, add the Parks and Open Space feature layer to the map's operational layers by calling createOpenSpaceLayer()
.
MainScreen.kt
Expand
Use dark colors for code blocks53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 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 77 77 77 77 77 77 77 77 78 79 80 81 82 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -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
Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun createMap(): ArcGISMap {
val parksAndOpenSpaces =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Parks_and_Open_Space/FeatureServer/0"
val trails =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0"
val trailheads =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer/0"
val trailheadImage =
"https://static.arcgis.com/images/Symbols/NPS/npsPictograph_0231b.png"
return ArcGISMap(BasemapStyle.ArcGISTopographic).apply {
initialViewpoint = Viewpoint(
latitude = 34.0270,
longitude = -118.8050,
scale = 72000.0
)
operationalLayers.addAll(
listOf(
createOpenSpaceLayer(parksAndOpenSpaces),
)
)
}
}
Click Run > Run > app to run the app.
When the app opens, Parks and Open Spaces feature layer is added to the map. The map displays the different types of parks and open spaces with four unique symbols.
Add a layer with a class breaks rendererCreate a method to apply a different symbol for each of the five ranges of elevation gain to the Trails feature layer.
Add a top-level function named createTrailsLayer()
.
A ClassBreak
assigns a symbol to a range of values.
For this example, the renderer uses each feature's ELEV_GAIN
attribute value to classify it into a defined range (class break) and apply the corresponding symbol.
MainScreen.kt
Expand
Use dark colors for code blocks159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 159 158 157 156 155 154 153 152 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 151 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 216 215 214 213 212 211 210 209 208 207 206 205 204 203 202 201 200 199 198 197 196 195 194 193 192 191 190 189 188 187 186 185 184 183 182 181 180 179 178 177 176 175 174 173 172 171 170 169 168 167 166 165 164 163 162 161 160 159 158 157 156 155 154 153 152 151 150 149 148 147 146 145 144 143 142 141 140
Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun createTrailsLayer(featureServiceUri: String): FeatureLayer {
// Create simple symbol objects to represent the trails layer
val firstClassSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.fromRgba(255, 0, 255), 3.0f)
val secondClassSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.fromRgba(255, 0, 255), 4.0f)
val thirdClassSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.fromRgba(255, 0, 255), 5.0f)
val fourthClassSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.fromRgba(255, 0, 255), 6.0f)
val fifthClassSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.fromRgba(255, 0, 255), 7.0f)
// Create 5 class breaks
val firstClassBreak = ClassBreak(
description = "Under 500",
label = "0 - 500",
minValue = 0.0,
maxValue = 500.0,
symbol = firstClassSymbol
)
val secondClassBreak = ClassBreak(
description = "501 to 1000",
label = "501 - 1000",
minValue = 501.0,
maxValue = 1000.0,
symbol = secondClassSymbol
)
val thirdClassBreak = ClassBreak(
description = "1001 to 1500",
label = "1001 - 1500",
minValue = 1001.0,
maxValue = 1500.0,
symbol = thirdClassSymbol
)
val fourthClassBreak = ClassBreak(
description = "1501 to 2000",
label = "1501 - 2000",
minValue = 1501.0,
maxValue = 2000.0,
symbol = fourthClassSymbol
)
val fifthClassBreak = ClassBreak(
description = "2001 to 2300",
label = "2001 - 2300",
minValue = 2001.0,
maxValue = 2300.0,
symbol = fifthClassSymbol
)
val elevationBreaks = listOf(
firstClassBreak,
secondClassBreak,
thirdClassBreak,
fourthClassBreak,
fifthClassBreak
)
// Create and assign a class breaks renderer to the feature layer
val elevationClassBreaksRenderer = ClassBreaksRenderer("ELEV_GAIN", elevationBreaks)
// Create a trails feature layer
val featureLayer = createFeatureLayer(featureServiceUri).apply {
// Style the feature layer using the class breaks renderer
renderer = elevationClassBreaksRenderer
// Set the layer opacity to semi-transparent
opacity = 0.75f
}
return featureLayer
}
Update createMap()
to call the new createTrailsLayer()
function.
MainScreen.kt
Expand
Use dark colors for code blocks53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 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 79 79 79 79 79 79 80 81 82 83 84 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9
Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun createMap(): ArcGISMap {
val parksAndOpenSpaces =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Parks_and_Open_Space/FeatureServer/0"
val trails =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0"
val trailheads =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer/0"
val trailheadImage =
"https://static.arcgis.com/images/Symbols/NPS/npsPictograph_0231b.png"
return ArcGISMap(BasemapStyle.ArcGISTopographic).apply {
initialViewpoint = Viewpoint(
latitude = 34.0270,
longitude = -118.8050,
scale = 72000.0
)
operationalLayers.addAll(
listOf(
createOpenSpaceLayer(parksAndOpenSpaces),
createTrailsLayer(trails),
)
)
}
}
Click Run > Run > app to run the app.
When the app opens, the Trails feature layer is added to the map. The map displays trails with different symbols depending on trail elevation.
Add layers with definition expressionsYou can use a definition expression to define a subset of features to display. Features that do not meet the expression criteria are not displayed by the layer. In the following steps, you will create two methods that use a definition expression to apply a symbol to a subset of features in the Trails feature layer.
FeatureLayer.definitionExpression
uses a SQL expression to limit the features available for query and display. Your code will create two layers that each display a different subset of trails based on the value for the USE_BIKE
field. Trails that allow bikes will be symbolized with a blue symbol ("USE_BIKE = 'Yes'"
) and those that don't will be yellowred ("USE_BIKE = 'No'"
). Another way to symbolize these features would be to create a UniqueValueRenderer
that applies a different symbol for these values.
Add a top-level function named createBikeOnlyTrailsLayer()
that uses a definitionExpression
to filter for trails that permit bikes.
MainScreen.kt
Expand
Use dark colors for code blocks225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 225 224 223 222 221 220 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 235 234 233 232 231 230 229 228 227 226 225 224 223 222 221 220 219 218 217 216 215 214 213 212 211 210 209 208 207 206 205 204 203 202 201 200 199 198 197 196 195 194 193 192 191 190 189 188 187 186 185 184 183 182 181 180 179 178 177 176
Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun createBikeOnlyTrailsLayer(featureServiceUri: String): FeatureLayer {
// Create blue dot style simple line symbol to represent the bike trails
val bikeTrailSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Dot, Color.fromRgba(0, 0, 255), 2.0f)
// Create a simple renderer for the feature layer
val bikeTrailRenderer = SimpleRenderer(bikeTrailSymbol)
// Create a bike trails feature layer
val featureLayer = createFeatureLayer(featureServiceUri).apply {
// Style the feature layer using the simple renderer
renderer = bikeTrailRenderer
// Write a definition expression to filter for trails that permit the use of bikes
definitionExpression = "USE_BIKE = 'Yes'"
}
return featureLayer
}
Add another top-level function named createNoBikeTrailsLayer()
with a definition expression to filter for trails that don't allow bikes.
MainScreen.kt
Expand
Use dark colors for code blocks242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 242 241 240 239 238 237 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 252 251 250 249 248 247 246 245 244 243 242 241 240 239 238 237 236 235 234 233 232 231 230 229 228 227 226 225 224 223 222 221 220 219 218 217 216 215 214 213 212 211 210
Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun createNoBikeTrailsLayer(featureServiceUri: String): FeatureLayer {
// Create a yellow dot style simple line symbol to represent no bike trails
val noBikeTrailSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Dot, Color.fromRgba(255, 255, 0), 2.0f)
// Create a simple renderer for the feature layer
val noBikeTrailRenderer = SimpleRenderer(noBikeTrailSymbol)
// Create a no-bike trails feature layer
val featureLayer = createFeatureLayer(featureServiceUri).apply {
// Style the feature layer using the simple renderer
renderer = noBikeTrailRenderer
// Write a definition expression to filter for trails that don't permit the use of bikes
definitionExpression = "USE_BIKE = 'No'"
}
return featureLayer
}
Update createMap()
to call the new createBikeOnlyTrailsLayer()
and createNoBikeTrailsLayer()
functions.
MainScreen.kt
Expand
Use dark colors for code blocks53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 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 83 83 84 85 86 87 88 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47
Add line. Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun createMap(): ArcGISMap {
val parksAndOpenSpaces =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Parks_and_Open_Space/FeatureServer/0"
val trails =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0"
val trailheads =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer/0"
val trailheadImage =
"https://static.arcgis.com/images/Symbols/NPS/npsPictograph_0231b.png"
return ArcGISMap(BasemapStyle.ArcGISTopographic).apply {
initialViewpoint = Viewpoint(
latitude = 34.0270,
longitude = -118.8050,
scale = 72000.0
)
operationalLayers.addAll(
listOf(
createOpenSpaceLayer(parksAndOpenSpaces),
createTrailsLayer(trails),
createBikeOnlyTrailsLayer(trails),
createNoBikeTrailsLayer(trails),
)
)
}
}
Click Run > Run > app to run the app.
When the app opens, two Trails feature layers are added to the map. One shows where bikes are permitted and the other where they are prohibited.
Symbolize a layer with a picture symbol and label features with an attributeCreate a method to style trailheads with hiker images and labels for the Trailheads feature layer.
Feature layers, graphics overlays, and map image layer sublayers in your app can be labeled using a combination of attribute values, text strings, and values calculated with an expression. You can determine how labels are positioned and prioritized, and how conflicts between overlapping labels are automatically and dynamically resolved.
For feature layers, graphics overlays, and map image sublayers, labeling is implemented using a collection of LabelDefinition
objects to define what labels look like (font, size, color, angle, and so on), the scale at which they display, the text they contain, how they handle overlaps, and so on.
If you want to label everything in your layer or overlay to look identical, you can define a single label definition. If you want to use different label formatting for different attribute values, you can add as many label definitions as you need to define distinct sets of geoelements for labeling.
Add a top-level function named createTrailheadsLayer()
.
Use a PictureMarkerSymbol
to draw a trailhead hiker image. Use the LabelDefinition
to label each trailhead by its name.
In this code, you create a LabelDefinition
by calling makeLabelDefinition()
, a function you will define in the next step.
MainScreen.kt
Expand
Use dark colors for code blocks259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 259 258 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 280 279 278 277 276 275 274 273 272 271 270 269 268 267 266 265 264 263 262
Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun createTrailheadsLayer(featureServiceUri: String, trailheadImage: String): FeatureLayer {
// Create a new picture marker symbol that uses the trailhead image
val pictureMarkerSymbol = PictureMarkerSymbol(trailheadImage).apply {
height = 18.0f
width = 18.0f
}
// Create a new simple renderer based on the picture marker symbol
val simpleRenderer = SimpleRenderer(pictureMarkerSymbol)
// Create the label definition
val trailHeadsDefinition = makeLabelDefinition(labelAttribute = "TRL_NAME")
// Create a trail heads feature layer
val featureLayer: FeatureLayer = createFeatureLayer(featureServiceUri).apply {
// Style the feature layer using the simple renderer
renderer = simpleRenderer
// Set labeling on the layer to be enabled
labelsEnabled = true
// Add the label definition to the layer's label definition collection
labelDefinitions.add(trailHeadsDefinition)
}
return featureLayer
}
Create a top-level function named makeLabelDefinition()
that defines a label definition based on the passed in feature layer attribute. This helper function will also define the label placement and text symbol.
MainScreen.kt
Expand
Use dark colors for code blocks283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 283 282 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line. Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun makeLabelDefinition(labelAttribute: String): LabelDefinition {
// Create a text symbol for the label definition
val labelTextSymbol = TextSymbol().apply {
color = Color.white
size = 12.0f
haloColor = Color.red
haloWidth = 1.0f
fontFamily = "Arial"
fontStyle = FontStyle.Italic
fontWeight = FontWeight.Normal
}
// Create an Arcade label expression based on the field name
val labelExpression = ArcadeLabelExpression("\$feature.$labelAttribute")
// Create and return the label definition
return LabelDefinition(labelExpression, labelTextSymbol)
}
Update createMap()
to call the new createTrailheadsLayer()
function.
MainScreen.kt
Expand
Use dark colors for code blocks53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 53 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 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91 91
Add line.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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
fun createMap(): ArcGISMap {
val parksAndOpenSpaces =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Parks_and_Open_Space/FeatureServer/0"
val trails =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trails/FeatureServer/0"
val trailheads =
"https://services3.arcgis.com/GVgbJbqm8hXASVYi/arcgis/rest/services/Trailheads/FeatureServer/0"
val trailheadImage =
"https://static.arcgis.com/images/Symbols/NPS/npsPictograph_0231b.png"
return ArcGISMap(BasemapStyle.ArcGISTopographic).apply {
initialViewpoint = Viewpoint(
latitude = 34.0270,
longitude = -118.8050,
scale = 72000.0
)
operationalLayers.addAll(
listOf(
createOpenSpaceLayer(parksAndOpenSpaces),
createTrailsLayer(trails),
createBikeOnlyTrailsLayer(trails),
createNoBikeTrailsLayer(trails),
createTrailheadsLayer(trailheads, trailheadImage)
)
)
}
}
Click Run > Run > app to run the app.
When the app opens, all the layers you've created and symbolized are displayed on the map.
Alternatively, you can download the tutorial solution, as follows.
Option 2: Download the solutionClick the Download solution link in the right-hand side of this page.
Unzip the file to a location on your machine.
Run Android Studio.
Go to File > Open.... Navigate to the solution folder and click Open.
On Windows: If you are in the Welcome to Android Studio dialog, click Open and navigate to the solution folder. Then click Open.
Since the downloaded solution does not contain authentication credentials, you must first set up authentication to create credentials, and then add the developer credentials to the solution.
Set up authenticationTo access the secure ArcGIS location services used in this tutorial, you must implement API key authentication or user authentication using an ArcGIS Location Platform or an ArcGIS Online account.
You can implement API key authentication or user authentication in this tutorial. Compare the differences below:
API key authentication
Learn more in API key authentication.
User authentication
Learn more in User authentication.
Security and authentication guideTo learn more about the different types of authentication, visit Types of authentication.
Create a new API key access token with privileges to access the secure resources used in this tutorial.
Complete the Create an API key tutorial and create an API key with the following privilege(s):
Copy and paste the API key access token into a safe location. It will be used in a later step.
Create new OAuth credentials to access the secure resources used in this tutorial.
Complete the Create OAuth credentials for user authentication tutorial to obtain a Client ID and Redirect URL.
A Client ID
uniquely identifies your app on the authenticating server. If the server cannot find an app with the provided Client ID, it will not proceed with authentication.
The Redirect URL
(also referred to as a callback url) is used to identify a response from the authenticating server when the system returns control back to your app after an OAuth login. Since it does not necessarily represent a valid endpoint that a user could navigate to, the redirect URL can use a custom scheme, such as my-app://auth
. It is important to make sure the redirect URL used in your app's code matches a redirect URL configured on the authenticating server.
Copy and paste the Client ID and Redirect URL into a safe location. They will be used in a later step.
All users that access this application need account privileges to access the ArcGIS Basemap Styles service.
Set developer credentials in the solutionTo allow your app users to access ArcGIS location services, use the developer credentials that you created in the Set up authentication step to authenticate requests for resources.
In the Android view of Android Studio, open app > kotlin+java > com.example.app > MainActivity. Set the AuthenticationMode
to .API_KEY
.
MainActivity.kt
Expand
Use dark colors for code blocks1
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
class MainActivity : ComponentActivity() {
private enum class AuthenticationMode { API_KEY, USER_AUTH }
private val authenticationMode = AuthenticationMode.API_KEY
Set the apiKey
property with your API key access token.
MainActivity.kt
Expand
Use dark colors for code blocks1
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
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
when (authenticationMode) {
AuthenticationMode.API_KEY -> {
ArcGISEnvironment.apiKey = ApiKey.create("YOUR_ACCESS_TOKEN")
}
Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.
In the Android view of Android Studio, open app > kotlin+java > com.example.app > MainActivity. Set the AuthenticationMode
to .USER_AUTH
.
MainActivity.kt
Use dark colors for code blocks
1
2
3
4
class MainActivity : ComponentActivity() {
private enum class AuthenticationMode { API_KEY, USER_AUTH }
private val authenticationMode = AuthenticationMode.USER_AUTH
Set your clientID
and redirectURL
values. You must use the RedirectURL that you supplied for your app in the user authentication
part of the Set up authentication step.
MainActivity.kt
Expand
Use dark colors for code blocks1
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
AuthenticationMode.USER_AUTH -> {
authenticatorState.oAuthUserConfigurations = listOf(
OAuthUserConfiguration(
portalUrl = "https://www.arcgis.com",
clientId = "YOUR_CLIENT_ID",
redirectUrl = "YOUR_REDIRECT_URL"
)
)
Open app > manifests > AndroidManifest.xml.
Set the android:scheme
and android:host
using the scheme and host from your RedirectURL.
A redirectURL is composed of a scheme and a host component. The format for the redirect url is scheme://host
. For example, if the redirect url is myscheme://myhost
then the scheme is myscheme
and the host is myhost
.
AndroidManifest.xml
Expand
Use dark colors for code blocks1
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
<data
android:scheme="your_redirect_url_scheme"
android:host="your_redirect_url_host" />
Best Practice: The OAuth credentials are stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.
Run the appClick Run > Run > app to run the app.
When the app opens, all the layers you've created and symbolized are displayed on the map.
Learn how to use additional API features, ArcGIS location services, and ArcGIS tools in these tutorials:
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4