Building Production-Ready Navigation with the Mapbox UX Framework for Android

Overview

Building a navigation app from scratch is a massive undertaking. Traditionally, developers had to manually coordinate route fetching, camera transitions, voice instructions, and complex UI states. The

offers a "Core SDK" for total control, but for most production teams, the
UX Framework
(or UXF) is the real power move. UXF provides a set of flexible UI components and pre-defined user flows built on top of
Mapbox
services. It handles the heavy lifting of state management, allowing you to deploy a production-ready solution for vehicles, tablets, or phones on day one.

Prerequisites

To follow this guide, you should be comfortable with

and
Kotlin
. Since the framework now utilizes modern UI toolkits, familiarity with
Jetpack Compose
is highly recommended for customization. You also need a
Mapbox
account to generate two specific tokens:

  • Public Token: Used for accessing map tiles and direction services.
  • Secret Token: Required to download SDK dependencies from the private Mapbox Maven repository.

Key Libraries & Tools

  • UX Framework (Dash): The primary high-level library containing pre-built UI components like search bars, guidance banners, and maneuver lists.
  • Core SDK: The underlying engine that handles routing logic and map rendering.
  • Configuration API: A tool for toggling features like 3D mode or street labels without writing custom UI code.
  • Customization API: The interface for overriding default styles, icons, and fonts or injecting custom
    Jetpack Compose
    views.
  • Coordination API: Allows developers to programmatically manipulate the navigation state through the DashController.
Building Production-Ready Navigation with the Mapbox UX Framework for Android
Building with the Navigation UX Framework on Android

Code Walkthrough

1. Initializing the Framework

Unlike the Core SDK, which requires manual assembly, the UXF (internally referred to as Dash) is initialized globally within your Application class. This ensures the navigation services are ready before the user ever sees a map.

// In your Application class
override fun onCreate() {
    super.onCreate()
    // Dash is the internal shorthand for the UX Framework
    dashInit(
        context = this,
        accessToken = getString(R.string.mapbox_access_token)
    )
}

2. Implementing the Navigation Fragment

To display the interface, you instantiate the DashNavigationFragment. This single fragment handles the transition between different navigation states: Free Drive, Search, Preview, and Active Guidance.

// In your MainActivity
val navigationFragment = DashNavigationFragment()
supportFragmentManager.beginTransaction()
    .replace(R.id.container, navigationFragment)
    .commit()

3. Configuring Features with the UI Builder

You can modify the default behavior using the UIBuilder. For example, enabling a 3D perspective toggle in the camera controller requires only a few lines within a lambda after the initialization call.

UIBuilder {
    // Enable the 3D perspective option in the camera toggle button
    freeDriveCamera3DModeEnabled = true
    
    // Always show the current street name at the bottom of the screen
    streetLabelState = StreetLabelState.ALWAYS
}

4. Customizing UI with Jetpack Compose

The true strength of UXF lies in its extensibility. If you want to replace the standard search panel with a custom one, you use the setSearchPanel method on the DashFragment. This allows you to inject

code directly into the framework's layout.

navigationFragment.setSearchPanel { modifier, state ->
    // Custom Compose Row replacing the default search bar
    Row(modifier = modifier) {
        IconButton(onClick = { state.onHomeClick() }) {
            Icon(Icons.Default.Home, contentDescription = "Home")
        }
        IconButton(onClick = { 
            // Use DashController to trigger specific internal actions
            dashController.openSearch(query = "Coffee") 
        }) {
            Icon(Icons.Default.ShoppingCart, contentDescription = "Search Coffee")
        }
    }
}

Syntax Notes

  • Dash Naming Convention: Throughout the API, you will see the prefix dash (e.g., dashInit, DashController). This is the internal name for the UX Framework.
  • Lambda Configuration: The SDK uses a DSL-style configuration pattern. By passing a lambda to UIBuilder, you are interacting with a singleton state that the fragments observe.
  • State Hoisting: When overriding UI components, the framework provides a state object. This object contains necessary callbacks (like onHomeClick) so your custom UI can still trigger standard navigation behaviors.

Practical Examples

  • Multi-Stop Routing: The UXF includes a built-in "Edit Trip" state. Users can tap a pencil icon to reorder waypoints, such as moving a gas station stop before a coffee shop stop, and the framework automatically recalculates the route.
  • Contextual Search: When approaching a destination like an airport, the search tool can prioritize specific terminals or parking lots rather than generic results.
  • EV Routing: The framework can be configured to display charging stations and monitor battery levels if integrated with vehicle data.

Tips & Gotchas

  • Core vs. UXF: Do not try to mix
    Mapbox
    Core SDK components with UXF components for the same feature. If you use UXF for guidance, let it handle the routing. While you can call Core APIs for low-level data, the UI state is best managed by the UXF to avoid synchronization bugs.
  • Token Security: Always store your Secret Token in a local.properties file. Never hardcode it in your build.gradle or commit it to version control, as it grants access to paid Mapbox downloads.
  • Form Factors: UXF is responsive. The same code used for a 10-inch vehicle head unit will automatically adjust its layout for a vertical smartphone screen, though you should test specific touch targets on smaller devices.
5 min read