Frame Locations
Contents
The Mobile Maps SDK examples require that you first complete the initial project set-up.
Frame the map view to the bounds of a set of locations. In this case, we will use the Lines On a Map example to frame the map to each set of lines when clicking on the buttons, which will utilize the moveCamera()
or easeCamera()
functions.
activity_sample_framing.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.trimblemaps.mapsdk.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_cycleLocations"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="moveCamera()"
android:textAllCaps="false" />
<Button
android:id="@+id/btn_easeCamera"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="easeCamera()"
android:textAllCaps="false" />
</LinearLayout>
</LinearLayout>
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>
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import com.trimblemaps.account.LicensedFeature;
import com.trimblemaps.account.TrimbleMapsAccountManager;
import com.trimblemaps.account.models.TrimbleMapsAccount;
import com.trimblemaps.geojson.FeatureCollection;
import com.trimblemaps.geojson.LineString;
import com.trimblemaps.geojson.Point;
import com.trimblemaps.mapsdk.TrimbleMaps;
import com.trimblemaps.mapsdk.camera.CameraPosition;
import com.trimblemaps.mapsdk.camera.CameraUpdate;
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 com.trimblemaps.mapsdk.style.layers.LineLayer;
import com.trimblemaps.mapsdk.style.layers.PropertyFactory;
import com.trimblemaps.mapsdk.style.sources.GeoJsonSource;
import com.trimblemaps.mapsdk.plugins.places.common.utils.CameraUtils;
import java.io.InputStreamReader;
import java.util.List;
import java.util.stream.Collectors;
public class FramingJava extends Activity implements Style.OnStyleLoaded {
private MapView mapView = null;
private TrimbleMapsMap map = null;
private int currentIndex = 0;
private static final String SOURCE_ID = "linesource";
private static final String LAYER_ID = "linelayer";
private List<LineString> allLines;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Authorize the API key for the session.
// .apiKey() requires your Trimble Maps API key
TrimbleMapsAccount 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_framing);
// 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;
CameraPosition position = new CameraPosition.Builder()
.target(new LatLng(40.60902838712187, -97.73800045737227))
.zoom(2.5)
.build();
map.setCameraPosition(position);
map.setStyle(Style.MOBILE_DAY, this);
});
// When the button is clicked, cycle through the lines using trimbleMapsMap.moveCamera
findViewById(R.id.btn_cycleLocations).setOnClickListener(v -> {
if (map != null && allLines != null && !allLines.isEmpty()) {
LineString selectedLine = allLines.get(currentIndex);
List<Point> pointList = selectedLine.coordinates().stream()
.map(point -> Point.fromLngLat(point.longitude(), point.latitude()))
.collect(Collectors.toList());
CameraUpdate update = CameraUtils.frameLocationOrPolygon(null, pointList);
if (update != null) {
map.moveCamera(update);
}
currentIndex = (currentIndex + 1) % allLines.size();
}
});
// When the button is clicked, cycle through the lines using trimbleMapsMap.easeCamera
findViewById(R.id.btn_easeCamera).setOnClickListener(v -> {
if (map != null && allLines != null && !allLines.isEmpty()) {
LineString selectedLine = allLines.get(currentIndex);
List<Point> pointList = selectedLine.coordinates().stream()
.map(point -> Point.fromLngLat(point.longitude(), point.latitude()))
.collect(Collectors.toList());
CameraUpdate update = CameraUtils.frameLocationOrPolygon(null, pointList);
if (update != null) {
map.easeCamera(update);
}
currentIndex = (currentIndex + 1) % allLines.size();
}
});
}
@Override
public void onStyleLoaded(Style style) {
// Load lines from the GeoJson file
try {
InputStreamReader inputStreamReader = new InputStreamReader(getAssets().open("lines.json"));
StringBuilder jsonBuilder = new StringBuilder();
int charRead;
char[] buffer = new char[1024];
while ((charRead = inputStreamReader.read(buffer)) != -1) {
jsonBuilder.append(buffer, 0, charRead);
}
String geoJson = jsonBuilder.toString();
FeatureCollection featureCollection = FeatureCollection.fromJson(geoJson);
allLines = featureCollection.features().stream()
.map(feature -> (LineString) feature.geometry())
.collect(Collectors.toList());
// Create a GeoJsonSource with the loaded data
GeoJsonSource source = new GeoJsonSource(SOURCE_ID, featureCollection);
style.addSource(source);
// Create a LineLayer to display our source information
LineLayer lineLayer = new LineLayer(LAYER_ID, SOURCE_ID);
lineLayer.setProperties(
PropertyFactory.lineWidth(6f),
PropertyFactory.lineColor(Color.BLUE),
PropertyFactory.lineOpacity(.8f)
);
// Add the layer
style.addLayer(lineLayer);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onStart() {
super.onStart();
if (mapView != null) {
mapView.onStart();
}
}
@Override
protected void onResume() {
super.onResume();
if (mapView != null) {
mapView.onResume();
}
}
@Override
protected void onPause() {
super.onPause();
if (mapView != null) {
mapView.onPause();
}
}
@Override
protected void onStop() {
super.onStop();
if (mapView != null) {
mapView.onStop();
}
}
@Override
public void onLowMemory() {
super.onLowMemory();
if (mapView != null) {
mapView.onLowMemory();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mapView != null) {
mapView.onDestroy();
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (mapView != null) {
mapView.onSaveInstanceState(outState);
}
}
}
import android.app.Activity
import android.graphics.Color
import android.os.Bundle
import android.view.View
import android.widget.Button
import com.trimblemaps.account.LicensedFeature
import com.trimblemaps.account.TrimbleMapsAccountManager
import com.trimblemaps.account.models.TrimbleMapsAccount
import com.trimblemaps.geojson.FeatureCollection
import com.trimblemaps.geojson.LineString
import com.trimblemaps.geojson.Point
import com.trimblemaps.mapsdk.TrimbleMaps
import com.trimblemaps.mapsdk.camera.CameraPosition
import com.trimblemaps.mapsdk.camera.CameraUpdate
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 com.trimblemaps.mapsdk.style.layers.LineLayer
import com.trimblemaps.mapsdk.style.layers.PropertyFactory
import com.trimblemaps.mapsdk.style.sources.GeoJsonSource
import com.trimblemaps.mapsdk.plugins.places.common.utils.CameraUtils
import java.io.InputStreamReader
class SampleFramingActivity : Activity(), Style.OnStyleLoaded {
private var mapView: MapView? = null
private var map: TrimbleMapsMap? = null
private var currentIndex = 0
private val SOURCE_ID = "linesource"
private val LAYER_ID = "linelayer"
private lateinit var allLines: List<LineString>
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_framing)
// Set up the MapView from the layout
mapView = findViewById<View>(R.id.mapView) as MapView
// the onMapReadyCallback is fired when the map is ready to be worked with
mapView?.getMapAsync { trimbleMapsMap ->
map = trimbleMapsMap
val position = CameraPosition.Builder()
.target(LatLng(40.60902838712187, -97.73800045737227))
.zoom(2.5)
.build()
map?.cameraPosition = position
map?.setStyle(Style.MOBILE_DAY, this@SampleFramingActivity)
}
// When the button is clicked, cycle through the lines using trimbleMapsMap.moveCamera
findViewById<Button>(R.id.btn_cycleLocations).setOnClickListener {
map?.let { trimbleMapsMap ->
if (allLines.isNotEmpty()) {
val selectedLine = allLines[currentIndex]
val pointList = selectedLine.coordinates().map { point ->
Point.fromLngLat(point.longitude(), point.latitude())
}
val update: CameraUpdate? = CameraUtils.frameLocationOrPolygon(
null, // No specific location to frame
pointList
)
if (update != null) {
trimbleMapsMap.moveCamera(update)
}
currentIndex = (currentIndex + 1) % allLines.size
}
}
}
// When the button is clicked, cycle through the lines using trimbleMapsMap.easeCamera
findViewById<Button>(R.id.btn_easeCamera).setOnClickListener {
map?.let { trimbleMapsMap ->
if (allLines.isNotEmpty()) {
val selectedLine = allLines[currentIndex]
val pointList = selectedLine.coordinates().map { point ->
Point.fromLngLat(point.longitude(), point.latitude())
}
val update: CameraUpdate? = CameraUtils.frameLocationOrPolygon(
null, // No specific location to frame
pointList
)
if (update != null) {
trimbleMapsMap.easeCamera(update)
}
currentIndex = (currentIndex + 1) % allLines.size
}
}
}
}
override fun onStyleLoaded(style: Style) {
// Load lines from the GeoJson file
try {
val inputStream = assets.open("lines.json")
val geoJson = InputStreamReader(inputStream).readText()
val featureCollection = FeatureCollection.fromJson(geoJson)
allLines = featureCollection.features()?.mapNotNull { feature ->
feature.geometry() as? LineString
} ?: emptyList()
// Create a GeoJsonSource with the loaded data
val source = GeoJsonSource(SOURCE_ID, featureCollection)
style.addSource(source)
// Create a LineLayer to display our source information.
val lineLayer = LineLayer(LAYER_ID, SOURCE_ID)
lineLayer.setProperties(
PropertyFactory.lineWidth(6f),
PropertyFactory.lineColor(Color.BLUE),
PropertyFactory.lineOpacity(.8f)
)
// Add the layer
style.addLayer(lineLayer)
} catch (e: Exception) {
e.printStackTrace()
}
}
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()
}
override fun onSaveInstanceState(outState: Bundle) {
if (outState != null) {
super.onSaveInstanceState(outState)
mapView?.onSaveInstanceState(outState)
}
}
}