Many web maps contain predefined popups which are used to display the attributes associated with each feature layer in the map, such as hiking trails, land values, or unemployment rates. You can display text, attachments, images, charts, and web links. Rather than creating new popups to display information, you can easily access and display the predefined popups.
How to use the sample
Tap on the features to prompt a popup that displays information about the feature.
How it works
Create and load an ArcGISMap using a URL.
Set the map to a MapView and add an onTouchListener.
Use the MapView.identifyLayerAsync() method to identify the top-most feature.
Attach the Popup from identifyLayerResultsFuture.get() to the PopupViewModel
Present the view controller.
Relevant API
IdentifyLayerResult
ArcGISMap
PopupViewModel
About the data
This sample uses a feature layer that displays reported incidents in San Francisco.
Tags
feature, feature layer, popup, web map
Sample Code
MainActivity.ktMainActivity.ktPopupFragment.kt
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
/* Copyright 2021 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
*
* http://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.
*
*/package com.esri.arcgisruntime.sample.showpopup
import android.os.Bundle
import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.widget.ProgressBar
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import com.esri.arcgisruntime.ArcGISRuntimeEnvironment
import com.esri.arcgisruntime.data.Feature
import com.esri.arcgisruntime.geometry.GeometryType
import com.esri.arcgisruntime.layers.FeatureLayer
import com.esri.arcgisruntime.mapping.ArcGISMap
import com.esri.arcgisruntime.mapping.view.DefaultMapViewOnTouchListener
import com.esri.arcgisruntime.mapping.view.MapView
import com.esri.arcgisruntime.portal.Portal
import com.esri.arcgisruntime.portal.PortalItem
import com.esri.arcgisruntime.sample.showpopup.databinding.ActivityMainBinding
import com.esri.arcgisruntime.toolkit.popup.PopupViewModel
import com.esri.arcgisruntime.toolkit.util.observeEvent
import com.google.android.material.bottomsheet.BottomSheetBehavior
import kotlin.math.roundToInt
classMainActivity : AppCompatActivity() {
privateval TAG: String = MainActivity::class.java.simpleName
privatelateinitvar bottomSheetBehavior: BottomSheetBehavior<View>
privatelateinitvar mapView: MapView
privatelateinitvar progressBar: ProgressBar
privatelateinitvar map: ArcGISMap
privateval popupViewModel: PopupViewModel by viewModels()
/**
* getter function to retrieve the first available feature layer
* [featureLayer] updates with every map click
*/privateval featureLayer: FeatureLayer?
get() {
return map.operationalLayers?.filterIsInstance<FeatureLayer>()?.first {
(it.featureTable?.geometryType == GeometryType.POINT)
.and(it.isVisible)
.and(it.isPopupEnabled && it.popupDefinition != null)
}
}
overridefunonCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// authentication with an API key or named user is required to access basemaps and other// location services ArcGISRuntimeEnvironment.setApiKey(BuildConfig.API_KEY)
val binding: ActivityMainBinding =
DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.lifecycleOwner = thisval portal = Portal("https://arcgisruntime.maps.arcgis.com/")
val portalItem = PortalItem(portal, "fb788308ea2e4d8682b9c05ef641f273")
map = ArcGISMap(portalItem)
// set up binding and UI behaviour mapView = binding.mapView
mapView.map = map
progressBar = binding.progressBar
bottomSheetBehavior = BottomSheetBehavior.from(binding.bottomSheetContainer)
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
// reset the IdentifyResult on a sheet close bottomSheetBehavior.addBottomSheetCallback(object :
BottomSheetBehavior.BottomSheetCallback() {
overridefunonStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
// Clear the selected features from the feature layer resetIdentifyResult()
}
}
overridefunonSlide(bottomSheet: View, slideOffset: Float) {
}
})
popupViewModel.dismissPopupEvent.observeEvent(this) {
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
// Clear the selected features from the feature layer resetIdentifyResult()
}
// set the progressBar visibility progressBar.visibility = View.GONE
mapView.onTouchListener =
object : DefaultMapViewOnTouchListener(this, mapView) {
overridefunonSingleTapConfirmed(event: MotionEvent): Boolean {
// set the progressBar visibility progressBar.visibility = View.VISIBLE
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
val screenPoint = android.graphics.Point(
event.x.roundToInt(),
event.y.roundToInt()
)
// setup identifiable layer at the given screen point. identifyLayer(screenPoint)
returntrue }
}
}
/**
* Performs an identify on the feature layer at the given screen point.
* [screenPoint] in Android graphic coordinates.
*/privatefunidentifyLayer(screenPoint: android.graphics.Point) {
featureLayer?.let {
// clear the selected features from the feature layer resetIdentifyResult()
val identifyLayerResultsFuture = mapView
.identifyLayerAsync(featureLayer, screenPoint, 12.0, true)
identifyLayerResultsFuture.addDoneListener {
try {
val identifyLayerResult = identifyLayerResultsFuture.get()
if (identifyLayerResult.popups.isNotEmpty()) {
popupViewModel.setPopup(identifyLayerResult.popups.first())
val featureLayer: FeatureLayer? =
identifyLayerResult.layerContent as? FeatureLayer
featureLayer?.selectFeature(identifyLayerResult.popups.first().geoElement as Feature)
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HALF_EXPANDED
}
} catch (e: Exception) {
val error = "Error identifying results ${e.message}" Log.e(TAG, error)
Toast.makeText(this, error, Toast.LENGTH_SHORT).show()
}
// set the progressBar visibility progressBar.visibility = View.GONE
}
}
}
/**
* Resets the Identify Result.
*/privatefunresetIdentifyResult() {
featureLayer?.clearSelection()
popupViewModel.clearPopup()
}
overridefunonPause() {
mapView.pause()
super.onPause()
}
overridefunonResume() {
super.onResume()
mapView.resume()
}
overridefunonDestroy() {
mapView.dispose()
super.onDestroy()
}
}