I'm using the Mapbox Maps SDK for Android to display pins with custom icons in a map on my app. More specifically, I'm using the SymbolLayer API. When the user clicks on a pin, its appearance changes to show it is selected. However, that clicked pin is often behind other pins, like in this image:
All those pins are Feature
s from the same Source
, added to the same SymbolLayer
.
I want to be able to make the selected pin appear above the other pins, and for that I'm trying to control its z axis. I'm playing around with the PropertyFactory.symbolZOrder(value)
method and it seems that neither Property.SYMBOL_Z_ORDER_VIEWPORT_Y
nor Property.SYMBOL_Z_ORDER_SOURCE
will be of help. I'm hopeful that I will be able to achieve that with an Expression
but I have no idea on how to use it.
Any thoughts?
here's an example with explanations.
You should set the properties symbolZOrder
and symbolSortKey
when defining the symbol layer.
symbolZOrder
accept one of the following as argument:
// SYMBOL_Z_ORDER: Controls the order in which overlapping symbols in the same layer are rendered
/**
* If symbol sort key is set, sort based on that. Otherwise sort symbols by their y-position relative to the viewport.
*/
public static final String SYMBOL_Z_ORDER_AUTO = "auto";
/**
* Symbols will be sorted by their y-position relative to the viewport.
*/
public static final String SYMBOL_Z_ORDER_VIEWPORT_Y = "viewport-y";
/**
* Symbols will be rendered in the same order as the source data with no sorting applied.
*/
public static final String SYMBOL_Z_ORDER_SOURCE = "source";
so if you wish to control the symbols based on some logic you should use the SYMBOL_Z_ORDER_AUTO
value.
then you can set the symbolSortKey
to some float value.
Style.OnStyleLoaded onStyleLoaded = style -> {
style.addLayer(new SymbolLayer(SYMBOLS_LAYER, SYMBOLS_SOURCE)
.withProperties(
iconImage(step(zoom(),
literal("marker_public_base"),
stop(6, get("icon")))),
iconIgnorePlacement(true),
iconAllowOverlap(true),
iconSize(interpolate(
linear(), zoom(),
stop(0, MARKER_SYMBOL_SIZE * .13),
stop(5, MARKER_SYMBOL_SIZE * .33),
stop(9, MARKER_SYMBOL_SIZE))),
iconAnchor(ICON_ANCHOR_BOTTOM),
textField(get("title")),
textSize(interpolate(
linear(), zoom(),
stop(5.9, 0),
stop(6, SYMBOL_TEXT_SIZE * .4),
stop(7, SYMBOL_TEXT_SIZE * .7),
stop(11, SYMBOL_TEXT_SIZE))),
textOptional(true),
textHaloColor("#ffffff"),
textHaloWidth(1f),
textHaloBlur(1f),
textAnchor(TEXT_ANCHOR_TOP),
symbolZOrder(SYMBOL_Z_ORDER_AUTO),
symbolSortKey(get("zIndex"))
));
where
points.forEach(point -> {
Feature feature = Feature.fromGeometry(com.mapbox.geojson.Point.fromLngLat(point.lon, point.lat));
feature.addStringProperty("id", point.id);
feature.addNumberProperty("zIndex", point.isPublic? 0f : point.isSearchResult? 2f : 1f);
feature.addStringProperty("title", point.name);
feature.addStringProperty("icon", getIconImageID(point.category, point.isPublic, point.visited));
symbolsFeatures.add(feature);
});