Skip to main content

Customize Drop-In UI

Even though Drop-In UI comes with preset UI components arranged in a layout, you can customize it in three different ways:

  • ViewStyleCustomization: Style the default UI components supported by Drop-In UI.
  • ViewBinderCustomization: Swap the default UI components with your custom designed views.
  • ViewOptionsCustomization: Change the default values for the attributes otherwise specified by Drop-In UI.

Style UI Components

ViewStyleCustomization can be used to change the style of an existing UI component at runtime. This includes:

  • infoPanelPeekHeight: Change the peek height value of the info panel.
  • infoPanelMarginStart: Change the start margin value of the info panel.
  • infoPanelMarginEnd: Change the end margin value of the info panel.
  • infoPanelBackground: Change the background of the info panel.
  • poiNameTextAppearance: Update the text appearance of the view showing POI details.
  • destinationMarkerAnnotationOptions: Update the PointAnnotationOptions used to draw destination marker.
  • roadNameBackground: Change the background of the RoadNameView.
  • roadNameTextAppearance: Update the text appearance of the RoadNameView.
  • tripProgressStyle: Update the style of MapboxTripProgressView.
  • speedLimitStyle: Update the style of MapboxSpeedLimitView.
  • speedLimitTextAppearance: Update the text appearance of MapboxSpeedLimitView.
  • recenterButtonStyle: Update the style of MapboxExtendableButton, representing the recenter button.
  • cameraModeButtonStyle: Update the style of MapboxCameraModeButton.
  • compassButtonStyle: Update the style of MapboxExtendableButton, representing the compass button.
  • audioGuidanceButtonStyle: Update the style of MapboxAudioGuidanceButton.
  • routePreviewButtonStyle: Update the style of MapboxExtendableButton, representing the route preview button.
  • endNavigationButtonStyle: Update the style of MapboxExtendableButton, representing the end navigation button.
  • startNavigationButtonStyle: Update the style of MapboxExtendableButton, representing the start navigation button.
  • maneuverViewOptions: Update the style of MapboxManeuverView.
  • arrivalTextAppearance: Update the text appearance of the view showing arrival details.
  • locationPuckOptions: Update the location puck.

Use the following code snippet to apply runtime styling changes to MapboxRoadNameView.

Add your custom style to styles.xml or themes.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyCustomRoadNameViewTextAppearance" parent="TextAppearance.AppCompat">
<item name="android:textColor">#333333</item>
<item name="android:textSize">16sp</item>
<item name="android:textStyle">bold</item>
</style>
</resources>

Create your custom background drawable:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:radius="30dp" />
<solid android:color="#FFFFFF" />
<stroke android:color="#EDEDED" android:width="1dp" />
</shape>

In your Activity or Fragment, invoke the function to change the appearance any time:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.your_layout)
findViewById<NavigationView>(R.id.navigationView).customizeViewStyles {
roadNameBackground = R.drawable.my_custom_drawable
roadNameTextAppearance = R.style.MyCustomRoadNameViewTextAppearance
}
}
Default road name viewCustom road name view

Similarly, you can customize the other standalone UI components listed above and apply it to the NavigationView at runtime.

EXAMPLE
Custom runtime styling with NavigationView

Render custom runtime styling of default UI components to be used with the NavigationView

Customize options

NavigationView exposes options that can be used to define the behavior of the components associated with it. This includes:

  • mapStyleUriDay: Apply custom day styles to MapView.
  • mapStyleUriNight: Apply custom night styles to MapView.
  • routeLineOptions: Apply custom MapboxRouteLineOptions.
  • routeArrowOptions: Apply custom RouteArrowOptions.
  • showInfoPanelInFreeDrive: Toggle the property to show/hide info panel in free drive state.
  • enableMapLongClickIntercept: Toggle the property to handle long press events on MapView.
  • isInfoPanelHideable: Toggle the property to allow the info panel to hide completely when swiped down.
  • infoPanelForcedState: Apply BottomSheet.State to the info panel.
  • distanceFormatterOptions: Apply DistanceFormatterOptions that would be used by MapboxManeuverView.
  • showCameraDebugInfo: Toggle the property to visualize navigation camera debug window.
  • showManeuver: Toggle the property to show/hide MapboxManeuverView.
  • showSpeedLimit: Toggle the property to show/hide MapboxSpeedLimitView.
  • showRoadName: Toggle the property to show/hide MapboxRoadNameView.
  • showTripProgress: Toggle the property to show/hide MapboxTripProgressView.
  • showActionButtons: Toggle the property to show/hide all action buttons.
  • showCompassActionButton: Toggle the property to show/hide compass action button.
  • showCameraModeActionButton: Toggle the property to show/hide MapboxCameraModeButton.
  • showToggleAudioActionButton: Toggle the property to show/hide MapboxAudioGuidanceButton.
  • showRecenterActionButton: Toggle the property to show/hide the recenter action button.
  • showRoutePreviewButton: Toggle the property to show/hide the route preview button.
  • showEndNavigationButton: Toggle the property to show/hide the end navigation button.
  • showStartNavigationButton: Toggle the property to show/hide the start navigation button.

