Clickable Points
Contents
The Mobile Maps SDK examples require that you first complete the initial project set-up.
Example showing how to click on locations on the map and display any associated data.
activity_sample_framing.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent">
<com.trimblemaps.mapsdk.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</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>
import android.app.Activity;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.PointF;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import com.trimblemaps.geojson.Feature;
import com.trimblemaps.geojson.FeatureCollection;
import com.trimblemaps.geojson.Point;
import com.trimblemaps.mapsdk.TrimbleMaps;
import com.trimblemaps.mapsdk.camera.CameraPosition;
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.PropertyFactory;
import com.trimblemaps.mapsdk.style.layers.SymbolLayer;
import com.trimblemaps.mapsdk.style.sources.GeoJsonSource;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;
public class SampleClickablePointsActivity extends Activity implements Style.OnStyleLoaded {
private MapView mapView;
private TrimbleMapsMap map;
private static final String SOURCE_ID = "tristatepoints";
private static final String LAYER_ID = "tristatepoints";
private static final String ICON_ID = "location-icon";
@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_clickable_points);
// 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(41.36290180612575, -74.6946761628674))
.zoom(13.0)
.build();
map.setCameraPosition(position);
map.setStyle(Style.SATELLITE, this);
});
}
@Override
public void onStyleLoaded(Style style) {
// Add the icon to the style
style.addImage(ICON_ID, BitmapFactory.decodeResource(getResources(), R.drawable.basic_icon_faqs));
// Load points from the GeoJson file
try {
InputStreamReader inputStream = new InputStreamReader(getAssets().open("tristate.json"));
BufferedReader bufferedReader = new BufferedReader(inputStream);
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
String geoJson = stringBuilder.toString();
FeatureCollection featureCollection = FeatureCollection.fromJson(geoJson);
// Create a GeoJsonSource with the loaded data
GeoJsonSource source = new GeoJsonSource(SOURCE_ID, featureCollection);
style.addSource(source);
// Create a SymbolLayer to display our source information as icons
SymbolLayer symbolLayer = new SymbolLayer(LAYER_ID, SOURCE_ID);
symbolLayer.setProperties(
PropertyFactory.iconImage(ICON_ID),
PropertyFactory.iconSize(1.0f),
PropertyFactory.iconColor(Color.RED)
);
// Add the layer
style.addLayer(symbolLayer);
// Set up a click listener to show a popup with state and coordinates information
map.addOnMapClickListener(point -> {
PointF screenPoint = map.getProjection().toScreenLocation(point);
List<Feature> features = map.queryRenderedFeatures(screenPoint, LAYER_ID);
if (!features.isEmpty()) {
Feature feature = features.get(0);
String state = feature.getStringProperty("state");
List<Double> coordinates = ((Point) feature.geometry()).coordinates();
String message = "State: " + state + "\nCoordinates: " + coordinates;
// Create and show the popup
new AlertDialog.Builder(this)
.setTitle("Location Info")
.setMessage(message)
.setPositiveButton("OK", (dialog, which) -> dialog.dismiss())
.show();
}
return true;
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onStart() {
super.onStart();
mapView.onStart();
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public void onStop() {
super.onStop();
mapView.onStop();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
}
import android.app.Activity
import android.graphics.BitmapFactory
import android.graphics.Color
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AlertDialog
import com.trimblemaps.geojson.FeatureCollection
import com.trimblemaps.geojson.Point
import com.trimblemaps.mapsdk.TrimbleMaps
import com.trimblemaps.mapsdk.camera.CameraPosition
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.PropertyFactory
import com.trimblemaps.mapsdk.style.layers.SymbolLayer
import com.trimblemaps.mapsdk.style.sources.GeoJsonSource
import java.io.InputStreamReader
class SampleClickablePointsActivity : Activity(), Style.OnStyleLoaded {
private var mapView: MapView? = null
private var map: TrimbleMapsMap? = null
private val SOURCE_ID = "tristatepoints"
private val LAYER_ID = "tristatepoints"
private val ICON_ID = "location-icon"
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_clickable_points)
// 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 -> // The TrimbleMapsMap object is created, now a style can be applied to render a map.
map = trimbleMapsMap
val position = CameraPosition.Builder()
.target(LatLng(41.36290180612575, -74.6946761628674))
.zoom(13.0)
.build()
map?.cameraPosition = position
map?.setStyle(Style.SATELLITE, this@SampleClickablePointsActivity)
}
}
override fun onStyleLoaded(style: Style) {
// Add the icon to the style
val iconBitmap = BitmapFactory.decodeResource(resources, R.drawable.basic_icon_faqs)
style.addImage(ICON_ID, iconBitmap)
// Load points from the GeoJson file
try {
val inputStream = assets.open("tristate.json")
val geoJson = InputStreamReader(inputStream).readText()
val featureCollection = FeatureCollection.fromJson(geoJson)
// Create a GeoJsonSource with the loaded data
val source = GeoJsonSource(SOURCE_ID, featureCollection)
style.addSource(source)
// Create a SymbolLayer to display our source information as icons
val symbolLayer = SymbolLayer(LAYER_ID, SOURCE_ID)
symbolLayer.setProperties(
PropertyFactory.iconImage(ICON_ID),
PropertyFactory.iconSize(1.0f),
PropertyFactory.iconColor(Color.RED)
)
// Add the layer
style.addLayer(symbolLayer)
// Set up a click listener to show a popup with state and coordinates information
map?.addOnMapClickListener { point ->
val screenPoint = map?.projection?.toScreenLocation(point)
val features = map?.queryRenderedFeatures(screenPoint!!, LAYER_ID)
if (!features.isNullOrEmpty()) {
val feature = features[0]
val state = feature.getStringProperty("state")
val coordinates = (feature.geometry() as Point).coordinates()
val message = "State: $state\nCoordinates: $coordinates"
// Create and show the popup
AlertDialog.Builder(this)
.setTitle("Location Info")
.setMessage(message)
.setPositiveButton("OK") { dialog, _ -> dialog.dismiss() }
.show()
}
true
}
} 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)
}
}
}