Skip to content

Configuration

This guide will explain various ways to create a map.

When working with maps, you likely want to configure the MapView.

There are several ways to build a MapView:

  1. Using existing XML namespace tags forMapView in the layout.
  2. Creating MapMetricsMapOptions and passing builder function values into the MapView.
  3. Creating a SupportMapFragment with the help of MapMetricsMapOptions.

Before diving into MapView configurations, let's understand the capabilities of both XML namespaces and MapMetricsMapOptions.

Here are some common configurations you can set:

  • Map base URI
  • Camera settings
  • Zoom level
  • Pitch
  • Gestures
  • Compass
  • Logo
  • Attribution
  • Placement of the above elements on the map and more

We will explore how to achieve these configurations in XML layout and programmatically in Activity code, step by step.

MapView Configuration with an XML layout

To configure MapView within an XML layout, you need to use the right namespace and provide the necessary data in the layout file.

xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activity.options.MapOptionsXmlActivity">

    <org.maplibre.android.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:maplibre_apiBaseUri="https://api.maplibre.org"
        app:maplibre_cameraBearing="0.0"
        app:maplibre_cameraPitchMax="90.0"
        app:maplibre_cameraPitchMin="0.0"
        app:maplibre_cameraTargetLat="42.31230486601532"
        app:maplibre_cameraTargetLng="64.63967338936439"
        app:maplibre_cameraTilt="0.0"
        app:maplibre_cameraZoom="3.9"
        app:maplibre_cameraZoomMax="26.0"
        app:maplibre_cameraZoomMin="2.0"
        app:maplibre_localIdeographFontFamilies="@array/array_local_ideograph_family_test"
        app:maplibre_localIdeographFontFamily="Droid Sans"
        app:maplibre_uiCompass="true"
        app:maplibre_uiCompassFadeFacingNorth="true"
        app:maplibre_uiCompassGravity="top|end"
        app:maplibre_uiDoubleTapGestures="true"
        app:maplibre_uiHorizontalScrollGestures="true"
        app:maplibre_uiRotateGestures="true"
        app:maplibre_uiScrollGestures="true"
        app:maplibre_uiTiltGestures="true"
        app:maplibre_uiZoomGestures="true" />

</androidx.constraintlayout.widget.ConstraintLayout>

This can be found in activity_map_options_xml.xml.

You can assign any other existing values to the mapmetrics... tags. Then, you only need to create MapView and MapMetricsMap objects with a simple setup in the Activity.

kotlin

/**
 *  TestActivity demonstrating configuring MapView with XML
 */

class MapOptionsXmlActivity : AppCompatActivity(), OnMapReadyCallback {
    private lateinit var mapView: MapView
    private lateinit var mapMetricsMap: MapMetricsMap

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_map_options_xml)
        mapView = findViewById(R.id.mapView)
        mapView.onCreate(savedInstanceState)
        mapView.getMapAsync(this)
    }

    override fun onMapReady(mapMetricsMap: MapMetricsMap) {
        this.mapMetricsMap = mapMetricsMap
        this.mapMetricsMap.setStyle(TestStyles.getMapMetricsStyle())
    }

    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 onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        mapView.onSaveInstanceState(outState)
    }

    override fun onDestroy() {
        super.onDestroy()
        mapView.onDestroy()
    }

    override fun onLowMemory() {
        super.onLowMemory()
        mapView.onLowMemory()
    }
}

This can be found in MapOptionsXmlActivity.kt.

MapView configuration with MapMetricsMapOptions

Here we don't have to create MapView from XML since we want to create it programmatically.

xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"/>

This can be found in activity_map_options_runtime.xml.

A MapMetricsMapOptions object must be created and passed to the MapView constructor. All setup is done in the Activity code:

kotlin


/**
 *  TestActivity demonstrating configuring MapView with MapOptions
 */
class MapOptionsRuntimeActivity : AppCompatActivity(), OnMapReadyCallback {

