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

# Map markers configuration

The Navigation SDK UX Framework is pre-built with the default map marker factory. This documentation provides an overview of how to customize pins using the `SymbolDescriptor` class and `MarkerOptions` interface. The primary focus is on creating customizable markers for different descriptors and configuring various visual properties of these markers.

## Setting Up Your Marker Factory

To set up your own marker factory through the configuration object, use the following code:

```kotlin
Dash.init(
   applicationContext = applicationContext,
   accessToken = getString(R.string.mapbox_access_token)
) {
   mapStyle {
       markerFactory = <Your marker factory implementation>
   }
}
```

Where `<Your marker factory implementation>` is an instance of the `MarkerFactory` interface.

-   `MarkerFactory` defines a contract for creating markers tailored to specific types of symbol descriptors. Implementations of this interface are responsible for generating `MarkerOptions` based on the properties of the provided symbol descriptor and its selection state.
-   `SearchSuggestionsMarkerFactory` interface provides a factory method for creating markers for search suggestions symbol descriptors.
-   `RoutePointMarkerFactory` interface provides a factory method for creating markers for route points symbol descriptors.
-   `MarkerOptions` class contains all the options for a marker, including image, text properties, and styling options. It provides fluent APIs for setting these properties.

### Example: Customizing Pins

```kotlin
private const val SCALE_FACTOR = 1.5
private const val TEXT_OFFSET_EMS = 0.5

class SampleMarkerFactory(
    private val context: Context,
) : MarkerFactory {

    private val textOffset = listOf(0.0, TEXT_OFFSET_EMS)

    /**
     * Creates a marker for search suggestions symbol descriptors.
     */
    override fun create(symbolDescriptor: SymbolDescriptorSearchSuggestions, selected: Boolean): MarkerOptions {
        return MarkerOptions()
            .withImage(symbolDescriptor.image)
            .withImageAnchor(MarkerOptions.ImageAnchor.BOTTOM)
            .withImageScaleFactorSize(if (selected) SCALE_FACTOR else 1.0)
            .withTextField("#${symbolDescriptor.index + 1}")
            .withTextAnchor(MarkerOptions.TextAnchor.BOTTOM)
            .withTextColor(Color.WHITE)
            .withTextOffset(textOffset)
            .withTextHaloColor(symbolDescriptor.haloColor)
            .withTextHaloWidth(1.0)
    }

    /**
     * Creates a marker for route point symbol descriptors.
     */
    override fun create(symbolDescriptor: SymbolDescriptorRoutePoint, selected: Boolean): MarkerOptions {
        return MarkerOptions()
            .withImage(symbolDescriptor.image)
            .withImageAnchor(MarkerOptions.ImageAnchor.BOTTOM)
            .withImageScaleFactorSize(if (selected) SCALE_FACTOR else 1.0)
            .withTextAnchor(MarkerOptions.TextAnchor.BOTTOM)
    }

    private val SymbolDescriptorSearchSuggestions.haloColor: Int
        get() {
            val hex = when {
                categories.contains(SearchCategory.Grocery) -> "#FF63A6E9"
                categories.contains(SearchCategory.Coffee) -> "#FFFF9933"
                categories.contains(SearchCategory.Food) -> "#FFFF8126"
                else -> "#FFF47BCB"
            }
            return Color.parseColor(hex)
        }

    private val SymbolDescriptorSearchSuggestions.image: MarkerOptions.Image.Bitmap
        get() {
            val resId = when {
                categories.contains(SearchCategory.Grocery) -> R.drawable.ic_grocery
                categories.contains(SearchCategory.Coffee) -> R.drawable.ic_coffee
                categories.contains(SearchCategory.Food) -> R.drawable.ic_food
                else -> R.drawable.ic_fallback
            }
            return checkNotNull(ContextCompat.getDrawable(context, resId))
                .let { MarkerOptions.Image.Bitmap(it.toBitmap()) }
        }

    private val SymbolDescriptorRoutePoint.image: MarkerOptions.Image.Bitmap
        get() {
            return when (type) {
                is SymbolDescriptorRoutePoint.Type.Destination -> checkNotNull(
                    ContextCompat.getDrawable(context, R.drawable.ic_destination)
                )

                else -> checkNotNull(
                    ContextCompat.getDrawable(context, R.drawable.ic_waypoint)
                )
            }.let { MarkerOptions.Image.Bitmap(it.toBitmap()) }

        }
}
```