> For the complete documentation index, see [llms.txt](https://docs.mapbox.com/android/maps/llms.txt)

# View annotation with point annotation

![Animate a view annotation on screen.](https://docs.mapbox.com/android/assets/ideal-img/maps-examples-view-annotation-with-point-annotation.f97b389.480.png)

This example demonstrates how to add a view annotation to a point annotation on a map using the **Maps SDK for Android**. The functionality creates a map marker with popup-style content containing additional information. It utilizes various classes and interfaces from the Mapbox Maps SDK for Android, such as [`MapView`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps/-map-view/), [`Point`](https://docs.mapbox.com/android/java/api/libjava-geojson/7.3.1/), [`loadStyle`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps/-mapbox-map/load-style.html), and [`ViewAnnotationManager`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.viewannotation/-view-annotation-manager/), among others.

The activity includes methods to set up and configure the view annotation, handle marker interactions, update the camera position, and manage the visibility and position of the annotations. Users can interact with the marker by dragging and clicking on it to show or hide the associated view annotation view. Additionally, options are provided to reset the camera, toggle the visibility mode of the view annotation, and update the view annotation whenever the marker is dragged.

There are several ways to add markers, annotations, and other shapes to the map using the Maps SDK. To choose the appropriate approach for your application, read the [Markers and annotations](https://docs.mapbox.com/android/maps/guides/annotations/) guide.

> **Note: Android Examples App Available**
> 
> This example code is part of the **Maps SDK for Android Examples App**, a working Android project [available on GitHub](https://github.com/mapbox/mapbox-maps-android/tree/v11.28.0/). 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](https://docs.mapbox.com/help/tutorials/maps-sdk-android-examples-app/) tutorial for step-by-step instructions.

**Kotlin**

Title: `ViewAnnotationWithPointAnnotationActivity.kt`

[View on GitHub](https://github.com/mapbox/mapbox-maps-android/blob/v11.28.0/app/src/main/java/com/mapbox/maps/testapp/examples/markersandcallouts/viewannotation/ViewAnnotationWithPointAnnotationActivity.kt)

```kt
package com.mapbox.maps.testapp.examples.markersandcallouts.viewannotation

import android.annotation.SuppressLint
import android.graphics.Bitmap
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 androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import com.mapbox.geojson.Point
import com.mapbox.maps.CameraOptions
import com.mapbox.maps.MapView
import com.mapbox.maps.Style
import com.mapbox.maps.ViewAnnotationAnchor
import com.mapbox.maps.extension.style.layers.properties.generated.IconAnchor
import com.mapbox.maps.plugin.annotation.Annotation
import com.mapbox.maps.plugin.annotation.AnnotationConfig
import com.mapbox.maps.plugin.annotation.annotations
import com.mapbox.maps.plugin.annotation.generated.OnPointAnnotationDragListener
import com.mapbox.maps.plugin.annotation.generated.PointAnnotation
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager
import com.mapbox.maps.plugin.annotation.generated.PointAnnotationOptions
import com.mapbox.maps.plugin.annotation.generated.createPointAnnotationManager
import com.mapbox.maps.testapp.R
import com.mapbox.maps.testapp.databinding.ActivityViewAnnotationShowcaseBinding
import com.mapbox.maps.testapp.databinding.ItemCalloutViewBinding
import com.mapbox.maps.testapp.utils.BitmapUtils.bitmapFromDrawableRes
import com.mapbox.maps.viewannotation.ViewAnnotationManager
import com.mapbox.maps.viewannotation.ViewAnnotationUpdateMode
import com.mapbox.maps.viewannotation.annotationAnchor
import com.mapbox.maps.viewannotation.geometry
import com.mapbox.maps.viewannotation.viewAnnotationOptions

/**
 * Example how to add view annotation to the point annotation.
 */
class ViewAnnotationWithPointAnnotationActivity : AppCompatActivity() {

  private lateinit var viewAnnotationManager: ViewAnnotationManager
  private lateinit var pointAnnotationManager: PointAnnotationManager
  private lateinit var pointAnnotation: PointAnnotation
  private lateinit var viewAnnotation: View
  private lateinit var binding: ActivityViewAnnotationShowcaseBinding

  @SuppressLint("SetTextI18n")
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityViewAnnotationShowcaseBinding.inflate(layoutInflater)
    setContentView(binding.root)

    viewAnnotationManager = binding.mapView.viewAnnotationManager

    resetCamera()

    binding.mapView.mapboxMap.loadStyle(Style.STANDARD) {
      prepareAnnotationMarker(binding.mapView, bitmapFromDrawableRes(R.drawable.ic_blue_marker))
      prepareViewAnnotation()
      // show / hide view annotation based on a marker click
      pointAnnotationManager.addClickListener { clickedAnnotation ->
        if (pointAnnotation == clickedAnnotation) {
          viewAnnotation.toggleViewVisibility()
        }
        true
      }
      // show / hide view annotation based on marker visibility
      binding.fabStyleToggle.setOnClickListener {
        if (pointAnnotation.iconImageBitmap == null) {
          pointAnnotation.iconImageBitmap = bitmapFromDrawableRes(R.drawable.ic_blue_marker)
          viewAnnotation.isVisible = true
        } else {
          pointAnnotation.iconImageBitmap = null
          viewAnnotation.isVisible = false
        }
        pointAnnotationManager.update(pointAnnotation)
      }

      // reset annotations and camera position
      binding.fabReframe.setOnClickListener {
        resetCamera()
        pointAnnotation.point = POINT
        pointAnnotationManager.update(pointAnnotation)
        syncAnnotationPosition()
      }

      // update view annotation geometry if dragging the marker
      pointAnnotationManager.addDragListener(object : OnPointAnnotationDragListener {
        override fun onAnnotationDragStarted(annotation: Annotation<*>) {
        }

        override fun onAnnotationDrag(annotation: Annotation<*>) {
          if (annotation == pointAnnotation) {
            syncAnnotationPosition()
          }
        }

        override fun onAnnotationDragFinished(annotation: Annotation<*>) {
        }
      })
    }
  }

  private fun resetCamera() {
    binding.mapView.mapboxMap.setCamera(
      CameraOptions.Builder()
        .center(POINT)
        .pitch(45.0)
        .zoom(12.5)
        .bearing(-17.6)
        .build()
    )
  }

  private fun syncAnnotationPosition() {
    viewAnnotationManager.updateViewAnnotation(
      viewAnnotation,
      viewAnnotationOptions {
        geometry(pointAnnotation.geometry)
      }
    )
    ItemCalloutViewBinding.bind(viewAnnotation).apply {
      textNativeView.text = "lat=%.2f\nlon=%.2f".format(
        pointAnnotation.geometry.latitude(),
        pointAnnotation.geometry.longitude()
      )
    }
  }

  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)
    }
  }

  private fun View.toggleViewVisibility() {
    visibility = if (visibility == View.VISIBLE) View.GONE else View.VISIBLE
  }

  @SuppressLint("SetTextI18n")
  private fun prepareViewAnnotation() {
    viewAnnotation = viewAnnotationManager.addViewAnnotation(
      resId = R.layout.item_callout_view,
      options = viewAnnotationOptions {
        geometry(pointAnnotation.geometry)
        annotationAnchor {
          anchor(ViewAnnotationAnchor.BOTTOM)
          offsetY((pointAnnotation.iconImageBitmap?.height!!.toDouble()))
        }
      }
    )
    ItemCalloutViewBinding.bind(viewAnnotation).apply {
      textNativeView.text = "lat=%.2f\nlon=%.2f".format(POINT.latitude(), POINT.longitude())
      closeNativeView.setOnClickListener {
        viewAnnotationManager.removeViewAnnotation(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"
        (button.layoutParams as ViewGroup.MarginLayoutParams).apply {
          bottomMargin += pxDelta
          rightMargin += pxDelta
          leftMargin += pxDelta
        }
        button.requestLayout()
      }
    }
  }

  private fun prepareAnnotationMarker(mapView: MapView, iconBitmap: Bitmap) {
    val annotationPlugin = mapView.annotations
    val pointAnnotationOptions: PointAnnotationOptions = PointAnnotationOptions()
      .withPoint(POINT)
      .withIconImage(iconBitmap)
      .withIconAnchor(IconAnchor.BOTTOM)
      .withDraggable(true)
    pointAnnotationManager = annotationPlugin.createPointAnnotationManager(
      AnnotationConfig(
        layerId = LAYER_ID
      )
    )
    pointAnnotation = pointAnnotationManager.create(pointAnnotationOptions)
  }

  private companion object {
    const val SELECTED_ADD_COEF_PX = 25
    val POINT: Point = Point.fromLngLat(0.381457, 6.687337)
    val LAYER_ID = "layer-id"
  }
}
```