To change the appearance of the route line, define MapboxRouteLineOptions and apply it to NavigationView.

class MyActivity: AppCompatActivity() {
private val routeLineOption: MapboxRouteLineOptions by lazy {
MapboxRouteLineOptions.Builder(this)
.withRouteLineResources(
RouteLineResources.Builder()
.routeLineColorResources(
RouteLineColorResources.Builder()
.routeLowCongestionColor(Color.YELLOW)
.routeCasingColor(Color.RED)
.build()
)
.build()
)
.withRouteLineBelowLayerId("road-label") // for Style.LIGHT and Style.DARK
.withVanishingRouteLineEnabled(true)
.displaySoftGradientForTraffic(true)
.build()
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.your_activity_layout)
findViewById<NavigationView>(R.id.navigationView).customizeViewOptions {
mapStyleUriDay = Style.LIGHT
routeLineOptions = this@MyActivity.routeLineOption
}
}
}
Default route line optionsCustom route line options

Similarly, you can change the other options listed above and apply it to NavigationView at runtime.

EXAMPLE
Define options used by NavigationView

Apply ViewOptionsCustomization at runtime.

Swap UI Components with custom views

ViewBinderCustomization can be used to replace the UI components created by Drop-In UI with your own custom design. This includes:

  • maneuverBinder: Swap default MapboxManeuverView with your custom maneuver view.
  • roadNameBinder: Swap default MapboxRoadNameView with your custom road name view.
  • speedLimitBinder: Swap default MapboxSpeedLimitView with your custom speed limit view.
  • actionButtonsBinder: Swap all action buttons with your custom action buttons.
  • actionCompassButtonBinder: Swap the compass action button with your custom compass button.
  • actionRecenterButtonBinder: Swap the recenter action button with your custom recenter button.
  • actionCameraModeButtonBinder: Swap MapboxCameraModeButton with your custom camera mode button.
  • actionToggleAudioButtonBinder: Swap MapboxAudioGuidanceButton with your custom audio guidance button.
  • leftFrameBinder: Use the left frame to inject additional content below speed limit UI.
  • rightFrameBinder: Use the right frame to inject additional content below action buttons.
  • customActionButtons: Use the property to inject additional action buttons either at the start or end of existing action buttons.
  • mapViewBinder: Swap the default MapView instance with your custom MapView.
  • infoPanelBinder: Use the property to swap the default info panel with custom design.
  • infoPanelTripProgressBinder: Use the property to swap MapboxTripProgressView with your custom design.
  • infoPanelHeaderBinder: Use the property to define custom header view for the info panel. The custom view supplied here will be used.
  • infoPanelHeaderFreeDriveBinder: Use the property to define custom header view for the info panel specific to free drive state when using the default infoPanelHeaderBinder.
  • infoPanelHeaderDestinationPreviewBinder: Use the property to define custom header view for the info panel specific to destination preview state when using the default infoPanelHeaderBinder.
  • infoPanelHeaderRoutePreviewBinder: Use the property to define custom header view for the info panel specific to route preview state when using the default infoPanelHeaderBinder.
  • infoPanelHeaderActiveGuidanceBinder: Use the property to define custom header view for the info panel specific to active guidance state when using the default infoPanelHeaderBinder.
  • infoPanelHeaderArrivalBinder: Use the property to define custom header view for the info panel specific to arrival state when using the default infoPanelHeaderBinder.
  • infoPanelContentBinder: Use the property to define custom content view for the info panel.
  • infoPanelRoutePreviewButtonBinder: Swap the route preview button with your custom design.
  • infoPanelEndNavigationButtonBinder: Swap the end navigation button with your custom design.
  • infoPanelStartNavigationButtonBinder: Swap the start navigation button with your custom design.

Use the following code snippets to swap the default UI component with a custom designed view:

Define the layout for custom view

<?xml version="1.0" encoding="utf-8"?>
<merge 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:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:parentTag="android.widget.FrameLayout">

