I was able to display popups in a bottom sheet. The display clusters sample pointed me in the right direction. Here is a sample of my code, note that it does not account for of every type of popup, just the ones I need for my app.
Below is my mapViewModel, on single tap I am calling identifyLayers. Then looping through the popups of the results and calling evaluateExpressions(), which will run any Arcade expressions that you have in your popups. Then store the evaluatedElements to a list of PopupElements and the title to a string.
private val _popupTitle = MutableStateFlow("")
private val _popupElements = MutableStateFlow<List<PopupElement>>(emptyList())
suspend fun onSingleTap(screenCoordinate: ScreenCoordinate) {
mapViewProxy.identifyLayers(
screenCoordinate = screenCoordinate,
tolerance = 100.dp,
returnPopupsOnly = true
).onSuccess { results ->
results.forEach { result ->
result.popups.forEach { popup ->
_popupTitle.value = popup.title
popup.evaluateExpressions().onSuccess {
_popupElements.value = popup.evaluatedElements
}
}
}
}
}
Then displaying the elements in a Column. If its a FieldsPopupElement, I'm displaying the label and formattedValues in a Row for each field. If its a MediaPopupElement and the PopupMediaType is Image, then I am displaying an AsyncImage. I'm still not fully sure the best way to show TextPopupElements, since it can be HTML (the display clusters sample handles it a differently). I haven't found a good way to handle links yet.
val popupTitle by mapViewModel.popupTitle.collectAsState()
val popupElements by mapViewModel.popupElements.collectAsState()
Column (modifier = Modifier
.fillMaxSize()
.padding(it)
.padding(start = 30.dp, end = 30.dp)) {
Text(popupTitle,
style = MaterialTheme.typography.titleLarge
)
LazyColumn {
items(popupElements) {expression ->
if (element is FieldsPopupElement) {
element.labels.forEachIndexed { index, label ->
Row (modifier = Modifier
.padding(10.dp)
.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(text = label, modifier = Modifier.weight(1f))
Text(text = element.formattedValues.get(index), modifier = Modifier.weight(1f))
}
}
}
if (element is MediaPopupElement) {
element.media.forEach { media ->
if (media.type == PopupMediaType.Image) {
AsyncImage(model = media.value?.sourceUrl, contentDescription = media.title)
}
}
}
if (element is TextPopupElement) {
AndroidView(
factory = { context ->
MaterialTextView(context).apply {
// links
autoLinkMask = Linkify.WEB_URLS
linksClickable = true
}
},
update = { a -> a.text = HtmlCompat.fromHtml(expression.text, HtmlCompat.FROM_HTML_MODE_COMPACT) }
)
}
}
}
}