> For the complete documentation index, see [llms.txt](https://docs.mapbox.com/android/navigation/ux/llms.txt)

# Route callout customization

You can customize the route callout view by providing your own UI written in Jetpack Compose.

![Custom callout](https://docs.mapbox.com/android/assets/ideal-img/dash-sdk-custom-callout.67061e0.480.png)

## Customizing Route Callout Content

The [`DashNavigationFragment#setRouteCallout`](https://docs.mapbox.com/android/navigation/api/uxframework/1.28.0/android/com.mapbox.dash.sdk/-dash-navigation-fragment/set-route-callout.html) function allows you to define custom content for route callouts. It takes an [`RouteCalloutViewsUiComposer`](https://docs.mapbox.com/android/navigation/api/uxframework/1.28.0/driver/com.mapbox.dash.driver.presentation.markers/-route-callout-views-ui-composer/), which is a composable function with one parameter - `state`. The `state` is an instance of [`RouteCalloutUiState`](https://docs.mapbox.com/android/navigation/api/uxframework/1.28.0/driver/com.mapbox.dash.driver.presentation.markers/-route-callout-ui-state/), which contains all necessary information for rendering the route callout UI.

### RouteCalloutUiState

The [`RouteCalloutUiState`](https://docs.mapbox.com/android/navigation/api/uxframework/1.28.0/driver/com.mapbox.dash.driver.presentation.markers/-route-callout-ui-state/) class provides the state needed for the route callout. It includes:

-   **callout**: route related data, represented as a [`RouteCallout`](https://docs.mapbox.com/android/navigation/api/coreframework/3.29.0/ui-maps/com.mapbox.navigation.ui.maps.route.callout.model/-route-callout/), includes the related route, flag that indicates if the related route is primary, and the data about duration difference with primary route

-   **hasTollRoad** indicates that remaining segment of the related route has toll road.
-   **isSuggested**: indicates that the related route was suggested by the navigation engine.

-   **isBest**: indicates that the related route considered as the best one (that means the navigation engine returned only one route without alternatives).
-   **isFastest**: indicates that the route is the fastest one among the set of routes returned by the navigation engine.
-   **layerId**: represents a layer id on the map which the related route is attached to.
-   **onClick**: A callback triggered when that route callout view is clicked.

### Example Usage

To set a custom route callout implementation:

```kotlin
fragment.setRouteCallout { state ->
    SampleRouteCalloutView(state, modifier)
}
```

The `SampleRouteCalloutView` composable customizes the route callout UI using the provided [`RouteCalloutUiState`](https://docs.mapbox.com/android/navigation/api/uxframework/1.28.0/driver/com.mapbox.dash.driver.presentation.markers/-route-callout-ui-state/).

A custom composable should be wrapped up into [`ViewAnnotation`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.compose.annotation/-view-annotation.html),

besides that `key` composable function should be used as a wrapper around [`ViewAnnotation`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.compose.annotation/-view-annotation.html) with parameters that affect recomposition:

```kotlin
@Composable
private fun SampleRouteCalloutViewAnnotation(
    duration: Duration,
    label: String,
    layerId: String,
    isPrimary: Boolean,
    onClick: () -> Unit,
) {
    key(
        duration,
        label,
        layerId,
        isPrimary,
    ) {
        val anchorState = remember { mutableStateOf(value = ViewAnnotationAnchor.TOP_LEFT) }
        ViewAnnotation(
            options = viewAnnotationOptions {
                ignoreCameraPadding(true)
                annotatedLayerFeature(layerId)
                annotationAnchors(
                    { anchor(ViewAnnotationAnchor.TOP_LEFT) },
                    { anchor(ViewAnnotationAnchor.TOP_RIGHT) },
                    { anchor(ViewAnnotationAnchor.BOTTOM_RIGHT) },
                    { anchor(ViewAnnotationAnchor.BOTTOM_LEFT) },
                )
            },
            onUpdatedListener = object : OnViewAnnotationUpdatedListener {
                override fun onViewAnnotationAnchorUpdated(view: View, anchor: ViewAnnotationAnchorConfig) {
                    anchorState.value = anchor.anchor
                }
            },
        ) {
            SampleRouteCalloutViewContent(
                anchor = anchorState.value,
                duration = duration,
                primary = isPrimary,
                label = label,
                onClick = onClick,
            )
        }
    }
}
```

To switch back to the default implementation at runtime:

```kotlin
fragment.setRouteCallout { state ->
    DefaultRouteCalloutView(state)
}
```

For practical examples, explore our [Dash Android Examples repository](https://github.com/mapbox/dash-android-examples).