MapsGL Android - Expressions
Expressions style vector layers from feature properties and the active timeline. Build them with the Expression factories, then wrap the result in StyleValue.Expression for a paint property or assign it to a layer filter.
See data-driven styling for end-to-end weather-layer examples.
Basic Syntax
Each factory returns an Expression whose raw value is a nested list: the operator first, then arguments.
["<operator>", <arg1>, <arg2>, ...]Expression.get("temperature")
StyleValue.Expression(Expression.get("COLOR"))Lookup
get
Reads a feature property. Dotted paths such as "alert.info.color" are expanded automatically via getPath.
Expression.get("temperature")
Expression.get("alert.info.color")literal
Wraps a value so it is not parsed as an expression. Used as a filter operand (for example with contains).
Expression.literal(listOf("Polygon", "MultiPolygon"))has
Returns true when the feature has the given property. Works in layer filters (including dotted paths) and in switchCase conditions.
Expression.has("COLOR")
Expression.has("alert.info.color")Control Flow
switchCase
Evaluates conditions in order and returns the first matching result (["case", …]). Use this on paint properties (color, size, image id). It is not evaluated as a layer filter.
Expression.switchCase(
listOf(
Expression.Case(Expression.lessThan(Expression.get("value"), 10), "low"),
Expression.Case(Expression.lessThan(Expression.get("value"), 20), "medium"),
),
"high",
)match
Compares an input against literal labels and returns the matching output. Works for paint and for boolean layer filters (including contains below).
Expression.match(
Expression.downcase(Expression.get("report.type")),
listOf(
Expression.Step("minor", "#dfcb01"),
Expression.Step("moderate", "#ff5d01"),
Expression.Step("major", "#ce0052"),
),
"#999999",
)coalesce
Returns the first non-null argument. Use it as a paint/value operand, not as a standalone filter.
Expression.coalesce(listOf(Expression.get("primary"), Expression.get("backup")))let / var
Bind a value once and reuse it in the result (Expression.bind / Expression.variable). Works for paint and for layer filters. Unbound names evaluate as missing (fail closed).
Expression.bind(
listOf(Expression.Variable("n", Expression.get("value"))),
Expression.multiply(Expression.variable("n"), 2),
)Scales
step
Maps a continuous input onto discrete outputs at stops. Works for paint color, number, and string values.
Expression.step(
Expression.get("age"),
listOf(
Expression.Step(null, "#ffffff"),
Expression.Step(60000, "#ffff00"),
Expression.Step(300000, "#ff0000"),
),
)For text and symbol size, the input may be Expression.zoom so the value follows map zoom. Do not use zoom in a layer filter — filters do not resolve it.
interpolate
Linear, exponential, or cubic-bezier blending between stops. Works for paint color and numeric paint (size, radius, weight).
Expression.interpolate(
Expression.get("magnitude"),
listOf(0.0, "rgba(0, 0, 255, 1)", 6.0, "rgba(255, 0, 0, 1)"),
)
Expression.interpolate(
Expression.zoom,
listOf(4, 2.0, 12, 16.0),
)
Expression.interpolateExponential(Expression.get("value"), 1.5, listOf(0.0, 1.0, 100.0, 10.0))
Expression.interpolateCubicBezier(
Expression.get("value"),
listOf(0.42, 0.0, 0.58, 1.0),
listOf(0.0, 1.0, 100.0, 10.0),
)Heatmap color ramps still use this operator on heatmap-density; that path is separate from fill/line/circle/symbol paint.
Mathematical Expressions
These evaluate on numeric paint properties:
Expression.add(Expression.get("value"), 2)
Expression.multiply(Expression.get("value"), 1.8)
Expression.subtract(Expression.get("max"), Expression.get("min"))
Expression.divide(Expression.get("value"), 2)
Expression.min(Expression.get("a"), Expression.get("b"))
Expression.max(Expression.get("a"), Expression.get("b"))
Expression.floor(Expression.get("value"))
Expression.ceil(Expression.get("value"))
Expression.abs(Expression.get("value"))
Expression.mod(Expression.get("value"), 10)
Expression.round(Expression.get("value"))
Expression.toNumber(Expression.get("value"))Comparison and Logic
Use these in layer filters and in switchCase conditions:
Expression.equals(Expression.get("CAT"), "flood")
Expression.notEquals(Expression.get("VTEC"), "FL.W")
Expression.greaterThan(Expression.get("value"), 100)
Expression.greaterThanOrEqual(Expression.get("value"), 0)
Expression.lessThanOrEqual(Expression.get("timestamp"), Expression.mapTime)and serializes as ["all", …], or as ["any", …]. contains compiles to a match filter (not in).
Expression.and(
listOf(
Expression.equals(Expression.get("featureType"), "trackPoint"),
Expression.lessThanOrEqual(Expression.get("timestamp"), Expression.mapTime),
)
)
Expression.or(
listOf(
Expression.equals(Expression.get("CAT"), "flood"),
Expression.equals(Expression.get("CAT"), "wind"),
)
)
Expression.not(Expression.equals(Expression.get("hidden"), true))
Expression.contains(Expression.geometryType, listOf("Polygon", "MultiPolygon"))
Expression.has("COLOR")Geometry and Map Time
Expression.geometryType // ["geometry-type"] — layer filters
Expression.mapTime // ["map-time"] — timeline position as Unix secondsExpression.mapTime is the active map timeline, not wall-clock time. Built-in tropical tracks and convective outlooks already filter on it. Custom vector layers can do the same:
layer.filter = Expression.lessThanOrEqual(
Expression.get("timestamp"),
Expression.mapTime,
)String Operators
Expression.concat(listOf("#", Expression.get("COLOR")))
Expression.upcase(Expression.get("label"))
Expression.downcase(Expression.get("report.type"))
Expression.toString(Expression.get("id"))
Expression.join("-", listOf(Expression.get("a"), Expression.get("b")))
Expression.slice(Expression.get("label"), 0, 3)
Expression.length(Expression.get("label"))
Expression.at(0, Expression.get("vals"))concat is the usual way to turn an MVT hex property such as COLOR (00FF00) into a CSS color (#00FF00). get("vals.0") compiles to at and reads the first array element.
Color
Paint color on fill, line, circle, and symbol layers evaluates step, match, case, concat, rgb, rgba, and interpolate (linear, exponential, and cubic-bezier):
Expression.rgb(255, 0, 0)
Expression.rgba(255, 0, 0, 0.5)
Expression.concat(listOf("#", Expression.get("COLOR")))
Expression.interpolate(
Expression.get("magnitude"),
listOf(0.0, "rgba(0, 0, 255, 1)", 6.0, "rgba(255, 0, 0, 1)"),
)Heatmap color ramps use interpolate on heatmap-density through the heatmap painter, not this general fill/line/circle path.
Not evaluated
These factories still serialize Mapbox-style JSON but are not run for GLES vector paint or filters: format, indexOf, and toBoolean. Expression.zoom works for paint (size, radius, color) but not in a layer filter.