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

# Location component

![Shows location puck on the map.](https://docs.mapbox.com/android/ja/assets/ideal-img/maps-examples-location-component.0869b80.480.png)

This example showcases the implementation of a location component utilizing customizations from the **Mapbox Maps SDK for Android**.

The `LocationComponentActivity` class extends Android's [`AppCompatActivity`](https://developer.android.com/reference/kotlin/androidx/appcompat/app/AppCompatActivity) and includes functionality to vary & customize the location component including:

-   Customizing the puck image
-   Changing map themes and light presets
-   Updating map projections
-   Showing and hiding the component
-   Showing a bearing image - [`puckBearingEnabled`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.plugin.locationcomponent.generated/-location-component-settings-interface/puck-bearing-enabled.html)
-   Enabling an accuracy ring - [`showAccuracyRing`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.plugin.locationcomponent.generated/-location-component-settings-interface/show-accuracy-ring.html)
-   Changing the components opacity
-   Moving the component to different [slots](https://docs.mapbox.com/style-spec/reference/slots/)

The example also shows how to handle user interactions like clicking and long-clicking ([`onMapClickListener`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.plugin.gestures/-gestures-plugin/add-on-map-click-listener.html) and [`onMapLongClickListener`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.plugin.gestures/-on-map-long-click-listener/)) on the location puck as well as utilizing [`LocationPuck2D`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.plugin/-location-puck2-d/), [`LocationPuck3D`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.plugin/-location-puck3-d/), and the [`DefaultLocationProvider`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.plugin.locationcomponent/-default-location-provider/).

> **Note: Android Examples App Available**
> 
> This example code is part of the **Maps SDK for Android Examples App**, a working Android project [available on GitHub](https://github.com/mapbox/mapbox-maps-android/tree/v11.28.0/). Android developers are encouraged to run the examples app locally to interact with this example in an emulator and explore other features of the Maps SDK.
> 
> See our [Run the Maps SDK for Android Examples App](https://docs.mapbox.com/help/tutorials/maps-sdk-android-examples-app/) tutorial for step-by-step instructions.

**Kotlin**

Title: `LocationComponentActivity.kt`

[View on GitHub](https://github.com/mapbox/mapbox-maps-android/blob/v11.28.0/app/src/main/java/com/mapbox/maps/testapp/examples/LocationComponentActivity.kt)

```kt
package com.mapbox.maps.testapp.examples

import android.graphics.Color
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.mapbox.bindgen.Value
import com.mapbox.maps.CameraOptions
import com.mapbox.maps.ImageHolder
import com.mapbox.maps.MapboxExperimental
import com.mapbox.maps.Style
import com.mapbox.maps.extension.style.expressions.dsl.generated.interpolate
import com.mapbox.maps.extension.style.layers.properties.generated.Anchor
import com.mapbox.maps.extension.style.layers.properties.generated.ProjectionName
import com.mapbox.maps.extension.style.light.generated.flatLight
import com.mapbox.maps.extension.style.light.setLight
import com.mapbox.maps.extension.style.projection.generated.getProjection
import com.mapbox.maps.extension.style.projection.generated.projection
import com.mapbox.maps.extension.style.projection.generated.setProjection
import com.mapbox.maps.plugin.LocationPuck2D
import com.mapbox.maps.plugin.LocationPuck3D
import com.mapbox.maps.plugin.PuckBearing
import com.mapbox.maps.plugin.gestures.gestures
import com.mapbox.maps.plugin.locationcomponent.DefaultLocationProvider
import com.mapbox.maps.plugin.locationcomponent.OnIndicatorPositionChangedListener
import com.mapbox.maps.plugin.locationcomponent.createDefault2DPuck
import com.mapbox.maps.plugin.locationcomponent.location
import com.mapbox.maps.testapp.R
import com.mapbox.maps.testapp.databinding.ActivityLocationComponentBinding
import com.mapbox.maps.testapp.examples.annotation.AnnotationUtils.showShortToast
import com.mapbox.maps.testapp.utils.LocationPermissionHelper
import java.lang.ref.WeakReference

@OptIn(MapboxExperimental::class)
class LocationComponentActivity : AppCompatActivity() {

  private var lastStyleTheme = StyleTheme.DARK
  private lateinit var locationPermissionHelper: LocationPermissionHelper
  private val onIndicatorPositionChangedListener = OnIndicatorPositionChangedListener {
    // Jump to the current indicator position
    binding.mapView.mapboxMap.setCamera(CameraOptions.Builder().center(it).build())
    // Set the gestures plugin's focal point to the current indicator location.
    binding.mapView.gestures.focalPoint = binding.mapView.mapboxMap.pixelForCoordinate(it)
  }
  private lateinit var binding: ActivityLocationComponentBinding
  private enum class StyleTheme {
    LIGHT,
    DARK
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityLocationComponentBinding.inflate(layoutInflater)
    setContentView(binding.root)
    locationPermissionHelper = LocationPermissionHelper(WeakReference(this))
    locationPermissionHelper.checkPermissions {
      binding.mapView.apply {
        mapboxMap.loadStyle(Style.STANDARD) {
          it.setLight(
            flatLight {
              anchor(Anchor.MAP)
              color(Color.YELLOW)
              position(
                radialCoordinate = 10.0,
                azimuthalAngle = 40.0,
                polarAngle = 50.0
              )
            }
          )
          // Disable scroll gesture, since we are updating the camera position based on the indicator location.
          gestures.scrollEnabled = false
          gestures.addOnMapClickListener { point ->
            location
              .isLocatedAt(point) { isPuckLocatedAtPoint ->
                if (isPuckLocatedAtPoint) {
                  Toast.makeText(context, "Clicked on location puck", Toast.LENGTH_SHORT).show()
                }
              }
            true
          }
          gestures.addOnMapLongClickListener { point ->
            location.isLocatedAt(point) { isPuckLocatedAtPoint ->
              if (isPuckLocatedAtPoint) {
                Toast.makeText(context, "Long-clicked on location puck", Toast.LENGTH_SHORT)
                  .show()
              }
            }
            true
          }
          val locationProvider = location.getLocationProvider() as DefaultLocationProvider
          locationProvider.addOnCompassCalibrationListener {
            Toast.makeText(context, "Compass needs to be calibrated", Toast.LENGTH_LONG).show()
          }
        }
      }
    }
  }

  override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.menu_location_component, menu)
    return true
  }

  override fun onOptionsItemSelected(item: MenuItem): Boolean {
    when (item.itemId) {
      R.id.action_customise_location_puck_change -> {
        toggleCustomisedPuck()
        return true
      }
      R.id.action_map_style_change -> {
        toggleMapStyle()
        return true
      }
      R.id.action_map_projection_change -> {
        toggleMapProjection()
        return true
      }
      R.id.action_component_disable -> {
        binding.mapView.location.enabled = false
        return true
      }
      R.id.action_component_enabled -> {
        binding.mapView.location.enabled = true
        return true
      }
      R.id.action_show_bearing -> {
        binding.mapView.location.puckBearingEnabled = true
        if (binding.mapView.location.locationPuck is LocationPuck2D) {
          binding.mapView.location.locationPuck = createDefault2DPuck(withBearing = true)
        }
        return true
      }
      R.id.action_hide_bearing -> {
        binding.mapView.location.puckBearingEnabled = false
        if (binding.mapView.location.locationPuck is LocationPuck2D) {
          binding.mapView.location.locationPuck = createDefault2DPuck(withBearing = false)
        }
        return true
      }
      R.id.heading -> {
        binding.mapView.location.puckBearing = PuckBearing.HEADING
        item.isChecked = true
        return true
      }
      R.id.course -> {
        binding.mapView.location.puckBearing = PuckBearing.COURSE
        item.isChecked = true
        return true
      }
      R.id.location_no_animation -> {
        (binding.mapView.location.getLocationProvider() as DefaultLocationProvider).locationAnimatorOptions {
            duration = 0
          }
        item.isChecked = true
        return true
      }
      R.id.location_1s_animation -> {
        (binding.mapView.location.getLocationProvider() as DefaultLocationProvider).locationAnimatorOptions {
          duration = 1000
        }
        item.isChecked = true
        return true
      }
      R.id.location_300ms_animation -> {
        (binding.mapView.location.getLocationProvider() as DefaultLocationProvider).locationAnimatorOptions {
            duration = 300
          }
        item.isChecked = true
        return true
      }
      R.id.action_accuracy_enabled -> {
        val location = binding.mapView.location
        location.showAccuracyRing = true
        if (location.locationPuck is LocationPuck3D) {
          showShortToast("showAccuracyRing works for 2D location puck only")
        }
        item.isChecked = true
        return true
      }
      R.id.action_accuracy_disable -> {
        binding.mapView.location.showAccuracyRing = false
        item.isChecked = true
        return true
      }
      R.id.toggle_opacity -> {
        val location = binding.mapView.location
        location.locationPuck = location.locationPuck.run {
          when (this) {
            is LocationPuck3D -> copy(modelOpacity = if (modelOpacity == 1.0F) 0.5F else 1.0F)
            is LocationPuck2D -> copy(opacity = if (opacity == 1.0F) 0.5F else 1.0F)
          }
        }
        return true
      }
      R.id.move_to_bottom_slot -> {
        val location = binding.mapView.location
        location.slot = "bottom"
        return true
      }

      R.id.reset_slot -> {
        val location = binding.mapView.location
        location.slot = null
        return true
      }

      else -> return super.onOptionsItemSelected(item)
    }
  }

  private fun toggleCustomisedPuck() {
    binding.mapView.location.let {
      when (it.locationPuck) {
        is LocationPuck3D -> it.locationPuck = LocationPuck2D(
          topImage = ImageHolder.from(com.mapbox.maps.plugin.locationcomponent.R.drawable.mapbox_user_icon),
          bearingImage = ImageHolder.from(com.mapbox.maps.plugin.locationcomponent.R.drawable.mapbox_user_bearing_icon),
          shadowImage = ImageHolder.from(com.mapbox.maps.plugin.locationcomponent.R.drawable.mapbox_user_stroke_icon),
          scaleExpression = interpolate {
            linear()
            zoom()
            stop {
              literal(0.0)
              literal(0.6)
            }
            stop {
              literal(20.0)
              literal(1.0)
            }
          }.toJson()
        )
        is LocationPuck2D -> it.locationPuck = LocationPuck3D(
          modelUri = "asset://sportcar.glb",
          modelScale = listOf(10f, 10f, 10f),
          modelTranslation = listOf(0.1f, 0.1f, 0.1f),
          modelRotation = listOf(0.0f, 0.0f, 180.0f),
          modelCastShadows = false,
          modelReceiveShadows = false,
          modelEmissiveStrength = 1.1f
        )
      }
    }
  }

  private fun toggleMapStyle() {
    if (lastStyleTheme == StyleTheme.DARK) {
      binding.mapView.mapboxMap.setStyleImportConfigProperty(
        "basemap",
        "theme",
        Value.valueOf("monochrome")
      )
      binding.mapView.mapboxMap.setStyleImportConfigProperty(
        "basemap",
        "lightPreset",
        Value.valueOf("day")
      )
      lastStyleTheme = StyleTheme.LIGHT
    } else {
      binding.mapView.mapboxMap.setStyleImportConfigProperty(
        "basemap",
        "theme",
        Value.valueOf("monochrome")
      )
      binding.mapView.mapboxMap.setStyleImportConfigProperty(
        "basemap",
        "lightPreset",
        Value.valueOf("night")
      )
      lastStyleTheme = StyleTheme.DARK
    }
  }

  private fun toggleMapProjection() {
    binding.mapView.mapboxMap.getStyle { style ->
      style.setProjection(
        projection(
          when (style.getProjection()?.name) {
            ProjectionName.MERCATOR -> ProjectionName.GLOBE
            ProjectionName.GLOBE -> ProjectionName.MERCATOR
            else -> ProjectionName.GLOBE
          }
        )
      )
    }
  }

  override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<String>,
    grantResults: IntArray
  ) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    locationPermissionHelper.onRequestPermissionsResult(requestCode, permissions, grantResults)
  }

  override fun onStart() {
    super.onStart()
    binding.mapView.location
      .addOnIndicatorPositionChangedListener(onIndicatorPositionChangedListener)
  }

  override fun onStop() {
    super.onStop()
    binding.mapView.location
      .removeOnIndicatorPositionChangedListener(onIndicatorPositionChangedListener)
  }
}
```

**XML**

Title: `activity_location_component.xml`

[View on GitHub](https://github.com/mapbox/mapbox-maps-android/blob/v11.28.0/app/src/main/res/layout/activity_location_component.xml)

```xml
<?xml version="1.0" encoding="utf-8"?>
<com.mapbox.maps.MapView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:mapbox="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mapView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    mapbox:mapbox_locationComponentEnabled = "true"
    mapbox:mapbox_locationComponentPuckBearing = "heading"
    tools:context=".examples.LocationComponentActivity" />
```