All docschevron-rightMaps SDK for Androidchevron-rightarrow-leftExampleschevron-rightAdd a view annotation

Add a view annotation

Add a ViewAnnotation to a MapView when the map is clicked.

activity_view_annotation_showcase
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.mapbox.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_style_toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_layers_24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:backgroundTint="@color/blue"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_reframe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_baseline_refresh_24"
app:layout_constraintBottom_toTopOf="@+id/fab_style_toggle"
app:layout_constraintEnd_toEndOf="parent"
tools:backgroundTint="@color/blue"/>
</androidx.constraintlayout.widget.ConstraintLayout>
ViewAnnotationBasicAddActivity.kt
package com.mapbox.maps.testapp.examples.markersandcallouts.viewannotation
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.mapbox.geojson.Point
import com.mapbox.maps.*
import com.mapbox.maps.plugin.animation.flyTo
import com.mapbox.maps.plugin.gestures.*
import com.mapbox.maps.testapp.R
import com.mapbox.maps.testapp.databinding.ActivityViewAnnotationShowcaseBinding
import com.mapbox.maps.testapp.databinding.ItemCalloutViewBinding
import com.mapbox.maps.viewannotation.ViewAnnotationManager
import com.mapbox.maps.viewannotation.ViewAnnotationUpdateMode
import com.mapbox.maps.viewannotation.geometry
import com.mapbox.maps.viewannotation.viewAnnotationOptions
/**
* Example how to add view annotations by clicking on the map.
*/
class ViewAnnotationBasicAddActivity : AppCompatActivity(), OnMapClickListener {
private lateinit var mapboxMap: MapboxMap
private lateinit var viewAnnotationManager: ViewAnnotationManager
private val viewAnnotationViews = mutableListOf<View>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityViewAnnotationShowcaseBinding.inflate(layoutInflater)
setContentView(binding.root)
viewAnnotationManager = binding.mapView.viewAnnotationManager
mapboxMap = binding.mapView.mapboxMap.apply {
loadStyle(Style.STANDARD) {
addOnMapClickListener(this@ViewAnnotationBasicAddActivity)
binding.fabStyleToggle.setOnClickListener {
when (style?.styleURI) {
Style.STANDARD -> loadStyle(Style.SATELLITE_STREETS)
Style.SATELLITE_STREETS -> loadStyle(Style.STANDARD)
}
}
Toast.makeText(this@ViewAnnotationBasicAddActivity, STARTUP_TEXT, Toast.LENGTH_LONG).show()
}
}
binding.fabReframe.setOnClickListener {
if (viewAnnotationViews.isNotEmpty()) {
val cameraOptions = viewAnnotationManager.cameraForAnnotations(viewAnnotationViews)
cameraOptions?.let {
mapboxMap.flyTo(it)
}
} else {
Toast.makeText(this@ViewAnnotationBasicAddActivity, ADD_VIEW_ANNOTATION_TEXT, Toast.LENGTH_LONG).show()
}
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_view_annotation, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.action_view_annotation_fixed_delay -> {
viewAnnotationManager.setViewAnnotationUpdateMode(ViewAnnotationUpdateMode.MAP_FIXED_DELAY)
true
}
R.id.action_view_annotation_map_synchronized -> {
viewAnnotationManager.setViewAnnotationUpdateMode(ViewAnnotationUpdateMode.MAP_SYNCHRONIZED)
true
}
else -> super.onOptionsItemSelected(item)
}
}
override fun onMapClick(point: Point): Boolean {
addViewAnnotation(point)
return true
}
@SuppressLint("SetTextI18n")
private fun addViewAnnotation(point: Point) {
val viewAnnotation = viewAnnotationManager.addViewAnnotation(
resId = R.layout.item_callout_view,
options = viewAnnotationOptions {
geometry(point)
allowOverlap(true)
ignoreCameraPadding(true)
allowOverlapWithPuck(true)
}
)
viewAnnotationViews.add(viewAnnotation)
ItemCalloutViewBinding.bind(viewAnnotation).apply {
textNativeView.text = "lat=%.2f\nlon=%.2f".format(point.latitude(), point.longitude())
closeNativeView.setOnClickListener {
viewAnnotationManager.removeViewAnnotation(viewAnnotation)
viewAnnotationViews.remove(viewAnnotation)
}
selectButton.setOnClickListener { b ->
val button = b as Button
val isSelected = button.text.toString().equals("SELECT", true)
val pxDelta = if (isSelected) SELECTED_ADD_COEF_PX else -SELECTED_ADD_COEF_PX
button.text = if (isSelected) "DESELECT" else "SELECT"
viewAnnotationManager.updateViewAnnotation(
viewAnnotation,
viewAnnotationOptions {
selected(isSelected)
}
)
(button.layoutParams as ViewGroup.MarginLayoutParams).apply {
bottomMargin += pxDelta
rightMargin += pxDelta
leftMargin += pxDelta
}
button.requestLayout()
}
}
}
private companion object {
const val SELECTED_ADD_COEF_PX = 25
const val STARTUP_TEXT = "Click on a map to add a view annotation."
const val ADD_VIEW_ANNOTATION_TEXT = "Add view annotations to re-frame map camera"
}
}
Was this example helpful?