Animation Around
Contents
The Mobile Maps SDK examples require that you first complete the initial project set-up.
Display an animated view around a specific location.
activity_sample_animate_around.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="match_parent">
<com.trimblemaps.mapsdk.maps.MapView android:id="@+id/mapView" android:layout_width="match_parent" android:layout_height="match_parent"/>
<Button android:id="@+id/btn_toggleAnimation" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="Toggle Animation"/>
</FrameLayout>
Sample Code
Before running the Java or Kotlin code, the theme needs to be set in the Theme.xml
file as shown below.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.AsyncAcctInit" parent="Theme.AppCompat" />
</resources>
package com.trimblemaps.navigationexamples;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import com.trimblemaps.account.LicensedFeature;
import com.trimblemaps.account.TrimbleMapsAccountManager;
import com.trimblemaps.account.models.TrimbleMapsAccount;
import com.trimblemaps.mapsdk.TrimbleMaps;
import com.trimblemaps.mapsdk.camera.CameraPosition;
import com.trimblemaps.mapsdk.camera.CameraUpdate;
import com.trimblemaps.mapsdk.camera.CameraUpdateFactory;
import com.trimblemaps.mapsdk.geometry.LatLng;
import com.trimblemaps.mapsdk.maps.MapView;
import com.trimblemaps.mapsdk.maps.OnMapReadyCallback;
import com.trimblemaps.mapsdk.maps.TrimbleMapsMap;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.trimblemaps.mapsdk.maps.Style;
public final class SampleAnimatedCameraActivity extends AppCompatActivity {
private MapView mapView;
private TrimbleMapsMap map;
private final List<LatLng> cities = Arrays.asList(new LatLng[]{new LatLng(39.765654371695554, -104.97953028057314), new LatLng(36.17154274531701, -115.15669159394326), new LatLng(33.45718847708079, -112.074932293209), new LatLng(40.75525433174506, -111.88587090500303)});
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TrimbleMapsAccount trimbleMapsAccount = TrimbleMapsAccount.builder().apiKey("Your-API-key-here").addLicensedFeature(LicensedFeature.MAPS_SDK).build();
TrimbleMapsAccountManager.initialize(trimbleMapsAccount);
TrimbleMapsAccountManager.awaitInitialization();
TrimbleMaps.getInstance((Context) this);
setContentView(R.layout.activity_sample_animate_around);
Button btn_randomAnimation = findViewById(R.id.btn_toggleAnimation);
btn_randomAnimation.setOnClickListener((View.OnClickListener) (new View.OnClickListener() {
public final void onClick(View it) {
double min = 10.0; // Lower bound (inclusive)
double max = 12.0; // Upper bound (exclusive)
Random random = new Random();
double randomZoom = min + (max - min) * random.nextDouble();
LatLng randomCity = (LatLng) cities.get(random.nextInt(cities.size()));
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(randomCity, randomZoom);
// Animate the camera and provide an (optional) duration for the change in milliseconds
map.animateCamera(cameraUpdate, 1000);
}
}));
// Set up the MapView from the layout
mapView = findViewById(R.id.mapView);
mapView.getMapAsync((OnMapReadyCallback) (new OnMapReadyCallback() {
public final void onMapReady(@NotNull TrimbleMapsMap trimbleMapsMap) {
map = trimbleMapsMap;
trimbleMapsMap.setStyle(Style.MOBILE_DAY);
if (map != null) {
map.setCameraPosition((new CameraPosition.Builder()).target((LatLng) cities.get(0)).zoom(11.0).build());
}
}
}));
}
protected void onStart() {
super.onStart();
if (this.mapView != null) {
this.mapView.onStart();
}
}
protected void onResume() {
super.onResume();
if (this.mapView != null) {
this.mapView.onResume();
}
}
protected void onPause() {
super.onPause();
if (this.mapView != null) {
this.mapView.onPause();
}
}
protected void onStop() {
super.onStop();
if (this.mapView != null) {
this.mapView.onStop();
}
}
public void onLowMemory() {
super.onLowMemory();
if (this.mapView != null) {
this.mapView.onLowMemory();
}
}
protected void onDestroy() {
super.onDestroy();
if (this.mapView != null) {
this.mapView.onDestroy();
}
}
}
package com.trimblemaps.kotlinsamples.samples
import android.animation.ValueAnimator
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.animation.LinearInterpolator
import android.widget.Button
import com.trimblemaps.account.LicensedFeature
import com.trimblemaps.account.TrimbleMapsAccountManager
import com.trimblemaps.account.models.TrimbleMapsAccount
import com.trimblemaps.mapsdk.TrimbleMaps
import com.trimblemaps.mapsdk.camera.CameraPosition
import com.trimblemaps.mapsdk.camera.CameraUpdateFactory
import com.trimblemaps.mapsdk.geometry.LatLng
import com.trimblemaps.mapsdk.maps.MapView
import com.trimblemaps.mapsdk.maps.Style
import com.trimblemaps.mapsdk.maps.TrimbleMapsMap
import kotlin.math.roundToLong
class SampleAnimateAroundActivity : AppCompatActivity() {
private var mapView: MapView? = null
private var map: TrimbleMapsMap? = null
private var shouldAnimate = false
private val numberOfSpins = 8f // How many times should it spin
private val spinDuration = 16 // how long, in seconds, should a spin take
// Working with an animator
private var animator : ValueAnimator = ValueAnimator.ofFloat(0f, numberOfSpins * 360)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Authorize the api key for the session.
// .apiKey() requires your Trimble Maps API key
val trimbleMapsAccount = TrimbleMapsAccount.builder()
.apiKey("Your-API-key-here")
.addLicensedFeature(LicensedFeature.MAPS_SDK)
.build()
// Initialize the session
TrimbleMapsAccountManager.initialize(trimbleMapsAccount)
TrimbleMapsAccountManager.awaitInitialization()
// Get an instance of the map, done before the layout is set.
TrimbleMaps.getInstance(this)
setContentView(R.layout.activity_sample_animate_around)
// Set up the MapView from the layout
mapView = findViewById(R.id.mapView)
// the onMapReadyCallback is fired when the map is ready to be worked with
mapView?.getMapAsync { trimbleMapsMap ->
map = trimbleMapsMap
// The TrimbleMapsMap object is created, now a style can be applied to render a map.
// Adding the source and layer for the buildings highlighted. Building outlines will be
// displayed in yellow
trimbleMapsMap.setStyle(Style.MOBILE_DAY)
map?.cameraPosition = CameraPosition.Builder()
.target(LatLng(39.90073499962372, -75.16745401827387))
.zoom(16.0)
.build()
}
// Setup the animator
animator.duration = (numberOfSpins * spinDuration * 1000).roundToLong()
animator.interpolator = LinearInterpolator()
animator.startDelay = 1000
// Create the animation toggles
findViewById<Button>(R.id.btn_toggleAnimation).setOnClickListener {
shouldAnimate = !shouldAnimate
// Should the animation be on? Are we resuming or starting from fresh?
if(shouldAnimate) {
if(animator.isStarted) {
animator.resume()
} else {
animator.addUpdateListener {valueAnimator ->
// Get the bearing from the animator and apply it to the camera position
val bearing = valueAnimator.animatedValue as Float
map?.moveCamera(CameraUpdateFactory.newCameraPosition(
CameraPosition.Builder()
.target(map?.cameraPosition?.target)
.bearing(bearing.toDouble())
.build()
))
}
animator.start()
}
} else {
animator.pause()
}
}
}
/**
* Activity Overrides
*/
override fun onStart() {
super.onStart()
mapView?.onStart()
}
override fun onResume() {
super.onResume()
mapView?.onResume()
}
override fun onPause() {
super.onPause()
mapView?.onPause()
}
override fun onStop() {
super.onStop()
mapView?.onStop()
}
override fun onLowMemory() {
super.onLowMemory()
mapView?.onLowMemory()
}
override fun onDestroy() {
super.onDestroy()
mapView?.onDestroy()
}
}