Fit Map to a Bounding Box
This tutorial shows how to automatically zoom and position your MapMetrics Android map to fit a set of points, markers, or a region.
Prerequisites
- Completed the Getting Started Guide
- A MapMetrics API key and style URL from the MapMetrics Portal
Fit to Multiple Markers
Automatically adjust the camera to show all markers:
kotlin
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import org.maplibre.android.annotations.MarkerOptions
import org.maplibre.android.camera.CameraUpdateFactory
import org.maplibre.android.geometry.LatLng
import org.maplibre.android.geometry.LatLngBounds
import org.maplibre.android.maps.MapView
import org.maplibre.android.maps.MapMetricsMap
import org.maplibre.android.maps.Style
class FitBoundsActivity : AppCompatActivity() {
private lateinit var mapView: MapView
private lateinit var map: MapMetricsMap
private val cities = listOf(
Pair(LatLng(48.8566, 2.3522), "Paris"),
Pair(LatLng(51.5074, -0.1278), "London"),
Pair(LatLng(52.5200, 13.4050), "Berlin"),
Pair(LatLng(41.9028, 12.4964), "Rome"),
Pair(LatLng(40.4168, -3.7038), "Madrid"),
)
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"
)
) { style ->
addMarkersAndFit()
}
}
}
private fun addMarkersAndFit() {
// Add markers
val boundsBuilder = LatLngBounds.Builder()
for ((position, name) in cities) {
map.addMarker(
MarkerOptions()
.position(position)
.title(name)
)
boundsBuilder.include(position)
}
// Fit camera to show all markers with padding
map.easeCamera(
CameraUpdateFactory.newLatLngBounds(
boundsBuilder.build(),
100 // padding in pixels
),
1000 // animation duration
)
}
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)
}
}Fit to a Predefined Region
Zoom to specific geographic regions with buttons:
kotlin
import android.widget.Button
private val regions = mapOf(
"Europe" to LatLngBounds.Builder()
.include(LatLng(71.0, -25.0)) // Northwest
.include(LatLng(35.0, 45.0)) // Southeast
.build(),
"North America" to LatLngBounds.Builder()
.include(LatLng(72.0, -170.0))
.include(LatLng(15.0, -50.0))
.build(),
"Asia" to LatLngBounds.Builder()
.include(LatLng(55.0, 25.0))
.include(LatLng(-10.0, 150.0))
.build(),
)
private fun setupRegionButtons() {
findViewById<Button>(R.id.btnEurope).setOnClickListener {
fitToRegion("Europe")
}
findViewById<Button>(R.id.btnNorthAmerica).setOnClickListener {
fitToRegion("North America")
}
findViewById<Button>(R.id.btnAsia).setOnClickListener {
fitToRegion("Asia")
}
}
private fun fitToRegion(name: String) {
regions[name]?.let { bounds ->
map.animateCamera(
CameraUpdateFactory.newLatLngBounds(bounds, 50),
2000
)
}
}Fit Bounds with Custom Padding
Use different padding per edge for UI elements:
kotlin
// Different padding for each side: [left, top, right, bottom]
val paddingPixels = intArrayOf(50, 200, 50, 100) // extra top for header
val cameraPosition = map.getCameraForLatLngBounds(
boundsBuilder.build(),
paddingPixels
)
cameraPosition?.let {
map.animateCamera(
CameraUpdateFactory.newCameraPosition(it),
1500
)
}Fit to Route Points
Zoom to fit a polyline route:
kotlin
import org.maplibre.geojson.LineString
import org.maplibre.geojson.Point
private fun fitToRoute() {
val routePoints = listOf(
LatLng(48.8566, 2.3522), // Paris
LatLng(50.8503, 4.3517), // Brussels
LatLng(52.3676, 4.9041), // Amsterdam
LatLng(53.5511, 9.9937), // Hamburg
LatLng(52.5200, 13.4050), // Berlin
)
val bounds = LatLngBounds.Builder()
for (point in routePoints) {
bounds.include(point)
}
map.animateCamera(
CameraUpdateFactory.newLatLngBounds(bounds.build(), 80),
2000
)
}Fit Bounds Options
| Parameter | Type | Description |
|---|---|---|
bounds | LatLngBounds | Southwest + northeast corners to fit |
padding | Int | Equal padding on all sides (pixels) |
padding | IntArray | Per-side padding: [left, top, right, bottom] |
duration | Int | Animation duration in milliseconds |
Animation Methods for Bounds
| Method | Behavior |
|---|---|
moveCamera() | Instant jump to bounds |
easeCamera() | Constant-speed animation |
animateCamera() | Natural ease-in/ease-out |
Next Steps
- Lat-Lng Bounds — Bounds API deep dive
- Zoom Methods — Zoom controls
- Fly to a Location — Point-to-point animation
Tip: Always add padding (50-100px minimum) when fitting bounds so markers at the edge aren't clipped by the screen boundary. For maps with floating UI panels, use per-side padding to account for the panel area.