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

# Work with sources and layers

Layers define how map features—such as roads, buildings, water, and points of interest—are visually represented in a Mapbox style. Each layer handles rendering specific data from a source, determining its appearance and behavior on the map. With the Mapbox Maps SDK for Android, developers can dynamically add, remove, and change layers to customize their map's design and functionality.

This guide covers the fundamentals of working with layers, including:

-   The relationship between sources and layers
-   Adding and updating layers at runtime
-   Controlling layer order and rendering behavior
-   Using different layer types (such as fill, line, symbol, and raster layers)
-   Understanding layers is essential for customizing a Mapbox-powered map and displaying data in a visually meaningful way.

## Add and update layers

You can use the Maps SDK to add more styled data to the map at runtime. There are two key concepts to understand when preparing to add a layer to a style at runtime: **layers** and **sources**. **Sources** contain geographic data. They determine the shape of the features you're adding to the map and where in the world they belong. **Layers** contain styling information. They determine how the data in a source should look on the map.

> **Note: Layers in Mapbox Standard**
> 
> For Mapbox Standard and Standard Satellite, you only have access to the layers that you add to the style yourself. To manipulate the Standard basemap, see the [Configure a Style](https://docs.mapbox.com/android/maps/guides/styles/set-a-style/#configure-a-style) section.

A **layer** is a styled representation of data of a single type (for example polygons, lines, or points) that make up a map style. For example, roads, city labels, and rivers would be three separate layers in a map. There are several layer types (for example fill, line, and symbol). You can read more about [layers in the Mapbox Style Specification](https://docs.mapbox.com/style-spec/reference/layers/).

Most layers also require a **source**. The source provides map data that the Maps SDK can use with a style document to render a visual representation of that data. There are several source types (for example vector tilesets, GeoJSON, and raster data). You can read more about [sources in the Mapbox Style Specification](https://docs.mapbox.com/style-spec/reference/sources/).

In the Maps SDK, the [`Style`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps/-style/) class exposes the entry point for all methods related to the style object including sources and layers.

### Rendering order

Typically, layers are displayed in the order of their declaration, with later layers appearing on top of earlier ones as rendered by the SDK. When using the [Mapbox Standard](https://docs.mapbox.com/map-styles/standard/), the display order primarily depends on the layer's [slot](https://docs.mapbox.com/style-spec/reference/slots/), while the relative order determines their arrangement within the slot. Layers not associated with slots appear above the entire map, also maintaining their relative order.

If the Globe projection or Terrain is active, the SDK optimizes performance by batching multiple layers together, which may cause layer rearrangements. Layers draped over the globe and terrain, including `fill`, `line`, `background`, `hillshade`, and `raster`, are rendered below symbols, regardless of slot placement or the absence of a designated slot.

This means that layers placed with methods such as [`addLayerAbove()`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers/add-layer-above.html), [`addLayerAt()`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers/add-layer-at.html), and [`addLayerBelow()`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers/add-layer-below.html) might not appear at the expected layer position for some layer types. If your layer is not positioned in the expected place, try disabling terrain and changing the map's projection to Mercator.

### Style domain-specific language

The Style domain-specific language (DSL) is a collection of functions that allows composition of a style in a block that is applied to a receiver class. DSL functions are provided to construct `Style`, `Layer`, `Source`, `Light`, and `Expression` classes. The DSL function names match the class name being created, but the first character in the name is lowercase (for example, the DSL function for the [`CircleLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-circle-layer/) class is [`circleLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/circle-layer.html)). In cases where there are mandatory constructor parameters of the class, assign the mandatory constructor parameters before the code block. Inside the DSL block, use code completion in Android Studio to find all available receiver functions.

With the Style DSL, authoring or updating map styles is like writing [style JSON](https://docs.mapbox.com/help/glossary/style/) directly. The higher-level style API is exposed as DSL, allowing construction of a `StyleExtension` object using the same paradigm as creating `Layer`, `Source`, and `Light` classes using DSL and using the overloaded operator and inside the Style DSL closure to add layers, sources, or light to the `StyleExtension`.

Below is an example using the Style DSL to add a [`GeoJsonSource`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.sources.generated/-geo-json-source/) and a circle layer:

**Android View**

```kotlin

mapView.mapboxMap.subscribeMapLoadingError {
  // Error occurred when loading the map, try to handle it gracefully here
}
mapView.mapboxMap.loadStyle(
  style(style = Style.TRAFFIC_DAY) {
    +geoJsonSource(id = "earthquakes") {
      data(GEOJSON_URL)
      cluster(false)
    }
    +circleLayer(layerId = "earthquakeCircle", sourceId = "earthquakes") {
      circleRadius(get { literal("mag") })
      circleColor(Color.RED)
      circleOpacity(0.3)
      circleStrokeColor(Color.WHITE)
    }
  }
) { style ->
  // Map is set up and the style has loaded. Now you can add data or make other map adjustments.
}
```

**Jetpack Compose**

```kotlin

val coroutineScope = rememberCoroutineScope()
val mapState = rememberMapState {
  coroutineScope.launch {
    mapLoadingErrorEvents.onEach {
      // Error occurred when loading the map, try to handle it gracefully here
    }
  }
  coroutineScope.launch {
    styleLoadedEvents.first().let {
      // Map is setup and style has loaded, Now you can add data or make other map adjustments.
    }
  }
}
MapboxMap(
  modifier = Modifier.fillMaxSize(),
  mapState = mapState
) {
  CircleLayer(
    sourceState = rememberGeoJsonSourceState {
      data = GeoJSONData(GEOJSON_URL)
      cluster = BooleanValue(false)
    }
  ) {
    circleRadius = DoubleValue(get { literal("mag") })
    circleColor = ColorValue(Color.Red)
    circleOpacity = DoubleValue(0.3)
    circleStrokeColor = ColorValue(Color.White)
  }
}
```

Sample code throughout this guide uses the Style DSL.

### Add a layer at runtime

To add a new layer to the map at runtime, start by adding a source using the `Style`'s [`addSource`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.sources/add-source.html) method. It is important that you add the source for a new layer *before* attempting to add the layer itself because the source is a required parameter for most layer types.

Then, you'll use the [`addLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers/add-layer.html) method to add the layer to the style. When adding the style layer, you will specify:

-   A unique ID that you assign to the new layer
-   The layer type (for example fill, line, or symbol)
-   What data to use by referencing a source
-   The appearance of the data by setting various properties (for example color, opacity, and language)

The sample code below illustrates how to add a GeoJSON source and then add and style a line layer that uses the data in that source.

**Android View**

```kotlin

// Get the style
mapView.mapboxMap.getStyle { style ->
  // Specify a unique string as the source ID (SOURCE_ID)
  // and reference the location of source data
  style.addSource(
    geoJsonSource(SOURCE_ID) {
      data("asset://from_crema_to_council_crest.geojson")
    }
  )
  // Specify a unique string as the layer ID (LAYER_ID)
  // and reference the source ID (SOURCE_ID) added above.
  style.addLayer(
    lineLayer(LAYER_ID, SOURCE_ID) {
      lineColor(ContextCompat.getColor(context, R.color.black))
      lineWidth(3.0)
    }
  )
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
) {
  LineLayer(
    sourceState = rememberGeoJsonSourceState {
      data = GeoJSONData("asset://from_crema_to_council_crest.geojson")
    }
  ) {
    lineColor = ColorValue(Color.Black)
    lineWidth = DoubleValue(3.0)
  }
}
```

The exact available properties available when adding a source and layer varies by source type and layer type. Read more about [source types](#source-types) and [layer types](#layer-types) below.

### Update a layer at runtime

You can also update the style of any layer at runtime using the layer's unique layer ID with `Style`'s [`getLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers/get-layer.html) or [`getLayerAs`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers/get-layer-as.html) method and defining style properties.

The sample code below illustrates how to get an existing layer by referencing a layer ID and updating the value of the [`fillOpacity`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-fill-layer/#com.mapbox.maps.extension.style.layers.generated/FillLayer/fillOpacity/#/PointingToDeclaration/)'s value.

Note for Jetpack Compose extension, you can drive layer properties for runtime-added layer through mutable state, and for layers from style JSON, you can use imperative API within a `MapEffect`.

**Android View**

```kotlin

// Get the style
mapView.mapboxMap.getStyle { style ->
  // Get an existing layer by referencing its
  // unique layer ID (LAYER_ID)
  val layer = style.getLayerAs<FillLayer>(LAYER_ID)
  // Update layer properties
  layer?.fillOpacity(0.7)
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
  style = {
    MapStyle(style = MY_CUSTOMISE_STYLE)
  }
) {
  // Updating a layer in style json can be done through MapEffect
  MapEffect(Unit) { mapView ->
    mapView.mapboxMap.styleLoadedEvents.first().let {
      // Get an existing layer by referencing its
      // unique layer ID (LAYER_ID)
      val layer = mapView.mapboxMap.getLayerAs<FillLayer>(LAYER_ID)
      // Update layer properties
      layer?.fillOpacity(0.7)
    }
  }
}
```

The exact available properties available when updating a layer varies by layer type. Read more about [layer types](#layer-types) below.

### Specify order of a layer at runtime for Mapbox Standard and Standard Satellite

Mapbox Standard and Standard Satellite uses [slots](https://docs.mapbox.com/style-spec/reference/slots/) to specify where custom data layers can be added. **Slots** are predefined locations in the Standard and Standard Satellite basemaps where your layer can be inserted. To add custom layers in the appropriate location in the Standard basemap layer stack, Standard and Standard Satellite offers 3 carefully designed slots that you can leverage to place your layer. These slots will stay stable, and you can be sure that your own map won't break even as the basemap updates over time.

| Slot | Description |
| --- | --- |
| `bottom` | Above polygons (land, landuse, water, etc.) |
| `middle` | Above lines (roads, etc.) and behind 3D buildings |
| `top` | Above POI labels and behind Place and Transit labels. Designed to be used with the `symbol` layers. |
| not specified | Above all existing layers in the style |

Here's an example of how to assign a slot to a layer:

**Android View**

```kotlin

+lineLayer(layerId = "line-layer", sourceId = "line-layer") {
  lineColor(rgb(255.0, 165.0, 0.0))
  slot("middle")
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
  style = {
    // For Jetpack Compose extension, you can put runtime added layers into slots 
    // defined in the strongly typed MapboxStandardStyle and MapboxStandardSatelliteStyle composable function.
    MapboxStandardStyle(
      middleSlot = {
        LineLayer(
          sourceState = rememberGeoJsonSourceState {
            data = GeoJSONData("asset://line-source.geojson")
          }
        ) {
          lineColor = ColorValue(Color(255, 156, 0))
        }
      }
    )
  }
)
```

Make sure to use slots instead of layer [ids](https://docs.mapbox.com/style-spec/reference/layers/#id) when inserting a custom layer into the Standard or Standard Satellite basemap. If you want to order custom layers relative to each other, you can use the methods [`addLayerAbove`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers/add-layer-above.html), [`addLayerAt`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers/add-layer-at.html) and [`addLayerBelow`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers/add-layer-below.html), or the [Style DSL](https://docs.mapbox.com/android/maps/guides/styles/style-layers/#syntax) method [`layerAtPosition`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style/-style-extension-impl/-builder/layer-at-position.html?query=fun%20layerAtPosition(layer:%20Layer,%20above:%20String?%20=%20null,%20below:%20String?%20=%20null,%20at:%20Int?%20=%20null):%20Pair%3CLayer,%20LayerPosition%3E).

> **Note: Specifying position of a layer when adding it to a style**
> 
> When importing the Standard Style, the `LayerPosition` is only applicable to custom layers you have added yourself. If you add two layers to the same slot with a specified layer position the latter will define the order of the layers in that slot.

### Specify order of a layer at runtime for other styles

Map styles contains many individual layers (for example, roads, buildings, labels, and more) that are stacked on top of each other. You can change the position of a layer at runtime using the [`moveStyleLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps/-style/move-style-layer.html) API. The sample code below illustrates how to move an existing layer with the ID `"population"` below the layer with the ID `"state-labels"`.

**Android View**

```kotlin

// Get the style
mapView.mapboxMap.getStyle { style ->
  // Move position of the population layer
  // below the state-labels layer
  style.moveStyleLayer("population", LayerPosition(null, "state-labels", null))
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
  style = {
    MapStyle(style = MY_CUSTOMISE_STYLE)
  }
) {
  // Moving a layer defined in style json can be done through MapEffect
  // Instead, if the layer to be moved is added through composable function, move it by adjusting the order of composable function
  MapEffect(Unit) { mapView ->
    mapView.mapboxMap.styleLoadedEvents.first().let {
      // Move position of the population layer
      // below the state-labels layer
      mapView.mapboxMap.moveStyleLayer("population", LayerPosition(null, "state-labels", null))
    }
  }
}
```

> **Note: Specify position of a layer when adding it to a style**
> 
> By default, when you add a new layer to the style, it is placed on top of all the other layers. You can specify where the new layer is positioned relative to existing layers using `layerAtPosition` and specify if the layer should be positioned `below` or `above` another layer by referencing the layer ID (a string) or `at` a specific index (an integer).
> 
> **Android View**
> 
> ```kotlin
> // Get the style
> mapView.mapboxMap.getStyle { style ->
>   style.addSource(
>     vectorSource("terrain-data") {
>       url("mapbox://mapbox.mapbox-terrain-v2")
>      }
>   )
>   style.addLayerBelow(
>     lineLayer("terrain-data", "terrain-data") {
>       sourceLayer("contour")
>       lineWidth(1.9)
>     },
>     below = "road-label"
>   )
> }
> ```
> 
> **Jetpack Compose**
> 
> ```kotlin
> 
> MapboxMap(
>   Modifier.fillMaxSize(),
>   style = {
>     GenericStyle(
>       style = Style.MAPBOX_STREETS,
>       layerPositionedContent = layerPositionedContent {
>         belowLayer("road-label") {
>           LineLayer(
>             sourceState = rememberVectorSourceState {
>               url = StringValue("mapbox://mapbox.mapbox-terrain-v2")
>             }
>           ) {
>             sourceLayer = StringValue("contour")
>             lineWidth = DoubleValue(1.9)
>           }
>         }
>       }
>     )
>   }
> )
> ```

### Remove a layer at runtime

You can remove a layer from a style using `Style`'s [`removeStyleLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps/-style/remove-style-layer.html).

**Android View**

```kotlin

// Where LAYER_ID is a valid id of a layer that already
// exists in the style
mapView.mapboxMap.getStyle { style ->
  // If a layer with a given layer ID exists in the
  // style, remove the layer
  if (style.styleLayerExists(LAYER_ID)) {
    style.removeStyleLayer(LAYER_ID)
  }
}
```

**Jetpack Compose**

```kotlin

var shouldShowLayer by remember {
  mutableStateOf(true)
}
MapboxMap(
  modifier = Modifier.fillMaxSize(),
  style = {
    MapStyle(style = MY_CUSTOMISE_STYLE)
  }
) {
  // Removing a layer defined in style json can be done through MapEffect.
  MapEffect(Unit) { mapView ->
    mapView.mapboxMap.styleLoadedEvents.first().let {
      // If a layer with a given layer ID exists in the
      // style, remove the layer
      if (mapView.mapboxMap.styleLayerExists(LAYER_ID)) {
        mapView.mapboxMap.removeStyleLayer(LAYER_ID)
      }
    }
  }
  // Removing a layer added in runtime through composable function can be done through state driven condition.
  if (shouldShowLayer) {
    CircleLayer(...)
  }
}
```

## Source types

### Vector

A vector source, [`VectorSource`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.sources.generated/-vector-source/), is a vector tileset that conforms to the [Mapbox Vector Tile](https://docs.mapbox.com/vector-tiles/specification/) format. A vector source contains geographic features (and their data properties) that have already been tiled. Learn more about the benefits of vector tilesets and how they work in the [Vector tiles](https://docs.mapbox.com/vector-tiles/reference/) documentation. For vector tiles hosted by Mapbox, the "url" value should be of the form of `mapbox://tilesetid`.

**Android View**

```kotlin

style {
  // Specify a unique string as the source ID (SOURCE_ID)
  +vectorSource(SOURCE_ID) {
    url("mapbox://mapbox.mapbox-terrain-v2")
  }
}
```

**Jetpack Compose**

```kotlin

// (Optional) Specify a unique string as the source ID (SOURCE_ID), or a random ID will be generated and used by default.
val vectorSource = rememberVectorSourceState(sourceId = SOURCE_ID) {
  url = StringValue("mapbox://mapbox.mapbox-terrain-v2")
}
```

> **Note**
> 
> All style layers that use a vector source must specify a `"source-layer"` value.

### GeoJSON

A GeoJSON source, [`GeoJsonSource`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.sources.generated/-geo-json-source/), is data in the form of a JSON object that conforms to the [GeoJSON specification](https://geojson.org/). A GeoJSON source is a collection of one or more geographic features, which may be points, lines, and polygons. Data must be provided via a `"data"` property, whose value can be a URL or inline GeoJSON.

**Android View**

```kotlin

style {
  // Specify a unique string as the source ID (SOURCE_ID)
  +geoJsonSource(SOURCE_ID) {
    url("asset://from_crema_to_council_crest.geojson")
  }
}
```

**Jetpack Compose**

```kotlin

// (Optional) Specify a unique string as the source ID (SOURCE_ID), or a random ID will be generated and used by default.
val geoJsonSource = rememberGeoJsonSourceState(sourceId = SOURCE_ID) {
  data = GeoJSONData("asset://from_crema_to_council_crest.geojson")
}
```

> **Note**
> 
> See the format of the data used in the sample code above in the [Maps SDK example app on GitHub](https://github.com/mapbox/mapbox-maps-android/blob/v11.29.0/app/src/main/assets/from_crema_to_council_crest.geojson).

### Raster

A raster source, [`RasterSource`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.sources.generated/-raster-source/), is a raster tileset. For raster tiles hosted by Mapbox, the "url" value should be of the form `mapbox://tilesetid`.

**Android View**

```kotlin

style {
  // Specify a unique string as the source ID (SOURCE_ID)
  +rasterSource(SOURCE_ID) {
    tileSize(256)
    tileSet(TILESET_JSON, listOf(SOURCE_URL)) {}
  }
}
```

**Jetpack Compose**

```kotlin

// (Optional) Specify a unique string as the source ID (SOURCE_ID), or a random ID will be generated and used by default.
val rasterSource = rememberRasterSourceState(sourceId = SOURCE_ID) {
  tileSize = LongValue(256)
  tiles = StringListValue(listOf(SOURCE_URL)))
}
```

### Raster DEM

A raster DEM source, [`RasterDemSource`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.sources.generated/-raster-dem-source/), refers to Mapbox Terrain-DEM (`mapbox://mapbox.mapbox-terrain-dem-v1`), which is the only supported raster DEM source.

**Android View**

```kotlin

style {
  // Specify a unique string as the source ID (SOURCE_ID)
  +rasterDemSource(SOURCE_ID) {
    url("mapbox://mapbox.mapbox-terrain-dem-v1")
    // 514 specifies padded DEM tile and provides better performance than 512 tiles.
    tileSize(514)
  }
}
```

**Jetpack Compose**

```kotlin

// (Optional) Specify a unique string as the source ID (SOURCE_ID), or a random ID will be generated and used by default.
val rasterDemSource = rememberRasterDemSourceState(sourceId = SOURCE_ID) {
  url = StringValue("mapbox://mapbox.mapbox-terrain-dem-v1")
  // 514 specifies padded DEM tile and provides better performance than 512 tiles.
  tileSize = LongValue(514)
}
```

### Image

An image source, [`ImageSource`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.sources.generated/-image-source/), is an image that you supply along with geographic coordinates. Specify geographic coordinates in the `"coordinates"` array as `[longitude, latitude]` pairs so the SDK knows at what location in the world to place the image. Each coordinate pair in the `"coordinates"` array represents the image corners listed in clockwise order: top left, top right, bottom right, bottom left.

**Android View**

```kotlin

style {
  // Specify a unique string as the source ID (SOURCE_ID)
  +imageSource(SOURCE_ID) {
    coordinates(
      listOf(
        listOf(-80.11725, 25.7836),
        listOf(-80.1397431334, 25.783548),
        listOf(-80.13964, 25.7680),
        listOf(-80.11725, 25.76795)
      )
    )
  }
}
```

**Jetpack Compose**

```kotlin

// (Optional) Specify a unique string as the source ID (SOURCE_ID), or a random ID will be generated and used by default.
val imageSource = rememberImageSourceState(sourceId = SOURCE_ID) {
  coordinates = PointListValue(
    listOf(
      listOf(-80.11725, 25.7836),
      listOf(-80.1397431334, 25.783548),
      listOf(-80.13964, 25.7680),
      listOf(-80.11725, 25.76795)
    )
  )
}
```

## Layer types

### Fill layer

A fill style layer, [`FillLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-fill-layer/), renders one or more filled (and optionally stroked) polygons on a map. You can use a fill layer to configure the visual appearance of polygon or multipolygon features.

![](https://docs.mapbox.com/android/assets/ideal-img/maps-guides-styles-layers-fill-layer.4d81ac0.480.png)

To add a fill layer you need to first add a vector or GeoJSON source that contains polygon data. Then you can use the available [properties in the `FillLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-fill-layer/) class to customize the appearance of the layer (for example, the color, opacity, or pattern).

**Android View**

```kotlin

style {
  // Specify a unique string as the layer ID (LAYER_ID)
  // and assign the source ID added above.
  +fillLayer(LAYER_ID, SOURCE_ID) {
    fillColor(ContextCompat.getColor(context, R.color.black))
    fillOpacity(0.5)
  }
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
) {
  // (Optional) Specify a unique string as the layer ID (LAYER_ID), or by default a random generated ID will be used.
  // and assign the source state created above.
  FillLayer(
    layerId = LAYER_ID,
    sourceState = geoJsonSource
  ) {
    fillColor = ColorValue(Color.Black)
    fillOpacity = DoubleValue(0.5)
  }
}
```

> **Related content (related): [FillLayer](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-fill-layer/)**
> 
> A filled polygon with an optional stroked border.

> **Related content (example): [Tint a fill layer](https://docs.mapbox.com/android/maps/examples/android-view/tint-a-fill-layer/)**
> 
> Add an image to a style and use it to display a pattern in the landuse `FillLayer` in the Mapbox Streets style.

### Line layer

A line style layer, [`LineLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-line-layer/), renders one or more stroked polylines on the map. You can use a line layer to configure the visual appearance of polyline or multipolyline features.

![Map with a light gray line along a trail.](https://docs.mapbox.com/android/assets/ideal-img/maps-guides-styles-layers-line-layer.668ee70.480.png)

To add a line layer, you need to first add a vector or GeoJSON source that contains line data. Then you can use the available [properties in the `LineLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-line-layer/) class to customize the appearance of the layer (for example, the `color`, `width`, or `dasharray`).

**Android View**

```kotlin

style {
  // Specify a unique string as the layer ID (LAYER_ID)
  // and assign the source ID added above.
  +lineLayer(LAYER_ID, SOURCE_ID) {
    lineColor(ContextCompat.getColor(this@DrawPolygonActivity, R.color.black))
    lineWidth(3.0)
  }
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
) {
  // (Optional) Specify a unique string as the layer ID (LAYER_ID), or by default a random generated ID will be used.
  // and assign the source state created above.
  LineLayer(
    layerId = LAYER_ID,
    sourceState = geoJsonSource
  ) {
    lineColor = ColorValue(Color.Black)
    lineWidth = DoubleValue(3.0)
  }
}
```

> **Related content (related): [LineLayer](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-line-layer/)**
> 
> A stroked line.

> **Related content (example): [Draw a GeoJSON line](https://docs.mapbox.com/android/maps/examples/android-view/draw-a-geojson-line/)**
> 
> Load a polyline to a style using `GeoJsonSource` and display it on a map using `LineLayer`.

### Symbol layer

A symbol style layer, [`SymbolLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-symbol-layer/), renders icon and text labels at points or along lines on a map. You can use a symbol layer to configure the visual appearance of labels for features in vector tiles.

![](https://docs.mapbox.com/android/assets/ideal-img/maps-guides-styles-layers-symbol-layer-label.d056d67.480.png)

![](https://docs.mapbox.com/android/assets/ideal-img/maps-guides-styles-layers-symbol-layer-icon.09b3dde.480.png)

To add a symbol layer, you need to first add a vector or GeoJSON source that contains point data. If you want to use icons in this layer, you also need to add images to the style before adding the layer. Then you can use the available [properties in the `SymbolLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-symbol-layer/) class to customize the appearance of the layer.

**Android View**

```kotlin

style {
  // Specify a unique string as the layer ID (LAYER_ID)
  // and assign the source ID added above.
  +symbolLayer(LAYER_ID, SOURCE_ID) {
    // set a few properties
  }
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
) {
  // (Optional) Specify a unique string as the layer ID (LAYER_ID), or by default a random generated ID will be used.
  // and assign the source state created above.
  SymbolLayer(
    layerId = LAYER_ID,
    sourceState = geoJsonSource
  ) {
    // set a few properties
  }
}
```

> **Related content (related): [SymbolLayer](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-symbol-layer/)**
> 
> An icon or a text label.

> **Related content (example): [Display multiple icon images in a symbol layer](https://docs.mapbox.com/android/maps/examples/android-view/display-multiple-icon-images-in-a-symbol-layer/)**
> 
> Add point data and several images to a style and use the `switchCase` and get expressions to choose which image to display at each point in a `SymbolLayer` based on a data property.

### Circle layer

A circle style layer, [`CirleLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-circle-layer/), renders one or more filled circles on a map. You can use a circle layer to configure the visual appearance of point or point collection features in vector tiles. A circle layer renders circles whose radii are measured in screen units.

![](https://docs.mapbox.com/android/assets/ideal-img/maps-guides-styles-layers-circle-layer.3a8751c.480.png)

To add a circle layer, you need to first add a vector or GeoJSON source that contains point data. Then you can use the available [properties in the `CircleLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-circle-layer/) class to customize the appearance of the layer (for example, radius, color, or offset).

**Android View**

```kotlin

style {
  // Specify a unique string as the layer ID (LAYER_ID)
  // and assign the source ID added above.
  +circleLayer(LAYER_ID, SOURCE_ID) {
    // set a few properties
  }
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
) {
  // (Optional) Specify a unique string as the layer ID (LAYER_ID), or by default a random generated ID will be used.
  // and assign the source state created above.
  CircleLayer(
    layerId = LAYER_ID,
    sourceState = geoJsonSource
  ) {
    // set a few properties
  }
}
```

> **Related content (related): [CircleLayer](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-circle-layer/)**
> 
> A filled circle.

> **Related content (example): [Style circles categorically](https://docs.mapbox.com/android/maps/examples/android-view/style-circles-categorically/)**
> 
> Add point data to a style from a vector tileset and use the match and get expressions to assign the color of each point in a `CircleLayer` based on a data property.

### Fill extrusion layer

A fill-extrusion, [`FillExtrusionLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-fill-extrusion-layer/), style layer renders one or more filled (and optionally stroked) extruded (3D) polygons on a map. You can use a fill-extrusion layer to configure the extrusion and visual appearance of polygon or multipolygon features.

![](https://docs.mapbox.com/android/assets/ideal-img/maps-guides-styles-layers-fill-extrusion-layer.61db04e.480.png)

To add a fill extrusion layer, you need to first add a vector or GeoJSON source that contains polygon data. Often you will want the data to contain a data property that you will use to determine the height of extrusion of each feature. This may be a physical height in meters or a way to illustrate a non-physical attribute of the area like population in Census blocks. Once you've added an appropriate source, you can use the available [properties in the `FillExtrusionLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-fill-extrusion-layer/) class to customize the appearance of the layer (for example, the height, opacity, or color).

**Android View**

```kotlin

style {
  // Specify a unique string as the layer ID (LAYER_ID)
  // and assign the source ID added above.
  +fillExtrusionLayer(LAYER_ID, SOURCE_ID) {
    fillExtrusionHeight(
      get("height")
    )
  }
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
) {
  // (Optional) Specify a unique string as the layer ID (LAYER_ID), or by default a random generated ID will be used.
  // and assign the source state created above.
  FillExtrusionLayer(
    layerId = LAYER_ID,
    sourceState = geoJsonSource
  ) {
    fillExtrusionHeight = DoubleValue(Expression.get("height"))
  }
}
```

> **Note**
> 
> This example uses expressions to assign a value based on a data property. Read more about expressions in the [Use expressions](https://docs.mapbox.com/android/maps/guides/styles/style-layers/) guide.

> **Related content (related): [FillExtrusionLayer](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-fill-extrusion-layer/)**
> 
> An extruded (3D) polygon.

> **Related content (example): [Display building extrusions](https://docs.mapbox.com/android/maps/examples/android-view/display-3d-buildings/)**
> 
> Extrude the building layer in the Mapbox Light style using `FillExtrusionLayer` and set up the light position.

### Hillshade layer

A hillshade style layer, [`HillshadeLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-hillshade-layer/), renders digital elevation model (DEM) data on the client-side.

The implementation only supports Mapbox Terrain RGB and Mapzen Terrarium tiles. You must add either Mapbox Terrain RGB or Mapzen Terrarium as a source before adding a hillshade layer. Once you've added an appropriate source, you can use the available [properties in the `HillshadeLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-hillshade-layer/) class to customize the appearance of the layer.

**Android View**

```kotlin

style {
  // Specify a unique string as the layer ID (LAYER_ID)
  // and assign the source ID added above.
  +hillshadeLayer(LAYER_ID, SOURCE_ID) {
    // set a few properties
  }
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
) {
  // (Optional) Specify a unique string as the layer ID (LAYER_ID), or by default a random generated ID will be used.
  // and assign the source state created above.
  HillshadeLayer(
    layerId = LAYER_ID,
    sourceState = geoJsonSource
  ) {
    // set a few properties  
  }
}
```

> **Related content (related): [HillshadeLayer](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-hillshade-layer/)**
> 
> Client-side hillshading visualization based on DEM data. The implementation only supports Mapbox Terrain RGB and Mapzen Terrarium tiles.

### Heatmap layer

A heatmap style layer, [`HeatmapLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-heatmap-layer/), renders a range of colors to represent the density of points in an area.

![](https://docs.mapbox.com/android/assets/ideal-img/maps-guides-styles-layers-heatmap-layer.c8925cb.480.png)

To add a heatmap layer, you need to first add a vector or GeoJSON source that contains point data. Then you can use the available [properties in the `HeatmapLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-heatmap-layer/) class to customize the appearance of the layer.

**Android View**

```kotlin

style {
  // Specify a unique string as the layer ID (LAYER_ID)
  // and assign the source ID added above.
  +heatmapLayer(LAYER_ID, SOURCE_ID) {
    // set a few properties
  }
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
) {
  // (Optional) Specify a unique string as the layer ID (LAYER_ID), or by default a random generated ID will be used.
  // and assign the source state created above.
  HeatmapLayer(
    layerId = LAYER_ID,
    sourceState = geoJsonSource
  ) {
    // set a few properties  
  }
}
```

> **Related content (related): [HeatmapLayer](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-heatmap-layer/)**
> 
> A heatmap.

> **Related content (example): [Visualize data as a heatmap](https://docs.mapbox.com/android/maps/examples/android-view/visualize-data-as-a-heatmap/)**
> 
> Add earthquake frequency data to a style from a GeoJSON file and render it on a map using a `HeatmapLayer`.

### Raster layer

A raster style layer, [`RasterLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-raster-layer/), renders raster tiles on a map. You can use a raster layer to configure the color parameters of raster tiles.

To add a raster layer, you need to first add a raster source. Then you can use the available [properties in the `RasterLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-raster-layer/) class to customize the appearance of the layer.

**Android View**

```kotlin

style {
  // Specify a unique string as the layer ID (LAYER_ID)
  // and assign the source ID added above.
  +rasterLayer(LAYER_ID, SOURCE_ID) {
    // set a few properties
  }
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
) {
  // (Optional) Specify a unique string as the layer ID (LAYER_ID), or by default a random generated ID will be used.
  // and assign the source state created above.
  RasterLayer(
    layerId = LAYER_ID,
    sourceState = geoJsonSource
  ) {
    // set a few properties  
  }
}
```

> **Related content (related): [RasterLayer](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-raster-layer/)**
> 
> Raster map textures such as satellite imagery.

> **Related content (example): [Add animated weather data](https://docs.mapbox.com/android/maps/examples/android-view/add-animated-weather-data/)**
> 
> Load a raster image to a style using `ImageSource` and display it on a map as animated weather data using `RasterLayer`

> **Related content (example): [(Compose) Add animated weather data](https://docs.mapbox.com/android/maps/examples/compose/add-animated-weather-data/)**
> 
> Load a raster image to a style using `ImageSource` and display it on a map as animated weather data using `RasterLayer`

### Sky layer

A sky style layer, [`SkyLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-sky-layer/), renders a stylized spherical dome that encompasses the entire map and is automatically rendered behind all layers. This can be used to fill the area above the horizon with a simulated sky that illustrates a particular time-of-day, or stylized custom gradients.

![](https://docs.mapbox.com/android/assets/ideal-img/maps-guides-styles-layers-sky-layer.ba4f273.480.png)

You can use the available [properties in the `SkyLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-sky-layer/) class to customize the appearance of the layer.

**Android View**

```kotlin

style {
  // Specify a unique string as the layer ID (LAYER_ID)
  +skyLayer(LAYER_ID) {
    // set a few properties
  }
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
) {
  // (Optional) Specify a unique string as the layer ID (LAYER_ID), or by default a random generated ID will be used.
  SkyLayer(
    layerId = LAYER_ID
  ) {
    // set a few properties  
  }
}
```

> **Related content (related): [SkyLayer](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-sky-layer/)**
> 
> A spherical dome around the map that is always rendered behind all other layers.

### Background layer

The background style layer, [`BackgroundLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-background-layer/), covers the entire map. Use a background style layer to configure a color or pattern to show below all other map content. If the background layer is transparent or omitted from the style, any part of the map view that does not show another style layer is transparent.

You can use the available [properties in the `BackgroundLayer`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-background-layer/) class to customize the appearance of the layer.

**Android View**

```kotlin

style {
  // Specify a unique string as the layer ID (LAYER_ID)
  +backgroundLayer(LAYER_ID) {
    // set a few properties
  }
}
```

**Jetpack Compose**

```kotlin

MapboxMap(
  modifier = Modifier.fillMaxSize(),
) {
  // (Optional) Specify a unique string as the layer ID (LAYER_ID), or by default a random generated ID will be used.
  BackgroundLayer(
    layerId = LAYER_ID
  ) {
    // set a few properties  
  }
}
```

> **Related content (related): [BackgroundLayer](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.extension.style.layers.generated/-background-layer/)**
> 
> The background color or pattern of the map.