Skip to main content

Location component animation

Animates puck with custom location provider updates.
Android Examples App Available

This example code is part of the Maps SDK for Android Examples App, a working Android project available on GitHub. 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 tutorial for step-by-step instructions.

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

import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.appcompat.app.AppCompatActivity
import androidx.interpolator.view.animation.FastOutSlowInInterpolator
import com.mapbox.geojson.Point
import com.mapbox.maps.CameraOptions
import com.mapbox.maps.ImageHolder
import com.mapbox.maps.MapboxMap
import com.mapbox.maps.Style
import com.mapbox.maps.plugin.LocationPuck2D
import com.mapbox.maps.plugin.PuckBearing
import com.mapbox.maps.plugin.locationcomponent.LocationConsumer
import com.mapbox.maps.plugin.locationcomponent.LocationProvider
import com.mapbox.maps.plugin.locationcomponent.location
import com.mapbox.maps.testapp.R
import com.mapbox.maps.testapp.databinding.ActivityLocationComponentAnimationBinding

/**
* Example that demonstrates using custom [LocationProvider] and sending custom location updates
* with [LocationConsumer] with using custom puck transition options.
*/
class LocationComponentAnimationActivity : AppCompatActivity() {

private lateinit var mapboxMap: MapboxMap

private var emitCount = 0
private var delta = 0f
private val handler = Handler(Looper.getMainLooper())

private inner class FakeLocationProvider : LocationProvider {

private var locationConsumer: LocationConsumer? = null

private fun emitFakeLocations() {
// after several first emits we update puck animator options
if (emitCount == 5) {
locationConsumer?.let {
it.onPuckLocationAnimatorDefaultOptionsUpdated {
// set same duration as our location emit frequency - it will make puck position change smooth
duration = 2000
interpolator = FastOutSlowInInterpolator()
}
it.onPuckBearingAnimatorDefaultOptionsUpdated {
// set duration bigger than our location emit frequency -
// this will result in cancelling ongoing animation and starting new one with a visible non-smooth `jump`
duration = 5000
}
}
}
handler.postDelayed(
{
when (emitCount) {
// set duration > location emit frequency -> location animator will interrupt running one
// and start from last interpolated point. Because of constant change of target point
// it will result in increasing puck speed.
in 1..5 -> {
locationConsumer?.onLocationUpdated(
Point.fromLngLat(
POINT_LNG + delta,
POINT_LAT + delta
)
) {
duration = 4000
}
}
// set duration = emit frequency -> location animators do not interrupt each other
else -> {
locationConsumer?.onLocationUpdated(
Point.fromLngLat(
POINT_LNG + delta,
POINT_LAT + delta
)
)
}
}
locationConsumer?.onBearingUpdated(BEARING + delta * 10000.0 * 5)
delta += 0.001f
emitCount++
emitFakeLocations()
},
2000
)
}

override fun registerLocationConsumer(locationConsumer: LocationConsumer) {
this.locationConsumer = locationConsumer
emitFakeLocations()
}

override fun unRegisterLocationConsumer(locationConsumer: LocationConsumer) {
this.locationConsumer = null
handler.removeCallbacksAndMessages(null)
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityLocationComponentAnimationBinding.inflate(layoutInflater)
setContentView(binding.root)
mapboxMap = binding.mapView.mapboxMap.apply {
loadStyle(
Style.STANDARD
) {
setCamera(
CameraOptions.Builder()
.zoom(14.0)
.pitch(0.0)
.bearing(0.0)
.center(Point.fromLngLat(POINT_LNG, POINT_LAT))
.build()
)
binding.mapView.location.apply {
setLocationProvider(FakeLocationProvider())
updateSettings {
puckBearingEnabled = true
puckBearing = PuckBearing.COURSE
enabled = true
locationPuck = LocationPuck2D(
bearingImage = ImageHolder.from(R.drawable.mapbox_mylocation_icon_bearing),
)
}
}
}
}
}

override fun onDestroy() {
super.onDestroy()
handler.removeCallbacksAndMessages(null)
}

companion object {
private const val POINT_LAT = 60.1699
private const val POINT_LNG = 24.9384
private const val BEARING = 60.0
}
}
Was this example helpful?