Defines a Shape built from rounded polygon geometry.

Create instances with PolygonShape or companion factories like regularPolygon and star.

  • Call transform to rotate, translate, scale, apply a Matrix, or fit the geometry into the layout bounds in place.

  • Call copy before mutating a shared shape to keep the original unchanged.

Note: Caches the resolved Outline for the most recent layout size, and shares returned Outline instances across callers. Do not mutate the Outline returned by createOutline.

Summary

Public companion functions

PolygonShape
absoluteRectangle(
    topLeftRounding: CornerRounding,
    topRightRounding: CornerRounding,
    bottomRightRounding: CornerRounding,
    bottomLeftRounding: CornerRounding
)

Creates a rectangular PolygonShape with fixed left/right corner roundings.

Cmn
PolygonShape
circle(numVertices: @IntRange(from = 3) Int)

Creates a circular PolygonShape approximated by numVertices rounded vertices.

Cmn
PolygonShape
pill(smoothing: @FloatRange(from = 0.0, to = 1.0) Float)

Creates a pill PolygonShape with rounded ends along the shorter container sides.

Cmn
PolygonShape
pillStar(
    numPoints: @IntRange(from = 2) Int,
    innerRadiusRatio: @FloatRange(from = 0.0, to = 1.0, fromInclusive = false, toInclusive = false) Float,
    vertexSpacing: @FloatRange(from = 0.0, to = 1.0) Float,
    startLocation: @FloatRange(from = 0.0, to = 1.0) Float,
    outerRounding: CornerRounding,
    innerRounding: CornerRounding
)

Creates a star PolygonShape with vertices distributed along a pill outline.

Cmn
PolygonShape

Creates a rectangular PolygonShape filling the layout bounds with uniform rounding.

Cmn
PolygonShape
rectangle(
    topStartRounding: CornerRounding,
    topEndRounding: CornerRounding,
    bottomEndRounding: CornerRounding,
    bottomStartRounding: CornerRounding
)

Creates a rectangular PolygonShape with independent layout-direction-aware corners.

Cmn
PolygonShape
regularPolygon(
    numVertices: @IntRange(from = 3) Int,
    rounding: CornerRounding
)

Creates a regular polygon PolygonShape inscribed in the container's smaller dimension.

Cmn
PolygonShape
star(
    numPoints: @IntRange(from = 2) Int,
    innerRadiusRatio: @FloatRange(from = 0.0, to = 1.0, fromInclusive = false, toInclusive = false) Float,
    outerRounding: CornerRounding,
    innerRounding: CornerRounding
)

Creates a star PolygonShape inscribed in the container's smaller dimension.

Cmn

Protected constructors

Cmn

Public functions

PolygonShape

Creates an independent copy of this PolygonShape and its transformations.

Cmn
final Outline
createOutline(
    size: Size,
    layoutDirection: LayoutDirection,
    density: Density
)

Creates Outline of this shape for the given size.

Cmn
Unit

Transforms this PolygonShape's geometry in place using block.

Cmn

Public companion functions

absoluteRectangle

fun absoluteRectangle(
    topLeftRounding: CornerRounding = CornerRounding.Unrounded,
    topRightRounding: CornerRounding = CornerRounding.Unrounded,
    bottomRightRounding: CornerRounding = CornerRounding.Unrounded,
    bottomLeftRounding: CornerRounding = CornerRounding.Unrounded
): PolygonShape

Creates a rectangular PolygonShape with fixed left/right corner roundings.

Corner roundings do not mirror with LayoutDirection.

Parameters
topLeftRounding: CornerRounding = CornerRounding.Unrounded

top-left corner rounding, resolved against the layout bounds

topRightRounding: CornerRounding = CornerRounding.Unrounded

top-right corner rounding, resolved against the layout bounds

bottomRightRounding: CornerRounding = CornerRounding.Unrounded

bottom-right corner rounding, resolved against the layout bounds

bottomLeftRounding: CornerRounding = CornerRounding.Unrounded

bottom-left corner rounding, resolved against the layout bounds

circle

fun circle(numVertices: @IntRange(from = 3) Int = 8): PolygonShape

Creates a circular PolygonShape approximated by numVertices rounded vertices.

Parameters
numVertices: @IntRange(from = 3) Int = 8

number of vertices approximating the circle, at least 3

Throws
IllegalArgumentException

if numVertices is less than 3

pill

fun pill(smoothing: @FloatRange(from = 0.0, to = 1.0) Float = 0.0f): PolygonShape

Creates a pill PolygonShape with rounded ends along the shorter container sides.

Parameters
smoothing: @FloatRange(from = 0.0, to = 1.0) Float = 0.0f

transition smoothness between the endcap arcs and straight edges, in 0f..1f (0f keeps a purely circular arc)

