Add outlines around shapes, text, and graphics to create emphasis, separation, or decorative effects.
Strokes are visual outlines on design blocks. This guide focuses on controlling stroke color, width, line pattern, position relative to the block edge, corner geometry, and the miter limit through the block API. It also shows how to paint a stroke with a gradient fill. Mutating stroke properties requires the stroke/change scope. Additional cap, custom dash, and PDF overprint APIs are listed in the API Reference.
This guide covers the built-in Android editor controls for strokes and the programmatic APIs for applying the same settings. The code snippets use a rectangle graphic block named block, but the same API calls apply to any block after supportsStroke() returns true.
Using the Built-in Stroke UI#
The Android editor shows stroke controls in the Fill & Stroke sheet, represented by SheetType.FillStroke, for selected blocks that support strokes and allow the stroke/change scope. That sheet can render fill controls, stroke controls, or both depending on the selected block. The color row controls stroke on/off: choosing no color disables the stroke, while choosing a swatch or custom color enables and colors it.
- No-color and color swatches - Disable the stroke or apply a preset RGBA stroke color
- Color picker - Choose a custom stroke color
- Width slider - Adjust stroke thickness in design units
- Style property picker - Select solid, dashed, rounded-dashed, dotted, long-dashed, or long round-ended dashed patterns
- Position and join property pickers - Adjust stroke placement and corner joins when available for the selected block
Checking Stroke Support#
Before applying stroke settings, check whether the block supports strokes. Return before the mutation calls when supportsStroke() is false.
val canHaveStroke = engine.block.supportsStroke(block = block)if (!canHaveStroke) { return null}Enabling Strokes#
Enable strokes with setStrokeEnabled(), then read the state back with isStrokeEnabled() when your app needs to update UI or validate the change.
engine.block.setStrokeEnabled(block = block, enabled = true)val strokeIsEnabled = engine.block.isStrokeEnabled(block = block)Setting Stroke Color#
Use setStrokeColor() with normalized RGBA components from 0F to 1F. The sample sets a blue stroke color and reads it back with getStrokeColor().
engine.block.setStrokeColor( block = block, color = Color.fromRGBA(r = 0F, g = 0.4F, b = 0.9F, a = 1F),)val strokeColor = engine.block.getStrokeColor(block = block)Setting Stroke Width#
Set the thickness in design units with setStrokeWidth(). Larger values create more prominent outlines, and getStrokeWidth() returns the current value.
engine.block.setStrokeWidth(block = block, width = 8F)val strokeWidth = engine.block.getStrokeWidth(block = block)Stroke Styles#
Use setStrokeStyle() to control the line pattern. Android exposes the available styles as StrokeStyle enum values:
StrokeStyle.SOLID- Continuous lineStrokeStyle.DASHED- Square-ended dashes with gapsStrokeStyle.DASHED_ROUND- Round-ended dashes with gapsStrokeStyle.DOTTED- Circular dotsStrokeStyle.LONG_DASHED- Longer square-ended dashesStrokeStyle.LONG_DASHED_ROUND- Longer round-ended dashes
engine.block.setStrokeStyle(block = block, style = StrokeStyle.DASHED)val strokeStyle = engine.block.getStrokeStyle(block = block)Stroke Position#
Use setStrokePosition() to control where the stroke renders relative to the block edge:
StrokePosition.CENTER- Centered on the edgeStrokePosition.INNER- Rendered inside the block boundaryStrokePosition.OUTER- Rendered outside the block boundary
Inner strokes stay within the block bounds, while outer strokes extend beyond them.
engine.block.setStrokePosition(block = block, position = StrokePosition.OUTER)val strokePosition = engine.block.getStrokePosition(block = block)Stroke Corner Geometry#
Use setStrokeCornerGeometry() to control how stroke corners are joined. The effect is easiest to see on rectangular shapes.
StrokeCornerGeometry.MITER- Sharp pointed corners, up to the miter limitStrokeCornerGeometry.ROUND- Smoothly curved cornersStrokeCornerGeometry.BEVEL- Flat cut corners
engine.block.setStrokeCornerGeometry(block = block, geometry = StrokeCornerGeometry.ROUND)val strokeCornerGeometry = engine.block.getStrokeCornerGeometry(block = block)Miter Limit#
A mitered corner extends to a point. On a sharp corner, this point can reach far beyond the shape. The stroke/miterLimit property limits the length of the miter as a multiple of the stroke width. A corner whose miter is longer than this limit gets a bevel.
Set the limit with setFloat() and read it with getFloat(). The limit only changes corners that use StrokeCornerGeometry.MITER. The sample uses a star block named star.
- Graphic blocks and pages use a default limit of
35F. - Text blocks use a default limit of
4F. - The value must be
1For greater. A smaller value throws an exception.
// Bevel each corner whose miter is longer than 1.5 times the stroke width.engine.block.setStrokeCornerGeometry(block = star, geometry = StrokeCornerGeometry.MITER)engine.block.setFloat(block = star, property = "stroke/miterLimit", value = 1.5F)val strokeMiterLimit = engine.block.getFloat(block = star, property = "stroke/miterLimit")Painting Strokes with a Fill#
A stroke uses its stroke color by default. To paint the stroke with a gradient instead, create a fill and set it with setStrokeFill(). getStrokeFill() returns this fill, or null when the stroke uses its color.
val strokeGradient = engine.block.createFill(FillType.LinearGradient)engine.block.setGradientColorStops( block = strokeGradient, property = "fill/gradient/colors", colorStops = listOf( GradientColorStop(stop = 0F, color = Color.fromRGBA(r = 0F, g = 0.4F, b = 0.9F, a = 1F)), GradientColorStop(stop = 1F, color = Color.fromRGBA(r = 0.9F, g = 0.2F, b = 0.5F, a = 1F)), ),)engine.block.setStrokeFill(block = star, fill = strokeGradient)val strokeFill = engine.block.getStrokeFill(block = star)The stroke fill replaces only the color. Width, style, position, and corner settings stay the same. Keep these rules in mind:
- Graphic blocks and pages support stroke fills. Text blocks do not.
- Color, gradient, and stripe fills are supported. Image and video fills are rejected.
- The block’s own fill cannot also paint its stroke. Create a separate fill block.
- A stroke color with an alpha of
0Fstill hides the stroke. - Pass
fill = nullto paint the stroke with its color again. This does not destroy the previous fill block.
Troubleshooting#
If strokes do not appear as expected, check these common issues:
- Stroke not visible - Verify
isStrokeEnabled()returnstrueand the width is greater than0F. - Stroke color appears wrong - Use normalized color components from
0Fto1F, not0to255. - Stroke affects the visual bounds - Use
StrokePosition.INNERto keep the stroke inside the block boundary, orStrokePosition.OUTERwhen the outline should extend beyond it. - Block does not support strokes - Guard mutations with
supportsStroke()before applying stroke properties. - Sharp corners look cut off - The miter is longer than the miter limit. Raise
stroke/miterLimit, or useStrokeCornerGeometry.ROUND. - Miter limit is rejected - The value is below
1For not finite. - Stroke fill is rejected - The block is a text block, the fill draws an image or video, or the fill is the block’s own fill.
API Reference#
| Method | Description |
|---|---|
engine.block.supportsStroke(block=_) |
Check whether a block supports strokes |
engine.block.setStrokeEnabled(block=_, enabled=_) |
Enable or disable the stroke |
engine.block.isStrokeEnabled(block=_) |
Check whether the stroke is enabled |
engine.block.setStrokeOverprint(block=_, overprint=_) |
Mark eligible spot-color strokes for PDF overprint output |
engine.block.getStrokeOverprint(block=_) |
Check whether stroke overprint is enabled |
engine.block.setStrokeColor(block=_, color=_) |
Set the stroke color |
engine.block.getStrokeColor(block=_) |
Get the current stroke color |
engine.block.setStrokeWidth(block=_, width=_) |
Set the stroke thickness in design units |
engine.block.getStrokeWidth(block=_) |
Get the current stroke width |
engine.block.setStrokeStyle(block=_, style=_) |
Set the stroke line pattern |
engine.block.getStrokeStyle(block=_) |
Get the current stroke style |
engine.block.setStrokeStartCap(block=_, cap=_) |
Set the cap at the start of an open stroked path |
engine.block.getStrokeStartCap(block=_) |
Get the start cap for an open stroked path |
engine.block.setStrokeEndCap(block=_, cap=_) |
Set the cap at the end of an open stroked path |
engine.block.getStrokeEndCap(block=_) |
Get the end cap for an open stroked path |
engine.block.setStrokeDashStartCap(block=_, cap=_) |
Set the leading cap for each dash segment |
engine.block.getStrokeDashStartCap(block=_) |
Get the leading cap for each dash segment |
engine.block.setStrokeDashEndCap(block=_, cap=_) |
Set the trailing cap for each dash segment |
engine.block.getStrokeDashEndCap(block=_) |
Get the trailing cap for each dash segment |
engine.block.setStrokeDashArray(block=_, dashArray=_) |
Set a custom dash pattern in design units |
engine.block.getStrokeDashArray(block=_) |
Get the custom dash pattern |
engine.block.setStrokeDashOffset(block=_, dashOffset=_) |
Shift the custom dash pattern along the stroke |
engine.block.getStrokeDashOffset(block=_) |
Get the dash pattern offset |
engine.block.setStrokePosition(block=_, position=_) |
Set the stroke position relative to the edge |
engine.block.getStrokePosition(block=_) |
Get the current stroke position |
engine.block.setStrokeCornerGeometry(block=_, geometry=_) |
Set the stroke corner join geometry |
engine.block.getStrokeCornerGeometry(block=_) |
Get the current stroke corner geometry |
engine.block.setFloat(block=_, property=_, value=_) |
Set the stroke/miterLimit property as a multiple of the stroke width (experimental) |
engine.block.getFloat(block=_, property=_) |
Get the current stroke/miterLimit value (experimental) |
engine.block.setStrokeFill(block=_, fill=_) |
Paint the stroke with a fill, or pass null to use the stroke color (experimental) |
engine.block.getStrokeFill(block=_) |
Get the fill that paints the stroke, or null (experimental) |
engine.block.createFill(fillType=_) |
Create a fill block, for example a gradient for a stroke fill |
engine.block.setGradientColorStops(block=_, property=_, colorStops=_) |
Set the color stops of a gradient fill |
Related Types#
| Type | Values | Description |
|---|---|---|
StrokeStyle |
SOLID, DASHED, DASHED_ROUND, DOTTED, LONG_DASHED, LONG_DASHED_ROUND |
Selects the preset line pattern |
StrokePosition |
CENTER, INNER, OUTER |
Controls where the stroke is drawn relative to the block edge |
StrokeCornerGeometry |
MITER, ROUND, BEVEL |
Controls how stroke corners join |
FillType |
Color, LinearGradient, RadialGradient, ConicalGradient, Stripe |
Fill types that can paint a stroke |
StrokeCap |
BUTT, ROUND, SQUARE |
Controls open-path and dash-segment end caps |
Next Steps#
- Apply Colors - Apply colors to design elements programmatically
- Fills - Add solid colors, gradients, images, or videos inside blocks
- Shadows and Glows - Add depth with shadow and glow effects
- Create and Edit Shapes - Create shape blocks you can style with strokes