MapsGL Android - Wind speed text labels using custom GeoJSON
The points in this example are your own: 19 cities around Puget Sound, written into the activity as GeoJSON. A query layer reads the wind-speeds layer at each city and labels it with the value, with the city’s name beneath.
It is the Android port of the MapsGL JS Wind speed text labels using custom GeoJSON example. The complete activity ships in the MapsGL Android SDK demo as QueryLayerStaticGeoJsonActivity.

The sampled layer, at high quality
As in JS, the wind layer is requested at DataQuality.high, which is set on the layer before it is added. The labels sample this layer, so its quality sets the quality of the numbers:
val winds = WeatherService.WindSpeeds(controller.service)
winds.layer.quality = DataQuality.high
controller.addWeatherLayer(winds)The activity keeps the layer’s code and passes it to the query layer, so the labels always sample the layer that was actually added.
Inline points with a nested name
Each feature is a Point with a place object holding a name, the same shape the places API returns. The collection is parsed and assigned to the descriptor before the source is registered:
val cities = GeoJSONSourceDescriptor(id = "cities")
cities.data = FeatureCollection.fromJson(PUGET_SOUND_CITIES)
controller.addSource(cities)Because the shape matches, the query layer and its name label are the same as the ones used over API places.
Two text blocks on one query layer
DataQueryLayerDescriptor is the JS type: 'query' layer, with sampledLayerCode in place of queryLayer. Its paint has two TextPaint blocks. The first is the sampled value, large and bold. The second is the name, small and anchored below the value:
TextPaint(
value = StyleValue.Expression(Expression.get("place.name")),
size = StyleValue.Constant(12.0),
color = StyleValue.Constant(Color.Black),
outlineColor = StyleValue.Constant(Color.White),
anchor = StyleValue.Constant(Anchor.TOP),
offset = StyleValue.Constant(AnchorOffset(0.0, 20.0)),
)labelKeyPath = "place.name" tells the layer where the name lives on each feature. pitchWithMap and rotateWithMap are off, as in JS, so the labels stay upright and flat to the screen.
The value comes from the SDK, not the JS expression
The JS value wraps dataValue in a to-unit expression that treats the wind speed as a temperature and converts it from Celsius to Fahrenheit. The Android label uses the plain Expression.variable("dataValue"). The SDK has already converted that value from the wind layer’s own units into the map’s speed unit.
The demo adds three controls the JS example does not have:
- Show names rebuilds the query layer with or without the name block. It starts on.
- Label size scales both blocks and the gap between them, from half to twice the JS size.
- Show units sets
MapboxMapController.showTextLabelUnits, so12reads12 mph. The labels reformat without being sampled again.
JS also sets fadeOpacity to false. Android has no such setting, so the labels fade in as symbols normally do.
Related
- Temperature text labels using GeoJSON places: the same query layer over points requested from the places API
- Adding custom GeoJSON data: the ways to give a GeoJSON source its features