Throws
IllegalArgumentException

if smoothing is outside 0f..1f

pillStar

fun pillStar(
    numPoints: @IntRange(from = 2) Int,
    innerRadiusRatio: @FloatRange(from = 0.0, to = 1.0, fromInclusive = false, toInclusive = false) Float = 0.5f,
    vertexSpacing: @FloatRange(from = 0.0, to = 1.0) Float = 0.5f,
    startLocation: @FloatRange(from = 0.0, to = 1.0) Float = 0.0f,
    outerRounding: CornerRounding = CornerRounding.Unrounded,
    innerRounding: CornerRounding = outerRounding
): PolygonShape

Creates a star PolygonShape with vertices distributed along a pill outline.

vertexSpacing controls how vertices are spaced around the curved ends:

  • 0f: spaces inner vertices evenly along the curved ends

  • 1f: spaces outer vertices evenly along the curved ends

  • 0.5f (default): averages inner and outer spacing symmetrically

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CornerRounding
import androidx.compose.foundation.shape.PolygonShape
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

// An elongated star outline distributed along a pill container, creating a decorative badge.
val pillStar = remember {
    PolygonShape.pillStar(
        numPoints = 8,
        innerRadiusRatio = 0.6f,
        outerRounding = CornerRounding.fraction(0.2f, smoothing = 0.5f),
    )
}
Box(Modifier.size(width = 140.dp, height = 64.dp).clip(pillStar).background(Color(0xFFE91E63)))
Parameters
numPoints: @IntRange(from = 2) Int

number of star tips, at least 2

innerRadiusRatio: @FloatRange(from = 0.0, to = 1.0, fromInclusive = false, toInclusive = false) Float = 0.5f

ratio of inner radius to outer radius, in (0f, 1f)

vertexSpacing: @FloatRange(from = 0.0, to = 1.0) Float = 0.5f

curved-end vertex spacing policy, in 0f..1f

startLocation: @FloatRange(from = 0.0, to = 1.0) Float = 0.0f

perimeter offset where the outline starts, in 0f..1f

outerRounding: CornerRounding = CornerRounding.Unrounded

rounding for outer tips, resolved against the star's outer radius

innerRounding: CornerRounding = outerRounding

rounding for inner corners, resolved against the star's outer radius

Throws
IllegalArgumentException

if numPoints is less than 2, innerRadiusRatio is outside (0f, 1f), or vertexSpacing or startLocation is outside 0f..1f

rectangle

fun rectangle(rounding: CornerRounding): PolygonShape

Creates a rectangular PolygonShape filling the layout bounds with uniform rounding.

Parameters
rounding: CornerRounding

corner rounding for all 4 corners, resolved against the layout bounds

rectangle

fun rectangle(
    topStartRounding: CornerRounding = CornerRounding.Unrounded,
    topEndRounding: CornerRounding = CornerRounding.Unrounded,
    bottomEndRounding: CornerRounding = CornerRounding.Unrounded,
    bottomStartRounding: CornerRounding = CornerRounding.Unrounded
): PolygonShape

Creates a rectangular PolygonShape with independent layout-direction-aware corners.

Corner roundings mirror automatically in LayoutDirection.Rtl.

Parameters
topStartRounding: CornerRounding = CornerRounding.Unrounded

top-start corner rounding, resolved against the layout bounds

topEndRounding: CornerRounding = CornerRounding.Unrounded

top-end corner rounding, resolved against the layout bounds

bottomEndRounding: CornerRounding = CornerRounding.Unrounded

bottom-end corner rounding, resolved against the layout bounds

bottomStartRounding: CornerRounding = CornerRounding.Unrounded

bottom-start corner rounding, resolved against the layout bounds

regularPolygon

fun regularPolygon(
    numVertices: @IntRange(from = 3) Int,
    rounding: CornerRounding = CornerRounding.Unrounded
): PolygonShape

Creates a regular polygon PolygonShape inscribed in the container's smaller dimension.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CornerRounding
import androidx.compose.foundation.shape.PolygonShape
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

// A pentagon whose corners round to a 0.2f fraction of its generating radius, so the rounding
// scales proportionally with the shape at any size.
val pentagon = remember {
    PolygonShape.regularPolygon(numVertices = 5, rounding = CornerRounding.fraction(0.2f))
}
Box(Modifier.size(96.dp).clip(pentagon).background(Color(0xFF009688)))
Parameters
numVertices: @IntRange(from = 3) Int

number of vertices, at least 3

rounding: CornerRounding = CornerRounding.Unrounded

corner rounding resolved against the polygon's radius

Throws
IllegalArgumentException

if numVertices is less than 3

star

