Skip to content

Commit db519f7

Browse files
mapbox-github-ci-writer-5[bot]pjleonard37
authored andcommitted
[Backport release/v0.17] Add custom vector icons examples for iOS and Android (#8507)
Backport b92c8c82cc24c5029b212e91db70518342cc260d from #8285. cc @mapbox/maps-ios cc @mapbox/maps-android Co-authored-by: Patrick Leonard <[email protected]> GitOrigin-RevId: f39812846df50b064bae04631c1b81911b0e9791
1 parent 74c549d commit db519f7

File tree

7 files changed

+141
-177
lines changed

7 files changed

+141
-177
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -738,18 +738,6 @@
738738
android:name="android.support.PARENT_ACTIVITY"
739739
android:value=".ExampleOverviewActivity" />
740740
</activity>
741-
<activity
742-
android:name=".examples.markersandcallouts.IconSizeChangeOnClickActivity"
743-
android:description="@string/description_change_icon_size"
744-
android:exported="true"
745-
android:label="@string/activity_style_change_icon_size_title">
746-
<meta-data
747-
android:name="@string/category"
748-
android:value="@string/category_markers_and_callouts" />
749-
<meta-data
750-
android:name="android.support.PARENT_ACTIVITY"
751-
android:value=".ExampleOverviewActivity" />
752-
</activity>
753741
<activity
754742
android:name=".examples.markersandcallouts.AddMarkersSymbolActivity"
755743
android:description="@string/description_add_marker_symbol"

app/src/main/java/com/mapbox/maps/testapp/examples/markersandcallouts/IconSizeChangeOnClickActivity.kt

Lines changed: 0 additions & 155 deletions
This file was deleted.

app/src/main/res/layout/activity_icon_size_change_on_click.xml

Lines changed: 0 additions & 10 deletions
This file was deleted.

compose-app/src/main/AndroidManifest.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@
9898
android:name="@string/category"
9999
android:value="@string/category_annotation" />
100100
</activity>
101+
<activity
102+
android:name=".examples.annotation.CustomVectorIconsActivity"
103+
android:description="@string/description_custom_vector_icons"
104+
android:exported="true"
105+
android:label="@string/activity_custom_vector_icons"
106+
android:parentActivityName=".ExampleOverviewActivity">
107+
<meta-data
108+
android:name="@string/category"
109+
android:value="@string/category_annotation" />
110+
</activity>
101111
<activity
102112
android:name=".examples.annotation.ViewAnnotationActivity"
103113
android:configChanges="orientation|screenSize|screenLayout"
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
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+
}

compose-app/src/main/res/values/example_descriptions.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
<string name="description_clip_layer">Showcase the usage of clip layer.</string>
3030
<string name="description_interactions">Showcase the interactions.</string>
3131
<string name="description_appearances">Change icon images dynamically using the Appearances API with feature-state</string>
32+
<string name="description_custom_vector_icons">Dynamically style vector icons with custom colors and interactively change their size on tap</string>
3233
<string name="description_precipitations">Showcase the rain and snow effects.</string>
3334
<string name="description_color_theme">Showcase color theme.</string>
3435
<string name="description_elevated_line">Showcase line elevation</string>

compose-app/src/main/res/values/example_titles.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
<string name="activity_clip_layer">Clip layer example</string>
3030
<string name="activity_interactions">Interactions example</string>
3131
<string name="activity_appearances">Appearances</string>
32+
<string name="activity_custom_vector_icons">Custom Vector Icons</string>
3233
<string name="activity_precipitations">Precipitations example</string>
3334
<string name="activity_color_theme">Color theme example</string>
3435
<string name="activity_elevated_line">Elevated line example</string>

0 commit comments

Comments
 (0)