    private lateinit var mapMetricsMap: MapMetricsMap
    private lateinit var mapView: MapView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_map_options_runtime)

        // Create map configuration
        val mapMetricsMapOptions = MapMetricsMapOptions.createFromAttributes(this)
        mapMetricsMapOptions.apply {
            apiBaseUri("https://api.maplibre.org")
            camera(
                CameraPosition.Builder()
                    .bearing(0.0)
                    .target(LatLng(42.31230486601532, 64.63967338936439))
                    .zoom(3.9)
                    .tilt(0.0)
                    .build()
            )
            maxPitchPreference(90.0)
            minPitchPreference(0.0)
            maxZoomPreference(26.0)
            minZoomPreference(2.0)
            localIdeographFontFamily("Droid Sans")
            zoomGesturesEnabled(true)
            compassEnabled(true)
            compassFadesWhenFacingNorth(true)
            scrollGesturesEnabled(true)
            rotateGesturesEnabled(true)
            tiltGesturesEnabled(true)
        }

        // Create map programmatically, add to view hierarchy
        mapView = MapView(this, mapMetricsMapOptions)
        mapView.getMapAsync(this)
        mapView.onCreate(savedInstanceState)
        (findViewById<View>(R.id.container) as ViewGroup).addView(mapView)
    }

    override fun onMapReady(mapMetricsMap: MapMetricsMap) {
        this.mapMetricsMap = mapMetricsMap
        this.mapMetricsMap.setStyle(TestStyles.getMapMetricsStyle())
    }

    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 onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        mapView.onSaveInstanceState(outState)
    }

    override fun onDestroy() {
        super.onDestroy()
        mapView.onDestroy()
    }

    override fun onLowMemory() {
        super.onLowMemory()
        mapView.onLowMemory()
    }
}

This can be found in MapOptionsRuntimeActivity.kt.

For the full contents of MapOptionsRuntimeActivity and MapOptionsXmlActivity, please take a look at the source code of MapMetricsAndroidTestApp.

You can read more about MapMetricsMapOptions in the Android API documentation.

SupportMapFragment with the help of MapMetricsMapOptions.

If you are using MapFragment in your project, it is also easy to provide initial values to the newInstance() static method of SupportMapFragment, which requires a MapMetricsMapOptions parameter.

Let's see how this can be done in a sample activity:

kotlin

/**
 * Test activity showcasing using the MapFragment API using Support Library Fragments.
 *
 *
 * Uses MapMetricsMapOptions to initialise the Fragment.
 *
 */
class SupportMapFragmentActivity :
    AppCompatActivity(),
    OnMapViewReadyCallback,
    OnMapReadyCallback,
    OnDidFinishRenderingFrameListener {
    private lateinit var mapMetricsMap: MapMetricsMap
    private lateinit var mapView: MapView
    private var initialCameraAnimation = true
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_map_fragment)
        val mapFragment: SupportMapFragment?
        if (savedInstanceState == null) {
            mapFragment = SupportMapFragment.newInstance(createFragmentOptions())
            supportFragmentManager
                .beginTransaction()
                .add(R.id.fragment_container, mapFragment, TAG)
                .commit()
        } else {
            mapFragment = supportFragmentManager.findFragmentByTag(TAG) as SupportMapFragment?
        }
        mapFragment!!.getMapAsync(this)
    }

    private fun createFragmentOptions(): MapMetricsMapOptions {
        val options = MapMetricsMapOptions.createFromAttributes(this, null)
        options.scrollGesturesEnabled(false)
        options.zoomGesturesEnabled(false)
        options.tiltGesturesEnabled(false)
        options.rotateGesturesEnabled(false)
        options.debugActive(false)
        val dc = LatLng(38.90252, -77.02291)
        options.minZoomPreference(9.0)
        options.maxZoomPreference(11.0)
        options.camera(
            CameraPosition.Builder()
                .target(dc)
                .zoom(11.0)
                .build()
        )
        return options
    }

    override fun onMapViewReady(map: MapView) {
        mapView = map
        mapView.addOnDidFinishRenderingFrameListener(this)
    }

    override fun onMapReady(map: MapMetricsMap) {
        mapMetricsMap = map
        mapMetricsMap.setStyle(TestStyles.getPredefinedStyleWithFallback("Satellite Hybrid"))
    }

    override fun onDestroy() {
        super.onDestroy()
        mapView.removeOnDidFinishRenderingFrameListener(this)
    }

    override fun onDidFinishRenderingFrame(fully: Boolean, frameEncodingTime: Double, frameRenderingTime: Double) {
        if (initialCameraAnimation && fully && this::mapMetricsMap.isInitialized) {
            mapMetricsMap.animateCamera(
                CameraUpdateFactory.newCameraPosition(CameraPosition.Builder().tilt(45.0).build()),
                5000
            )
            initialCameraAnimation = false
        }
    }

    companion object {
        private const val TAG = "com.mapbox.map"
    }
}

You can also find the full contents of SupportMapFragmentActivity in the MapMetricsAndroidTestApp.

To learn more about SupportMapFragment, please visit the Android API documentation.