fun star(
    numPoints: @IntRange(from = 2) Int,
    innerRadiusRatio: @FloatRange(from = 0.0, to = 1.0, fromInclusive = false, toInclusive = false) Float = 0.5f,
    outerRounding: CornerRounding = CornerRounding.Unrounded,
    innerRounding: CornerRounding = outerRounding
): PolygonShape

Creates a star PolygonShape inscribed in the container's smaller dimension.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CornerRounding
import androidx.compose.foundation.shape.PolygonShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

// An eight-point star with smoothly rounded outer points.
val star =
    PolygonShape.star(
        numPoints = 8,
        innerRadiusRatio = 0.6f,
        outerRounding = CornerRounding.fraction(0.15f, smoothing = 0.5f),
    )
Box(Modifier.size(96.dp).clip(star).background(Color(0xFFFFC107)))
Parameters
numPoints: @IntRange(from = 2) Int

number of star tips, at least 2

innerRadiusRatio: @FloatRange(from = 0.0, to = 1.0, fromInclusive = false, toInclusive = false) Float = 0.5f

ratio of inner radius to outer radius, in (0f, 1f)

outerRounding: CornerRounding = CornerRounding.Unrounded

rounding for outer tips, resolved against the star's outer radius

innerRounding: CornerRounding = outerRounding

rounding for inner corners, resolved against the star's outer radius

Throws
IllegalArgumentException

if numPoints is less than 2 or innerRadiusRatio is outside (0f, 1f)

Protected constructors

PolygonShape

protected PolygonShape()

Public functions

copy

@RememberInComposition
fun copy(): PolygonShape

Creates an independent copy of this PolygonShape and its transformations.

Subsequent in-place mutations via transform on the returned copy do not affect this shape, and vice versa.

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CornerRounding
import androidx.compose.foundation.shape.PolygonShape
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

// Creates an unrotated badge shape and an independent rotated copy using copy() + transform {}.
val badge = remember {
    PolygonShape.star(
        numPoints = 8,
        innerRadiusRatio = 0.75f,
        outerRounding = CornerRounding.fraction(0.4f),
    )
}
val selectedBadge =
    remember(badge) { badge.copy().apply { transform { rotate(degrees = 22.5f) } } }
var selected by remember { mutableStateOf(false) }
val shape = if (selected) selectedBadge else badge
Box(
    Modifier.size(96.dp).clip(shape).background(Color(0xFF00695C)).clickable {
        selected = !selected
    }
)
Returns
PolygonShape

a new PolygonShape with the same base geometry and transformation configuration

createOutline

final fun createOutline(
    size: Size,
    layoutDirection: LayoutDirection,
    density: Density
): Outline

Creates Outline of this shape for the given size.

Parameters
size: Size

the size of the shape boundary.

layoutDirection: LayoutDirection

the current layout direction.

density: Density

the current density of the screen.

Returns
Outline

Outline of this shape for the given size.

transform

@RememberInComposition
fun transform(block: PolygonShapeTransformScope.() -> Unit): Unit

Transforms this PolygonShape's geometry in place using block.

  • Runs block in PolygonShapeTransformScope during outline resolution, deferring Compose state reads out of composition so animated transforms update without recomposition.

  • Replaces any transformation block previously set on this shape via transform.

  • Mutates this PolygonShape in place; call copy first to keep a shared base shape unchanged.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CornerRounding
import androidx.compose.foundation.shape.PolygonShape
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.dp

// A square polygon rotated 45 degrees around its center and scaled into the layout bounds in a
// single pass so the rotated diamond stays inscribed without clipping.
val diamond = remember {
    PolygonShape { polygon(numVertices = 4, rounding = CornerRounding.fraction(0.15f)) }
        .apply {
            transform {
                rotate(degrees = 45f)
                scaleToFit(contentScale = ContentScale.Fit)
            }
        }
}
Box(Modifier.size(96.dp).clip(diamond).background(Color(0xFFE91E63)))
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CornerRounding
import androidx.compose.foundation.shape.PolygonShape
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

// Creates an unrotated badge shape and an independent rotated copy using copy() + transform {}.
val badge = remember {
    PolygonShape.star(
        numPoints = 8,
        innerRadiusRatio = 0.75f,
        outerRounding = CornerRounding.fraction(0.4f),
    )
}
val selectedBadge =
    remember(badge) { badge.copy().apply { transform { rotate(degrees = 22.5f) } } }
var selected by remember { mutableStateOf(false) }
val shape = if (selected) selectedBadge else badge
Box(
    Modifier.size(96.dp).clip(shape).background(Color(0xFF00695C)).clickable {
        selected = !selected
    }
)
Parameters
block: PolygonShapeTransformScope.() -> Unit

transformation block run in PolygonShapeTransformScope at resolution time