DEV Community

Erwin Soekianto for Mapbox

Posted on • Edited on

Quick Tip: Dynamic Speed Units in Mapbox Navigation SDK for Android

Hi everyone! I’m Erwin, the newest Developer Evangelist at Mapbox. As I explore our SDKs, I’m focused on making our samples more flexible and easier to implement.

Today, I’m sharing how to add a real-time MPH/KMH toggle to our Render speed limit for a route sample. This implementation is based on the Localization & internationalization guide in our docs.

See the unit in speed limit sign changing between mph and kph

The Implementation

In the Mapbox Navigation SDK for Android, the speed units are determined by the unitType passed via DistanceFormatterOptions. To make it dynamic, we cache the last location result to refresh the UI instantly.

You can view the full source code changes for this enhancement in this commit on GitHub.

1. Updating the Layout

First, we add a simple button to our layout to trigger the unit switch.

<androidx.appcompat.widget.AppCompatButton
    android:id="@+id/toggleUnitButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Toggle Unit"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
Enter fullscreen mode Exit fullscreen mode

2. The Toggle Logic

Rebuild your options and trigger a refresh using the cached LocationMatcherResult:

private var lastLocationMatcherResult: LocationMatcherResult? = null

binding.toggleUnitButton.setOnClickListener {
    val newUnit = if (distanceFormatterOptions.unitType == UnitType.METRIC) 
                    UnitType.IMPERIAL else UnitType.METRIC

    distanceFormatterOptions = distanceFormatterOptions.toBuilder()
        .unitType(newUnit)
        .build()

    // Immediate UI refresh
    lastLocationMatcherResult?.let { updateSpeedLimit(it) }
}
Enter fullscreen mode Exit fullscreen mode

3. Updating the View

Pass the updated options into the MapboxSpeedInfoApi to get the correctly formatted speed "sign" data:

private fun updateSpeedLimit(locationMatcherResult: LocationMatcherResult) {
    val info = speedInfoApi.updatePostedAndCurrentSpeed(
        locationMatcherResult,
        distanceFormatterOptions
    )
    if (info != null) {
        binding.speedLimitView.isVisible = true
        binding.speedLimitView.render(info)
    } else {
        binding.speedLimitView.isVisible = false
    }
}
Enter fullscreen mode Exit fullscreen mode

Why it matters

Localization isn't just a "set and forget" feature. Providing a seamless way to switch units enhances the driving experience for users crossing borders or those with specific personal preferences.
For a deeper dive into localization, check out our full documentation here. Expect more tips as I continue my journey with the Mapbox ecosystem!

Top comments (0)