<TextView
android:id="@+id/speedLimit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textSize="18sp"
android:textColor="@android:color/black"
android:gravity="center"
android:background="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toStartOf="parent"/>
</merge>
Merge into a FrameLayout
Drop-In UI uses FrameLayout as a container to display views on top of the MapView. All UI Components and custom views are merged into the parent FrameLayout, each of which has a specific bound set on the screen. For a better understanding of the bounds, refer to mapbox_navigation_view_layout.

Create a UIComponent

UIComponent is an interface that gives you access to MapboxNavigation and coroutineScope. When the UIComponent is attached and detached from the binder, it invokes onAttached and onDetached respectively. All coroutines that you launch in onAttached are canceled automatically when the observer is detached which means you don't have to explicitly override onDetached in your custom UIComponent. This is where you add your business logic and wire the data to the custom view. For example, you can register to RouteProgressObserver using mapboxNavigation and extract the necessary data points from it.

class MySpeedLimitComponent(
private val speedLimit: MySpeedLimitLayoutBinding
) : UIComponent() {

override fun onAttached(mapboxNavigation: MapboxNavigation) {
super.onAttached(mapboxNavigation)
mapboxNavigation.flowLocationMatcherResult().collect {
val postedSpeedLimit = it.speedLimit?.speedKmph

textView.text = when {
postedSpeedLimit != null -> "Speed Limit\n $postedSpeedLimit"
else -> "--"
}
}
}
}

Create a UIBinder

UIBinder is an interface responsible for transitioning view(s) into ViewGroup.

@OptIn(ExperimentalPreviewMapboxNavigationAPI::class)
private class MySpeedLimitViewBinder : UIBinder {
override fun bind(viewGroup: ViewGroup): MapboxNavigationObserver {
val scene = Scene.getSceneForLayout(
viewGroup,
R.layout.my_speed_limit_layout,
viewGroup.context
)
TransitionManager.go(scene, Fade())

val binding = MySpeedLimitLayoutBinding.bind(viewGroup)
return MySpeedLimitComponent(binding)
}
}

The function bind defines the transition of speed limit view into the viewGroup using a Fade transition. You can choose to inflate your custom layout or opt in for a different transition based on app requirements.

Finally, apply your custom view binder to NavigationView

class MyActivity: AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.your_activity_layout)
findViewById<NavigationView>(R.id.navigationView).customizeViewBinders {
speedLimitBinder = MySpeedLimitViewBinder()
}
}
}
Default speed limitCustom speed limit

Similarly, you can replace the other UI components listed above with your custom designs and apply it to the NavigationView at runtime.

EXAMPLE
Custom speed limit with NavigationView

Render custom speed limit view to be used with the NavigationView

View Injection

There can be use cases where you want to use the Drop-In UI in a mostly default state, but also use a few additional capabilities. For example, if you are a logistics company, you might want to add delivery instructions for your driver, or if you are an automotive company, you might want to add controls that enable drivers to zoom in and out. Drop-In UI exposes these capabilities using:

  • ViewBinderCustomization.infoPanelContentBinder
  • ViewBinderCustomization.leftFrameBinder
  • ViewBinderCustomization.rightFrameBinder

These are additional empty frames where Drop-In UI doesn't add any content by default, but enables you to add any custom view to the hierarchy.

Use the following code snippets to inject a custom view:

Define the layout for custom view

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:parentTag="android.widget.FrameLayout">

<TextView
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:textSize="18sp"
android:textColor="#616161"
android:visibility="gone"
tools:visibility="visible"
android:text="Leave the parcel at my doorstep"
/>
</merge>

Create a UIComponent

The content is only visible once the user enters the ActiveNavigation state.

class MyInfoPanelContentComponent(private val content: TextView) : UIComponent() {

override fun onAttached(mapboxNavigation: MapboxNavigation) {
super.onAttached(mapboxNavigation)
mapboxNavigation.flowRoutesUpdated().observe {
content.isVisible = it.navigationRoutes.isNotEmpty()
}
}
}

Create a UIBinder

class MyInfoPanelContentBinder : UIBinder {
override fun bind(viewGroup: ViewGroup): MapboxNavigationObserver {
val scene = Scene.getSceneForLayout(
viewGroup,
R.layout.mapbox_info_panel_content_layout,
viewGroup.context
)
TransitionManager.go(scene, Fade())

val binding = MapboxInfoPanelContentLayoutBinding.bind(viewGroup)
return MyInfoPanelContentComponent(binding.content)
}
}

Finally, inject your custom binder to the Drop-In UI.

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.your_activity_layout)

findViewById<NavigationView>(R.id.navigationView).customizeViewBinders {
infoPanelContentBinder = MyInfoPanelContentBinder()
}
}
EXAMPLE
Inject a custom view to NavigationView

Render custom view to the info panel with NavigationView.

Was this page helpful?