Skip to main content

View annotations

View annotations are Views in SwiftUI and UIViews in UIKit that the SDK draws on top of a Mapbox Map or MapView. They can be bound to a Geometry or to a feature rendered on a Layer. This can be helpful for achieving common patterns used in maps in mobile applications, such as showing an information window when tapping a point of interest (POI), or providing estimated time of arrival (ETA) for navigation purposes along a route.

Benefits:

  • Straight-forward API that allows adding a Swift View or UIView as a view annotation, integrating with your existing SwiftUI or UIKit code.
  • High rendering performance when using a reasonable number of views (generally below 100, but may vary based on the view's content and the user's device model).
  • Wide number of options including allowing overlap between view annotations, selected state, connecting to a map feature, and more.

Limitations:

  • Inefficient and poor performance when adding many features (> 250) to the map if allow overlap is turned on.
  • Low-level API that requires adding code on the user's end for advanced cases.
  • No built-in support for clustering
Supported Layer types

The following layer types are supported for binding a view annotation to a feature:

Create a view annotation

Add a MapViewAnnotation inside the Map block. The MapViewAnnotation requires a coordinate and a SwiftUI View as its content.

let centerCoordinate = CLLocationCoordinate2D(latitude: 39.7128, longitude: -75.0060)
Map(initialViewport: .camera(center: centerCoordinate, zoom: 7)) {
MapViewAnnotation(coordinate: centerCoordinate) {
Text("Hello world!")
.font(.system(size: 14))
.lineLimit(0)
.foregroundColor(.black)
.multilineTextAlignment(.center)
.background(Color.white)
}
.priority(0) // To bring a view annotation on top of others regardless of the order in which it was added
}
More view annotation options

There are many more options available when adding or updating the view annotation. See the complete list of options in theViewAnnotation documentation.

Customize the appearance

Specify order

The z-index of view annotations is based on the order in which they are added. This allows you to control which view is visible when multiple views intersect on the screen.

To bring a view annotation on top of others regardless of the order in which it was added, use the priority property (or the .priority() modifier in SwiftUI). View annotations with higher priority values appear in front of those with lower priority values. The default priority value is 0.

MapViewAnnotation(coordinate: coordinate) {
Text("Hello world!")
}
.priority(10)

If multiple view annotations have the same priority, their z-index is determined by the order in which they were added.

Default order
View annotations with z-index based on the order in which they were added: Hello world!, Прывітанне Сусвет!, Hallo Welt!, Hei maailma!
Override order
Use the selected property to bring the Hello world! annotation on top of others regardless of the order in which they were added.

View annotations do not rotate, pitch, or scale with the map, but some properties (including width, height, and additional offset in pixels) can be controlled by the user using ViewAnnotationAnchorConfig. You can provide multiple anchor configurations for an annotation. The map renderer will automatically pick the first suitable anchor position depending on position relative to other view annotations or its annotated feature on the map, and notifies the change of anchor using ViewAnnotation/onAnchorChanged.

@State var selectedAnchor: ViewAnnotationAnchorConfig?
...
Map() {
MapViewAnnotation(
coordinate: CLLocationCoordinate2D(latitude: 40.0, longitude: -72.0)) {
Text("Hello world!")
}
.variableAnchors([
ViewAnnotationAnchorConfig(anchor: .top, offsetX: 10, offsetY: 10),
ViewAnnotationAnchorConfig(anchor: .bottom)
])
.onAnchorChanged { config in
selectedAnchor = config
}
}

Handle visibility

When a view annotation is added or updated, visibility can be specified explicitly. An annotation becomes hidden when it goes out of map view’s bounds or visible property is changed. You can listen to the event when the annotation's visibility has changed using ViewAnnotation/onVisibilityChanged.

viewAnnotation.visible = false
viewAnnotation.onVisibilityChanged = { isVisible in
// Handle visibility changes here
}
Do not modify the UIView's isHidden property

Do not change the UIView's isHidden property directly. When setting visible to false, it will set the view to hidden and also remove it from the layout calculation.

Handle content size updates

You do not need to explicitly set size for a view annotation, however, when you do some operation that results in content size changed, you should call ViewAnnotation/setNeedsUpdateSize() to update the annotation size.

updateViewSize(width: 100, height: 100)
viewAnnotation.setNeedsUpdateSize() // Updates the annotation size.

Common uses

The flexibility of view annotations means that there are countless ways to use this feature, but there are a few common uses outlined below to help you get started.

Display on map click

You can add view annotations when a user interacts with the map.

When the user clicks on the map, you can get information from the map camera, position (like in the example linked below), or data in the map to determine the contents of the view annotation using one of MapboxMap's map feature query methods.

EXAMPLE
Add view annotations

Add view annotation on a map click.

Attach to a geometry

You can tie a view annotation to a geometry, for example, a line string. This allows the annotation to stay visible on screen along with the visible part of the line string.

EXAMPLE
Dynamic view annotations

Use Dynamic View Annotations, Style, and Viewport API to create navigation experience

Attach to an annotated feature

You can tie a view annotation's visibility to an annotated feature's visibility using AnnotatedFeature. This allows you to implement marker pop-ups with a minimal amount of code and make the view annotation disappear automatically, if the point annotation image is not visible due to overlap or collision.

Map() {
PointAnnotation(id: "some-id", coordinate: coordinate)
.iconImage("marker-image-name")
.iconAnchor(.bottom)

MapViewAnnotation(layerId: "some-id") { Text("Annotation view") }
.variableAnchors([
ViewAnnotationAnchorConfig(anchor: .bottom, offsetY: markerImageHeight)
])
}
Add AnnotationView class to your project

This example uses AnnotationView. To use this code snippet, you must also add the AnnotationView class, a custom class defined in the Maps SDK for the iOS Examples App.

EXAMPLE
View annotations: attach to a point annotation

Add view annotation anchored to a point annotation.

Note

While the View Annotation API does not come with built-in logic for handling opening and closing a callout attached to a symbol layer feature when the feature is click, you can see one possible way to implement that functionality in the Add a view annotation attached to a symbol layer example.

EXAMPLE
Add view annotations connected to features

Add view annotation anchored to a symbol layer feature.

Was this page helpful?