1+ package com.mapbox.maps.compose.testapp.examples.annotation
2+
3+ import android.os.Bundle
4+ import androidx.activity.ComponentActivity
5+ import androidx.activity.compose.setContent
6+ import androidx.compose.foundation.layout.fillMaxSize
7+ import androidx.compose.runtime.getValue
8+ import androidx.compose.runtime.mutableStateOf
9+ import androidx.compose.runtime.remember
10+ import androidx.compose.runtime.setValue
11+ import androidx.compose.ui.Modifier
12+ import com.mapbox.geojson.Feature
13+ import com.mapbox.geojson.Point
14+ import com.mapbox.maps.MapboxDelicateApi
15+ import com.mapbox.maps.MapboxExperimental
16+ import com.mapbox.maps.compose.testapp.ExampleScaffold
17+ import com.mapbox.maps.compose.testapp.ui.theme.MapboxMapComposeTheme
18+ import com.mapbox.maps.extension.compose.MapboxMap
19+ import com.mapbox.maps.extension.compose.animation.viewport.rememberMapViewportState
20+ import com.mapbox.maps.extension.compose.style.BooleanValue
21+ import com.mapbox.maps.extension.compose.style.DoubleValue
22+ import com.mapbox.maps.extension.compose.style.MapStyle
23+ import com.mapbox.maps.extension.compose.style.layers.ImageValue
24+ import com.mapbox.maps.extension.compose.style.layers.generated.SymbolLayer
25+ import com.mapbox.maps.extension.compose.style.sources.GeoJSONData
26+ import com.mapbox.maps.extension.compose.style.sources.generated.rememberGeoJsonSourceState
27+ import com.mapbox.maps.extension.style.expressions.dsl.generated.image
28+ import com.mapbox.maps.extension.style.expressions.dsl.generated.switchCase
29+ import com.mapbox.maps.extension.style.expressions.generated.Expression
30+
31+ /* *
32+ * Example demonstrating custom vector icons with dynamic styling and interaction.
33+ * This example shows how to:
34+ * - Dynamically colorize vector icons based on feature properties using the image expression
35+ * - Interactively change icon size by tapping on icons
36+ *
37+ * Vector icons are parameterized SVG images that can be styled at runtime. In this example,
38+ * three flag icons are colored red, yellow, and purple using the 'flagColor' property.
39+ * Tap any flag to toggle its size between 1x and 2x.
40+ *
41+ * For this example to work, the SVGs must live inside the map style. The SVG file was uploaded
42+ * to Mapbox Studio with the name `flag`, making it available for customization at runtime.
43+ * You can add vector icons to your own style in Mapbox Studio.
44+ */
45+ @OptIn(MapboxDelicateApi ::class , MapboxExperimental ::class )
46+ public class CustomVectorIconsActivity : ComponentActivity () {
47+ override fun onCreate (savedInstanceState : Bundle ? ) {
48+ super .onCreate(savedInstanceState)
49+ setContent {
50+ var selectedFlagId by remember { mutableStateOf<String ?>(null ) }
51+
52+ // Create GeoJSON source with three flag locations
53+ val geoJsonSource = rememberGeoJsonSourceState {
54+ generateId = BooleanValue (true )
55+ }
56+ geoJsonSource.data = GeoJSONData (createFlagFeatures())
57+
58+ val mapViewportState = rememberMapViewportState {
59+ setCameraOptions {
60+ zoom(16.0 )
61+ center(Point .fromLngLat(24.6881 , 60.185755 ))
62+ }
63+ }
64+
65+ MapboxMapComposeTheme {
66+ ExampleScaffold {
67+ MapboxMap (
68+ Modifier .fillMaxSize(),
69+ mapViewportState = mapViewportState,
70+ style = {
71+ MapStyle (style = " mapbox://styles/mapbox-map-design/cm4r19bcm00ao01qvhp3jc2gi" )
72+ }
73+ ) {
74+ // Create symbol layer with parameterized icon
75+ SymbolLayer (
76+ sourceState = geoJsonSource,
77+ layerId = " points"
78+ ) {
79+ interactionsState.onClicked { feature, _ ->
80+ feature.properties.optString(" id" ).takeIf { it.isNotEmpty() }?.let { id ->
81+ selectedFlagId = if (selectedFlagId == id) null else id
82+ }
83+ true
84+ }
85+ iconImage = ImageValue (
86+ image {
87+ literal(" flag" )
88+ imageOptions(" flag_color" to Expression .get(" flagColor" ))
89+ }
90+ )
91+ iconSize = DoubleValue (
92+ switchCase {
93+ eq {
94+ get { literal(" id" ) }
95+ literal(selectedFlagId ? : " " )
96+ }
97+ literal(2.0 )
98+ literal(1.0 )
99+ }
100+ )
101+ iconAllowOverlap = BooleanValue (true )
102+ }
103+ }
104+ }
105+ }
106+ }
107+ }
108+
109+ /* *
110+ * Creates GeoJSON features with flag locations and colors.
111+ */
112+ private fun createFlagFeatures (): List <Feature > {
113+ return listOf (
114+ createFlagFeature(" flag-red" , 24.68727 , 60.185755 , " red" ),
115+ createFlagFeature(" flag-yellow" , 24.68827 , 60.186255 , " yellow" ),
116+ createFlagFeature(" flag-purple" , 24.68927 , 60.186055 , " #800080" )
117+ )
118+ }
119+
120+ /* *
121+ * Creates a feature with a flag at the specified location and color.
122+ */
123+ private fun createFlagFeature (id : String , longitude : Double , latitude : Double , color : String ): Feature {
124+ val feature = Feature .fromGeometry(Point .fromLngLat(longitude, latitude))
125+ feature.addStringProperty(" id" , id)
126+ feature.addStringProperty(" flagColor" , color)
127+ return feature
128+ }
129+ }
0 commit comments