Display a Popup on Marker Click
This tutorial shows how to display custom popup windows when users tap on markers in your MapMetrics Android map.
Prerequisites
- Completed the Getting Started Guide
- A MapMetrics API key and style URL from the MapMetrics Portal
Basic Marker with Info Window
The simplest way to show a popup is using the built-in marker title and snippet:
kotlin
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import org.maplibre.android.MapMetrics
import org.maplibre.android.annotations.MarkerOptions
import org.maplibre.android.camera.CameraPosition
import org.maplibre.android.geometry.LatLng
import org.maplibre.android.maps.MapView
import org.maplibre.android.maps.MapMetricsMap
import org.maplibre.android.maps.Style
class PopupActivity : AppCompatActivity() {
private lateinit var mapView: MapView
private lateinit var map: MapMetricsMap
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_map)
mapView = findViewById(R.id.mapView)
mapView.onCreate(savedInstanceState)
mapView.getMapAsync { mapMetricsMap ->
map = mapMetricsMap
map.setStyle(
Style.Builder().fromUri(
"https://gateway.mapmetrics.org/styles/YOUR_STYLE_ID?token=YOUR_API_KEY"
)
) {
// Add a marker with popup content
map.addMarker(
MarkerOptions()
.position(LatLng(48.8584, 2.2945))
.title("Eiffel Tower")
.snippet("Paris, France — Built in 1889")
)
// Move camera to the marker
map.cameraPosition = CameraPosition.Builder()
.target(LatLng(48.8584, 2.2945))
.zoom(14.0)
.build()
}
}
}
override fun onStart() { super.onStart(); mapView.onStart() }
override fun onResume() { super.onResume(); mapView.onResume() }
override fun onPause() { super.onPause(); mapView.onPause() }
override fun onStop() { super.onStop(); mapView.onStop() }
override fun onDestroy() { super.onDestroy(); mapView.onDestroy() }
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView.onSaveInstanceState(outState)
}
}Multiple Markers with Popups
Add several markers with different popup content:
kotlin
map.setStyle(
Style.Builder().fromUri(
"https://gateway.mapmetrics.org/styles/YOUR_STYLE_ID?token=YOUR_API_KEY"
)
) { style ->
val places = listOf(
Triple(LatLng(48.8584, 2.2945), "Eiffel Tower", "324m tall iron lattice tower"),
Triple(LatLng(48.8606, 2.3376), "Louvre Museum", "World's largest art museum"),
Triple(LatLng(48.8530, 2.3499), "Notre-Dame", "Medieval Catholic cathedral"),
Triple(LatLng(48.8738, 2.2950), "Arc de Triomphe", "Honors those who fought for France"),
)
for ((position, title, description) in places) {
map.addMarker(
MarkerOptions()
.position(position)
.title(title)
.snippet(description)
)
}
// Fit camera to show all markers
val bounds = org.maplibre.android.geometry.LatLngBounds.Builder()
for ((position, _, _) in places) {
bounds.include(position)
}
map.easeCamera(
org.maplibre.android.camera.CameraUpdateFactory.newLatLngBounds(
bounds.build(), 100
),
1000
)
}Popup on Map Click
Show a popup when the user taps anywhere on the map:
kotlin
map.setStyle(
Style.Builder().fromUri(
"https://gateway.mapmetrics.org/styles/YOUR_STYLE_ID?token=YOUR_API_KEY"
)
) { style ->
var currentMarker: org.maplibre.android.annotations.Marker? = null
map.addOnMapClickListener { latLng ->
// Remove previous marker
currentMarker?.let { map.removeMarker(it) }
// Add new marker with coordinates as popup
currentMarker = map.addMarker(
MarkerOptions()
.position(latLng)
.title("Tapped Location")
.snippet(
"Lat: ${String.format("%.6f", latLng.latitude)}\n" +
"Lng: ${String.format("%.6f", latLng.longitude)}"
)
)
// Show the info window immediately
currentMarker?.showInfoWindow(map, mapView)
true // consume the event
}
}Custom Info Window Adapter
Create a fully custom popup layout:
kotlin
import android.view.LayoutInflater
import android.view.View
import android.widget.TextView
import org.maplibre.android.maps.MapMetricsMap.InfoWindowAdapter
// Set custom adapter
map.setInfoWindowAdapter(object : InfoWindowAdapter {
override fun getInfoWindow(marker: org.maplibre.android.annotations.Marker): View {
val view = LayoutInflater.from(this@PopupActivity)
.inflate(R.layout.custom_info_window, null)
val title = view.findViewById<TextView>(R.id.info_title)
val snippet = view.findViewById<TextView>(R.id.info_snippet)
title.text = marker.title
snippet.text = marker.snippet
return view
}
})Custom layout XML (res/layout/custom_info_window.xml):
xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="12dp"
android:background="@drawable/info_window_bg">
<TextView
android:id="@+id/info_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#333333" />
<TextView
android:id="@+id/info_snippet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textColor="#666666"
android:layout_marginTop="4dp" />
</LinearLayout>Info Window Events
Listen for clicks on the info window popup:
kotlin
// Click on info window
map.setOnInfoWindowClickListener { marker ->
// Navigate to detail screen, open URL, etc.
Toast.makeText(
this,
"Clicked: ${marker.title}",
Toast.LENGTH_SHORT
).show()
}
// Info window opens
map.setOnInfoWindowLongClickListener { marker ->
Toast.makeText(
this,
"Long pressed: ${marker.title}",
Toast.LENGTH_SHORT
).show()
}
// Info window closes
map.setOnInfoWindowCloseListener { marker ->
// Cleanup or state updates
}Next Steps
- Add Markers — Marker basics and icons
- Fly to a Location — Camera animation to a point
- GeoJSON Guide — Loading map data from GeoJSON
Tip: Info windows only support one open at a time — tapping a new marker automatically closes the previous popup. For multiple simultaneous popups, use a symbol layer with custom label text instead.