Marker Customization
Why marker customization exists: Different use cases require different marker appearances. A navigation app might need simple pins, while a retail venue map might need branded icons with labels. The LzAnnotationConfiguration API provides full control over marker appearance — icon shape, color, text styling, and behavior — achieving feature parity with the iOS SDK.
Why a builder pattern: Markers have many optional properties with sensible defaults. The builder pattern lets you configure only the properties you need, keeping simple cases simple while supporting advanced customization.
The SDK provides LzAnnotationConfiguration and its fluent builder LzAnnotationConfigurationBuilder for comprehensive marker customization. Use these with LazarilloMap.addAnnotationWith() to add fully styled markers to the map.
Basic Marker
The simplest annotation requires only an id and a coordinate. All visual properties use their defaults (circle-clipped icon at normal size with full opacity).
val config = LzAnnotationConfiguration.builder("marker-1", LatLng(-33.45, -70.66))
.build()
lzMap.addAnnotationWith(config) { result ->
result.onSuccess { markerId ->
println("Marker added: $markerId")
}
result.onFailure { error ->
println("Failed: ${error.message}")
}
}Marker with Styled Text
Add a text label alongside the marker. You can control the font size, color, position relative to the icon, and halo (outline) effects for readability.
val config = LzAnnotationConfiguration.builder("entrance", LatLng(-33.45, -70.66))
.text("Main Entrance")
.textColor("#FFFFFF")
.textFontSize(14f)
.textPosition(TextPosition.BOTTOM)
.textHaloColor("#000000")
.textHaloWidth(2f)
.build()
lzMap.addAnnotationWith(config) { result ->
result.onSuccess { markerId ->
println("Marker with text added: $markerId")
}
}Text Position Options
The TextPosition enum controls where the text label appears relative to the icon:
| Value | Description |
|---|---|
TextPosition.TOP | Text above the icon (default) |
TextPosition.BOTTOM | Text below the icon |
TextPosition.LEFT | Text to the left of the icon |
TextPosition.RIGHT | Text to the right of the icon |
Text Background Color
Use textBackgroundColor to render a solid-colored background behind the text label. This is useful for ensuring text readability over complex map content. When set, it overrides textHaloColor and textHaloWidth.
val config = LzAnnotationConfiguration.builder("labeled-poi", LatLng(-33.45, -70.66))
.text("Gate A")
.textColor("#FFFFFF")
.textFontSize(13f)
.textBackgroundColor("#1A73E8")
.textPosition(TextPosition.BOTTOM)
.build()
lzMap.addAnnotationWith(config) { result ->
result.onSuccess { markerId ->
println("Marker with text background added: $markerId")
}
}Tinted Icon with Background
Apply a color tint to the icon and add a background color drawn behind it. The borderColor draws a colored area behind the icon with proportional padding (~12%).
val config = LzAnnotationConfiguration.builder("tinted-marker", LatLng(-33.45, -70.66))
.iconColor("#FF5722")
.iconSize(1.5f)
.borderColor("#333333")
.build()
lzMap.addAnnotationWith(config) { result ->
result.onSuccess { markerId ->
println("Tinted marker added: $markerId")
}
}Icon Shape (Corner Radius)
The iconCornerRadius property controls the shape of the icon:
| Value | Shape |
|---|---|
-1 (default) | Circle |
0 | Square |
> 0 | Rounded rectangle with that corner radius |
// Circular icon (default)
val circleConfig = LzAnnotationConfiguration.builder("circle", LatLng(-33.45, -70.66))
.iconCornerRadius(-1f)
.build()
// Square icon
val squareConfig = LzAnnotationConfiguration.builder("square", LatLng(-33.45, -70.67))
.iconCornerRadius(0f)
.build()
// Rounded rectangle icon
val roundedConfig = LzAnnotationConfiguration.builder("rounded", LatLng(-33.45, -70.68))
.iconCornerRadius(12f)
.build()Remote Image (URL)
Load a marker icon from a remote URL. The SDK handles downloading, scaling, and clipping the image asynchronously. SVG images are also supported.
val config = LzAnnotationConfiguration.builder("remote-icon", LatLng(-33.45, -70.66))
.imageUrl("https://example.com/icons/store-pin.png")
.iconSize(1.2f)
.text("Coffee Shop")
.textColor("#4E342E")
.textPosition(TextPosition.BOTTOM)
.build()
lzMap.addAnnotationWith(config) { result ->
result.onSuccess { markerId ->
println("Remote image marker added: $markerId")
}
}Drawable Resource Image
Reference a drawable resource by name using imageRef. The resource must exist in your app’s drawable resources.
val config = LzAnnotationConfiguration.builder("drawable-icon", LatLng(-33.45, -70.66))
.imageRef("ic_custom_pin")
.iconSize(1.0f)
.build()
lzMap.addAnnotationWith(config) { result ->
result.onSuccess { markerId ->
println("Drawable marker added: $markerId")
}
}Pre-created Bitmap
If you already have a Bitmap (for example, generated dynamically or loaded from a custom source), pass it directly using imageBitmap.
val myBitmap: Bitmap = // ... your bitmap
val config = LzAnnotationConfiguration.builder("bitmap-icon", LatLng(-33.45, -70.66))
.imageBitmap(myBitmap)
.iconCornerRadius(8f)
.iconSize(1.3f)
.build()
lzMap.addAnnotationWith(config) { result ->
result.onSuccess { markerId ->
println("Bitmap marker added: $markerId")
}
}Image Source Priority
When multiple image sources are set, the SDK uses the following priority order:
imageBitmap— highest priority (pre-created bitmap)imageUrl— remote image loaded asynchronouslyimageRef— drawable resource by name- Default marker icon — used when no image source is specified
Indoor Floor Markers
Assign a marker to a specific indoor floor using floorId. The marker will only be visible when that floor is active on the map.
val config = LzAnnotationConfiguration.builder("floor-marker", LatLng(-33.45, -70.66))
.floorId("floor-2")
.text("Room 204")
.textColor("#000000")
.textFontSize(12f)
.iconColor("#1976D2")
.build()
lzMap.addAnnotationWith(config) { result ->
result.onSuccess { markerId ->
println("Indoor marker added: $markerId")
}
}Behavior Properties
Control how markers interact with user gestures:
val config = LzAnnotationConfiguration.builder("interactive", LatLng(-33.45, -70.66))
.draggable(true) // User can drag the marker
.isFlat(true) // Marker lies flat on the map surface
.opacity(0.8f) // 80% opacity
.build()
lzMap.addAnnotationWith(config) { result ->
result.onSuccess { markerId ->
println("Interactive marker added: $markerId")
}
}| Property | Type | Default | Description |
|---|---|---|---|
opacity | Float | 1.0 | Marker transparency (0.0 = invisible, 1.0 = opaque) |
draggable | Boolean | false | Whether the user can drag the marker |
isFlat | Boolean | false | Whether the marker lies flat on the map surface |
Full Configuration Example
A comprehensive example combining multiple customization options:
val config = LzAnnotationConfiguration.builder("store-42", LatLng(-33.4500, -70.6600))
// Image
.imageUrl("https://example.com/logos/store-42.png")
// Text
.text("Electronics Store")
.textColor("#FFFFFF")
.textFontSize(13f)
.textPosition(TextPosition.BOTTOM)
.textBackgroundColor("#1565C0")
// Icon styling
.iconColor("#1565C0")
.iconSize(1.4f)
.iconCornerRadius(8f)
.borderColor("#0D47A1")
// Behavior
.opacity(0.95f)
.draggable(false)
.isFlat(false)
// Indoor
.floorId("floor-1")
.build()
lzMap.addAnnotationWith(config) { result ->
result.onSuccess { markerId ->
println("Fully customized marker added: $markerId")
}
result.onFailure { error ->
println("Error adding marker: ${error.message}")
}
}Property Reference
Image Properties
| Property | Type | Default | Description |
|---|---|---|---|
imageUrl | String? | null | URL to load a remote image (supports SVG) |
imageRef | String? | null | Drawable resource name |
imageBitmap | Bitmap? | null | Pre-created bitmap (highest priority) |
Text Properties
| Property | Type | Default | Description |
|---|---|---|---|
text | String? | null | Text label displayed alongside the marker |
textColor | String? | null | Hex color for the text (e.g., "#000000") |
textFontSize | Float | 12f | Font size in pixels |
textPosition | TextPosition | TOP | Position relative to the icon |
textHaloColor | String? | null | Hex color for text outline |
textHaloWidth | Float | 1.0f | Width of text outline in pixels |
textHaloBlur | Float | 0f | Blur radius of text outline |
textBackgroundColor | String? | null | Solid background color behind text |
Icon Properties
| Property | Type | Default | Description |
|---|---|---|---|
iconColor | String? | null | Hex color tint applied to the icon |
iconSize | Float | 1.0f | Scaling factor (1.0 = original size) |
iconCornerRadius | Float | -1f | Shape: -1=circle, 0=square, >0=rounded |
borderColor | String? | null | Background color drawn behind the icon |
Behavior Properties
| Property | Type | Default | Description |
|---|---|---|---|
opacity | Float | 1.0f | Transparency (0.0 to 1.0) |
draggable | Boolean | false | Whether the marker can be dragged |
isFlat | Boolean | false | Whether the marker lies flat on the map |
floorId | String? | null | Indoor floor identifier |