androidx.wear.compose.foundation

Interfaces

AmbientModeManager
ArcPaddingValues

Apply additional space along each edge of the content in Dp.

CurvedAlignment
CurvedDirection
CurvedModifier

An ordered, immutable, collection of modifier elements that work with curved components, in a polar coordinate space.

GestureInclusion

GestureInclusion provides fine-grained control over which gestures a component should handle, given the start offset and the layout coordinates of the component.

ScrollInfoProvider

An interface for providing scroll information for different scrollable containers, such lists.

Classes

AmbientMode

Represents the current ambient mode of the device.

AmbientMode.Ambient

Represents that device is in the ambient mode.

AnchorType

Specifies how components will be laid down with respect to the anchor.

CurvedAlignment.Angular

How to lay down components when they have a smaller sweep than their container.

CurvedAlignment.Radial

How to lay down components when they are thinner than the container.

CurvedDirection.Angular

The direction in which components are laid out on a curvedRow or CurvedLayout

CurvedDirection.Radial

The direction in which components are lay down on a curvedColumn

CurvedScope

Layout scope used for curved containers.

CurvedSemanticsScope

CurvedSemanticsScope is the scope provided by semantics lambda blocks, letting you set semantic properties.

CurvedTextStyle

Styling configuration for a curved text.

CurvedTextStyle.WarpOffset

Used to specify if we want to warp the text, and if so, the offset for warping.

ExpandableState

State of the Expandable composables.

ExpandableStateMapping

A class that maps from keys of the given type to ExpandableState.

RevealActionType

This class is deprecated. The SwipeToReveal component from the latest material library should be used instead.

RevealDirection

This class is deprecated. The SwipeToReveal component from the latest material library should be used instead.

RevealState

This class is deprecated. The SwipeToReveal component from the latest material library should be used instead.

RevealValue

This class is deprecated. The SwipeToReveal component from the latest material library should be used instead.

SwipeToDismissBoxState

State for BasicSwipeToDismissBox.

Objects

AmbientMode.Interactive

Represents the mode when the user is actively interacting with the device.

CurvedModifier.Companion

The companion object CurvedModifier is the empty, default, or starter CurvedModifier that contains no Elements.

ExpandableItemsDefaults

Contains the default values used by Expandable components.

SwipeToDismissBoxDefaults

Contains defaults for BasicSwipeToDismissBox.

SwipeToRevealDefaults

This object is deprecated. The SwipeToReveal component from the latest material library should be used instead.

WearComposeFoundationFlags

This is a collection of flags which are used to guard against regressions in some of the "riskier" refactors or new feature support that is added to this module.

Annotations

Enums

SwipeToDismissKeys

Keys used to persistent state in BasicSwipeToDismissBox.

SwipeToDismissValue

States used as targets for the anchor points for swipe-to-dismiss.

Composables

ActiveFocusListener
AmbientTickEffect

A convenience extension that performs recurrent, battery-efficient UI updates when the device is in AmbientMode.Ambient.

BasicSwipeToDismissBox

BasicSwipeToDismissBox that handles the swipe-to-dismiss gesture.

CurvedLayout

A layout composable that places its children in an arc, rotating them as needed.

HierarchicalFocusCoordinator
SwipeToReveal

A composable that can be used to add extra actions to a composable (up to two) which will be revealed when the original composable is swiped to the left.

rememberActiveFocusRequester
rememberAmbientModeManager

Creates, remembers, and manages the lifecycle of the default AmbientModeManager implementation.

rememberExpandableState

Create and remember an ExpandableState

rememberExpandableStateMapping

Create and remember a mapping from keys to ExpandableStates ExpandableStates can be requested by key, and we will created with the parameters given here when a mapping didn't exist before.

rememberRevealState

Create and remember a RevealState.

rememberSwipeToDismissBoxState

Create a SwipeToDismissBoxState and remember it.

Modifiers

edgeSwipeToDismiss

Handles swipe to dismiss from the edge of the viewport.

hierarchicalFocusGroup

hierarchicalFocusGroup is used to annotate composables in an application, so we can keep track of what is the active part of the composition.

requestFocusOnHierarchyActive

This Modifier is used in conjunction with hierarchicalFocusGroup and will request focus on the following focusable element when needed (i.e. this needs to be before that element in the Modifier chain).

Top-level functions summary

ArcPaddingValues

Apply all dp of additional space along each edge of the content.

ArcPaddingValues
ArcPaddingValues(radial: Dp, angular: Dp)

Apply radial dp of additional space on the edges towards and away from the center, and angular dp before and after the component.

ArcPaddingValues
ArcPaddingValues(outer: Dp, inner: Dp, before: Dp, after: Dp)

Apply additional space along each edge of the content in Dp.

ScrollInfoProvider

Function for creating a ScrollInfoProvider from a LazyListState, for use with LazyColumn - used to coordinate between scrollable content and scaffold content such as androidx.wear.compose.material.TimeText which is scrolled away at the top of the screen and androidx.wear.compose.material3.EdgeButton which is scaled.

ScrollInfoProvider

Function for creating a ScrollInfoProvider from a PagerState, for use with HorizontalPager and VerticalPager

ScrollInfoProvider

Function for creating a ScrollInfoProvider from a ScalingLazyListState, for use with ScalingLazyColumn - used to coordinate between scrollable content and scaffold content such as androidx.wear.compose.material.TimeText which is scrolled away at the top of the screen and androidx.wear.compose.material3.EdgeButton which is scaled.

ScrollInfoProvider

Function for creating a ScrollInfoProvider from a ScrollState, for use with Column - used to coordinate between scrollable content and scaffold content such as androidx.wear.compose.material.TimeText which is scrolled away at the top of the screen and androidx.wear.compose.material3.EdgeButton which is scaled.

ScrollInfoProvider

Function for creating a ScrollInfoProvider from a TransformingLazyColumnState, for use with TransformingLazyColumn - used to coordinate between scrollable content and scaffold content such as androidx.wear.compose.material.TimeText which is scrolled away at the top of the screen and androidx.wear.compose.material3.EdgeButton which is scaled.

Map<RevealValueFloat>
@ExperimentalWearFoundationApi
createRevealAnchors(
    coveredAnchor: Float,
    revealingAnchor: Float,
    revealedAnchor: Float,
    revealDirection: RevealDirection
)

This function is deprecated. The SwipeToReveal component from the latest material library should be used instead.

Extension functions summary

CurvedModifier
CurvedModifier.angularGradientBackground(
    vararg colorStops: Pair<FloatColor>,
    cap: StrokeCap
)

Specifies a sweep gradient background for a curved element.

CurvedModifier

Specifies a sweep gradient background for a curved element.

CurvedModifier

Specify the sweep (angular size) for the content.

CurvedModifier

Specify the sweep (arc length) for the content in Dp.

CurvedModifier

Specified a solid background for a curved element.

Unit
CurvedScope.basicCurvedText(
    text: String,
    modifier: CurvedModifier,
    angularDirection: CurvedDirection.Angular?,
    overflow: TextOverflow,
    style: @Composable () -> CurvedTextStyle
)

basicCurvedText is a component allowing developers to easily write curved text following the curvature a circle (usually at the edge of a circular screen).

Unit
CurvedScope.basicCurvedText(
    text: String,
    style: CurvedTextStyle,
    modifier: CurvedModifier,
    angularDirection: CurvedDirection.Angular?,
    overflow: TextOverflow
)

basicCurvedText is a component allowing developers to easily write curved text following the curvature a circle (usually at the edge of a circular screen).

CurvedModifier

Allow specifying semantic properties on a curved component, and clearing the existing properties.

Unit
CurvedScope.curvedBox(
    modifier: CurvedModifier,
    radialAlignment: CurvedAlignment.Radial?,
    angularAlignment: CurvedAlignment.Angular?,
    contentBuilder: CurvedScope.() -> Unit
)

A layout composable that places its children on top of each other and on an arc.

Unit
CurvedScope.curvedColumn(
    modifier: CurvedModifier,
    radialDirection: CurvedDirection.Radial?,
    angularAlignment: CurvedAlignment.Angular?,
    contentBuilder: CurvedScope.() -> Unit
)

A curved layout composable that places its children stacked as part of an arc (the first child will be the outermost).

Unit
CurvedScope.curvedComposable(
    modifier: CurvedModifier,
    radialAlignment: CurvedAlignment.Radial,
    rotationLocked: Boolean,
    content: @Composable BoxScope.() -> Unit
)

Component that allows normal composables to be part of a CurvedLayout.

Unit
CurvedScope.curvedRow(
    modifier: CurvedModifier,
    radialAlignment: CurvedAlignment.Radial?,
    angularDirection: CurvedDirection.Angular?,
    contentBuilder: CurvedScope.() -> Unit
)

A layout composable that places its children in an arc, rotating them as needed.

Unit
ScalingLazyListScope.expandableButton(
    state: ExpandableState,
    key: Any?,
    content: @Composable () -> Unit
)

Adds a single item, for the button that controls expandable item(s).

Unit
ScalingLazyListScope.expandableItem(
    state: ExpandableState,
    key: Any?,
    content: @Composable (expanded: Boolean) -> Unit
)

Adds a single item, that will be expanded/collapsed according to the ExpandableState.

Unit
ScalingLazyListScope.expandableItems(
    state: ExpandableState,
    count: Int,
    key: ((index: Int) -> Any)?,
    itemContent: @Composable BoxScope.(index: Int) -> Unit
)

Adds a series of items, that will be expanded/collapsed according to the ExpandableState

CurvedModifier

Apply all dp space around the component.

CurvedModifier

Apply additional space along the edges of the content.

CurvedModifier
CurvedModifier.padding(radial: Dp, angular: Dp)

Apply angular dp space before and after the component, and radial dp space to the outer and inner edges.

CurvedModifier
CurvedModifier.padding(outer: Dp, inner: Dp, before: Dp, after: Dp)

Apply additional space along the edges of the content.

CurvedModifier
CurvedModifier.parentDataModifier(modifyParentData: (Any?) -> Any?)

A CurvedModifier that provides data to the parent layout.

CurvedModifier
CurvedModifier.radialGradientBackground(
    vararg colorStops: Pair<FloatColor>,
    cap: StrokeCap
)

Specifies a radial gradient background for a curved element.

CurvedModifier

Specifies a radial gradient background for a curved element.

CurvedModifier

Specify the radialSize (thickness) for the content.

CurvedModifier

Allow specifying semantic properties on a curved component.

CurvedModifier
CurvedModifier.size(
    sweepDegrees: @FloatRange(from = 0.0, to = 360.0) Float,
    thickness: Dp
)

Specify the dimensions (sweep and thickness) for the content.

CurvedModifier
CurvedModifier.sizeIn(
    minSweepDegrees: @FloatRange(from = 0.0, to = 360.0) Float,
    maxSweepDegrees: @FloatRange(from = 0.0, to = 360.0) Float,
    minThickness: Dp,
    maxThickness: Dp
)

Specify the dimensions of the content to be restricted between the given bounds.

CurvedModifier
CurvedModifier.weight(
    weight: @FloatRange(from = 0.0, fromInclusive = false) Float
)

Size the element's proportional to its weight relative to other weighted sibling elements in the container (this will be the height in a curvedColumn and the width in a curvedRow).

Top-level properties summary

ProvidableCompositionLocal<AmbientModeManager?>

A androidx.compose.runtime.CompositionLocal that provides the current AmbientModeManager interface.

ProvidableCompositionLocal<Boolean>

CompositionLocal for global reduce-motion setting, which turns off animations and screen movements.

ProvidableCompositionLocal<Boolean>

CompositionLocal used to express/determine if a screen is active, as specified by each component (for example, it could be updated when the user is in the middle of the gesture to switch screens, or after the gesture is done).

ProvidableCompositionLocal<Color>

CompositionLocal containing the background scrim color of BasicSwipeToDismissBox.

ProvidableCompositionLocal<Color>

CompositionLocal containing the content scrim color of BasicSwipeToDismissBox.

Top-level functions

ArcPaddingValues

fun ArcPaddingValues(all: Dp): ArcPaddingValues

Apply all dp of additional space along each edge of the content.

ArcPaddingValues

fun ArcPaddingValues(radial: Dp = 0.dp, angular: Dp = 0.dp): ArcPaddingValues

Apply radial dp of additional space on the edges towards and away from the center, and angular dp before and after the component.

ArcPaddingValues

fun ArcPaddingValues(outer: Dp = 0.dp, inner: Dp = 0.dp, before: Dp = 0.dp, after: Dp = 0.dp): ArcPaddingValues

Apply additional space along each edge of the content in Dp. Note that that all dimensions are applied to a concrete edge, indepenend on layout direction and curved layout direction.

Parameters
outer: Dp = 0.dp

Padding in the outward direction from the center of the CurvedLayout

inner: Dp = 0.dp

Padding in the inwards direction towards the center of the CurvedLayout

before: Dp = 0.dp

Padding added before the component, if it was draw clockwise.

after: Dp = 0.dp

Padding added after the component, if it was draw clockwise.

ScrollInfoProvider

fun ScrollInfoProvider(state: LazyListState): ScrollInfoProvider

Function for creating a ScrollInfoProvider from a LazyListState, for use with LazyColumn - used to coordinate between scrollable content and scaffold content such as androidx.wear.compose.material.TimeText which is scrolled away at the top of the screen and androidx.wear.compose.material3.EdgeButton which is scaled.

ScrollInfoProvider

fun ScrollInfoProvider(state: PagerState): ScrollInfoProvider

Function for creating a ScrollInfoProvider from a PagerState, for use with HorizontalPager and VerticalPager

  • used to coordinate when to fade out the PageIndicator and androidx.wear.compose.material.TimeText. The PageIndicator fades out when when scrolling is finished and the screen is in an idle state.

Parameters
state: PagerState

the PagerState to use as the base for creating the ScrollInfoProvider

ScrollInfoProvider

fun ScrollInfoProvider(state: ScalingLazyListState): ScrollInfoProvider

Function for creating a ScrollInfoProvider from a ScalingLazyListState, for use with ScalingLazyColumn - used to coordinate between scrollable content and scaffold content such as androidx.wear.compose.material.TimeText which is scrolled away at the top of the screen and androidx.wear.compose.material3.EdgeButton which is scaled.

ScrollInfoProvider

fun ScrollInfoProvider(state: ScrollState): ScrollInfoProvider

Function for creating a ScrollInfoProvider from a ScrollState, for use with Column - used to coordinate between scrollable content and scaffold content such as androidx.wear.compose.material.TimeText which is scrolled away at the top of the screen and androidx.wear.compose.material3.EdgeButton which is scaled.

Parameters
state: ScrollState

the ScrollState to use as the base for creating the ScrollInfoProvider

ScrollInfoProvider

fun ScrollInfoProvider(state: TransformingLazyColumnState): ScrollInfoProvider

Function for creating a ScrollInfoProvider from a TransformingLazyColumnState, for use with TransformingLazyColumn - used to coordinate between scrollable content and scaffold content such as androidx.wear.compose.material.TimeText which is scrolled away at the top of the screen and androidx.wear.compose.material3.EdgeButton which is scaled.

createRevealAnchors

@ExperimentalWearFoundationApi
fun createRevealAnchors(
    coveredAnchor: Float = 0.0f,
    revealingAnchor: Float = SwipeToRevealDefaults.RevealingRatio,
    revealedAnchor: Float = 1.0f,
    revealDirection: RevealDirection = RevealDirection.RightToLeft
): Map<RevealValueFloat>

Creates the required anchors to which the top content can be swiped, to reveal the actions. Each value should be in the range 0..1, where 0 represents right most end and 1 represents the full width of the top content starting from right and ending on left.

Parameters
coveredAnchor: Float = 0.0f

Anchor for the RevealValue.Covered value

revealingAnchor: Float = SwipeToRevealDefaults.RevealingRatio

Anchor for the RevealValue.LeftRevealing or RevealValue.RightRevealing value

revealedAnchor: Float = 1.0f

Anchor for the RevealValue.LeftRevealed or RevealValue.RightRevealed value

revealDirection: RevealDirection = RevealDirection.RightToLeft

The direction in which the content can be swiped. It's strongly advised to keep the default RevealDirection.RightToLeft in order to preserve compatibility with the system wide swipe to dismiss gesture.

Extension functions

CurvedModifier.angularGradientBackground

fun CurvedModifier.angularGradientBackground(
    vararg colorStops: Pair<FloatColor>,
    cap: StrokeCap = StrokeCap.Butt
): CurvedModifier

Specifies a sweep gradient background for a curved element.

Example usage:

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.CurvedTextStyle
import androidx.wear.compose.foundation.angularGradientBackground
import androidx.wear.compose.foundation.basicCurvedText
import androidx.wear.compose.foundation.padding
import androidx.wear.compose.foundation.radialGradientBackground
import androidx.wear.compose.material.Text

CurvedLayout(modifier = Modifier.fillMaxSize()) {
    basicCurvedText(
        "Radial",
        style = { CurvedTextStyle(fontSize = 16.sp, color = Color.Black) },
        modifier =
            CurvedModifier.radialGradientBackground(0f to Color.White, 1f to Color.Black)
                .padding(5.dp),
    )
    basicCurvedText(
        "Angular",
        style = { CurvedTextStyle(fontSize = 16.sp, color = Color.Black) },
        modifier =
            CurvedModifier.angularGradientBackground(0f to Color.White, 1f to Color.Black)
                .padding(5.dp),
    )
}
Parameters
vararg colorStops: Pair<FloatColor>

Colors and their offset in the gradient area. Note that the offsets should be in ascending order. 0 means where the curved element starts laying out, 1 means the end

cap: StrokeCap = StrokeCap.Butt

How to start and end the background.

CurvedModifier.angularGradientBackground

fun CurvedModifier.angularGradientBackground(
    colors: List<Color>,
    cap: StrokeCap = StrokeCap.Butt
): CurvedModifier

Specifies a sweep gradient background for a curved element.

Parameters
colors: List<Color>

Colors in the gradient area. Gradient goes in the clockwise direction.

cap: StrokeCap = StrokeCap.Butt

How to start and end the background.

CurvedModifier.angularSize

fun CurvedModifier.angularSize(sweepDegrees: Float): CurvedModifier

Specify the sweep (angular size) for the content.

Parameters
sweepDegrees: Float

Indicates the sweep (angular size) of the content.

CurvedModifier.angularSizeDp

fun CurvedModifier.angularSizeDp(angularWidth: Dp): CurvedModifier

Specify the sweep (arc length) for the content in Dp. The arc length will be measured at the center of the item, except for basicCurvedText, where it will be measured at the text baseline.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.CurvedTextStyle
import androidx.wear.compose.foundation.angularSize
import androidx.wear.compose.foundation.angularSizeDp
import androidx.wear.compose.foundation.background
import androidx.wear.compose.foundation.basicCurvedText
import androidx.wear.compose.foundation.radialSize
import androidx.wear.compose.foundation.size
import androidx.wear.compose.material.Text

CurvedLayout(modifier = Modifier.fillMaxSize()) {
    basicCurvedText(
        "45 deg",
        style = { CurvedTextStyle(fontSize = 16.sp, color = Color.Black) },
        modifier =
            CurvedModifier.background(Color.White).size(sweepDegrees = 45f, thickness = 40.dp),
    )
    basicCurvedText(
        "40 dp",
        style = { CurvedTextStyle(fontSize = 16.sp, color = Color.Black) },
        modifier =
            CurvedModifier.background(Color.Yellow).radialSize(40.dp).angularSizeDp(40.dp),
    )
}
Parameters
angularWidth: Dp

Indicates the arc length of the content in Dp.

CurvedModifier.background

fun CurvedModifier.background(color: Color, cap: StrokeCap = StrokeCap.Butt): CurvedModifier

Specified a solid background for a curved element.

Parameters
color: Color

The color to use to paint the background.

cap: StrokeCap = StrokeCap.Butt

How to start and end the background.

CurvedScope.basicCurvedText

fun CurvedScope.basicCurvedText(
    text: String,
    modifier: CurvedModifier = CurvedModifier,
    angularDirection: CurvedDirection.Angular? = null,
    overflow: TextOverflow = TextOverflow.Clip,
    style: @Composable () -> CurvedTextStyle = { CurvedTextStyle() }
): Unit

basicCurvedText is a component allowing developers to easily write curved text following the curvature a circle (usually at the edge of a circular screen). basicCurvedText can be only created within a CurvedLayout since it's not a composable.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.CurvedTextStyle
import androidx.wear.compose.foundation.background
import androidx.wear.compose.foundation.basicCurvedText
import androidx.wear.compose.foundation.curvedComposable
import androidx.wear.compose.foundation.padding
import androidx.wear.compose.foundation.size
import androidx.wear.compose.material.Text

CurvedLayout(modifier = Modifier.fillMaxSize()) {
    basicCurvedText(
        "Curved Text",
        CurvedModifier.padding(10.dp),
        style = {
            CurvedTextStyle(fontSize = 16.sp, color = Color.Black, background = Color.White)
        },
    )
    curvedComposable { Box(modifier = Modifier.size(20.dp).background(Color.Gray)) }
    curvedComposable {
        BasicText(
            "Normal Text",
            Modifier.padding(5.dp),
            TextStyle(fontSize = 16.sp, color = Color.Black, background = Color.White),
        )
    }
}
Parameters
text: String

The text to display

modifier: CurvedModifier = CurvedModifier

The CurvedModifier to apply to this curved text.

angularDirection: CurvedDirection.Angular? = null

Specify if the text is laid out clockwise or anti-clockwise, and if those needs to be reversed in a Rtl layout. If not specified, it will be inherited from the enclosing curvedRow or CurvedLayout See CurvedDirection.Angular.

overflow: TextOverflow = TextOverflow.Clip

How visual overflow should be handled. Note that this takes into account only explicit size curved modifiers in this element, to size this element matching the parent's, add a CurvedModifier.weight here.

style: @Composable () -> CurvedTextStyle = { CurvedTextStyle() }

A @Composable factory to provide the style to use. This composable SHOULDN'T generate any compose nodes.

CurvedScope.basicCurvedText

fun CurvedScope.basicCurvedText(
    text: String,
    style: CurvedTextStyle,
    modifier: CurvedModifier = CurvedModifier,
    angularDirection: CurvedDirection.Angular? = null,
    overflow: TextOverflow = TextOverflow.Clip
): Unit

basicCurvedText is a component allowing developers to easily write curved text following the curvature a circle (usually at the edge of a circular screen). basicCurvedText can be only created within a CurvedLayout since it's not a composable.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.CurvedTextStyle
import androidx.wear.compose.foundation.background
import androidx.wear.compose.foundation.basicCurvedText
import androidx.wear.compose.foundation.curvedComposable
import androidx.wear.compose.foundation.padding
import androidx.wear.compose.foundation.size
import androidx.wear.compose.material.Text

CurvedLayout(modifier = Modifier.fillMaxSize()) {
    basicCurvedText(
        "Curved Text",
        CurvedModifier.padding(10.dp),
        style = {
            CurvedTextStyle(fontSize = 16.sp, color = Color.Black, background = Color.White)
        },
    )
    curvedComposable { Box(modifier = Modifier.size(20.dp).background(Color.Gray)) }
    curvedComposable {
        BasicText(
            "Normal Text",
            Modifier.padding(5.dp),
            TextStyle(fontSize = 16.sp, color = Color.Black, background = Color.White),
        )
    }
}
Parameters
text: String

The text to display

style: CurvedTextStyle

A style to use.

modifier: CurvedModifier = CurvedModifier

The CurvedModifier to apply to this curved text.

angularDirection: CurvedDirection.Angular? = null

Specify if the text is laid out clockwise or anti-clockwise, and if those needs to be reversed in a Rtl layout. If not specified, it will be inherited from the enclosing curvedRow or CurvedLayout See CurvedDirection.Angular.

overflow: TextOverflow = TextOverflow.Clip

How visual overflow should be handled.

CurvedModifier.clearAndSetSemantics

fun CurvedModifier.clearAndSetSemantics(properties: CurvedSemanticsScope.() -> Unit): CurvedModifier

Allow specifying semantic properties on a curved component, and clearing the existing properties. Note that currently only CurvedSemanticsScope.contentDescription and CurvedSemanticsScope.traversalIndex are supported, and they can be applied to curved text and curvedComposable

Sample for clearing semantics:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.traversalIndex
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.sp
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.CurvedTextStyle
import androidx.wear.compose.foundation.basicCurvedText
import androidx.wear.compose.foundation.clearAndSetSemantics
import androidx.wear.compose.foundation.semantics
import androidx.wear.compose.material.Text

val style =
    CurvedTextStyle(
        letterSpacing = 0.6.sp,
        letterSpacingCounterClockwise = 1.4.sp,
        color = Color.White,
    )
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
    CurvedLayout(modifier = Modifier.fillMaxSize()) {
        basicCurvedText("This is not announced", style, CurvedModifier.clearAndSetSemantics {})
    }
    Row { Text("This is announced", Modifier.semantics { traversalIndex = -1f }) }
}
Parameters
properties: CurvedSemanticsScope.() -> Unit

The properties to apply, SemanticsPropertyReceiver will be provided in the scope to allow access for common properties and its values.

CurvedScope.curvedBox

fun CurvedScope.curvedBox(
    modifier: CurvedModifier = CurvedModifier,
    radialAlignment: CurvedAlignment.Radial? = null,
    angularAlignment: CurvedAlignment.Angular? = null,
    contentBuilder: CurvedScope.() -> Unit
): Unit

A layout composable that places its children on top of each other and on an arc. This is similar to a Box layout, but curved into a segment of an annulus.

The thickness of the layout (the difference between the outer and inner radius) will be the same as the thickest child, and the angle taken will be the biggest angle of the children.

Example usage:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.CurvedAlignment
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.background
import androidx.wear.compose.foundation.curvedBox
import androidx.wear.compose.foundation.curvedComposable
import androidx.wear.compose.foundation.size

CurvedLayout(modifier = Modifier.fillMaxSize()) {
    curvedBox(
        modifier = CurvedModifier.background(Color.Red),
        radialAlignment = CurvedAlignment.Radial.Inner,
        angularAlignment = CurvedAlignment.Angular.End,
    ) {
        curvedComposable {
            Box(modifier = Modifier.width(40.dp).height(80.dp).background(Color.Green))
        }
        curvedComposable {
            Box(modifier = Modifier.size(30.dp).clip(CircleShape).background(Color.White))
        }
    }
}
Parameters
modifier: CurvedModifier = CurvedModifier

The CurvedModifier to apply to this curved row.

radialAlignment: CurvedAlignment.Radial? = null

Radial alignment specifies where to lay down children that are thinner than the CurvedBox, either closer to the center CurvedAlignment.Radial.Inner, apart from the center CurvedAlignment.Radial.Outer or in the middle point CurvedAlignment.Radial.Center. If unspecified, they can choose for themselves.

angularAlignment: CurvedAlignment.Angular? = null

Angular alignment specifies where to lay down children that are thinner than the CurvedBox, either at the CurvedAlignment.Angular.Start of the layout, at the CurvedAlignment.Angular.End, or CurvedAlignment.Angular.Center. If unspecified or null, they can choose for themselves.

contentBuilder: CurvedScope.() -> Unit

Specifies the content of this layout, currently there are 5 available elements defined in foundation for this DSL: the sub-layouts curvedBox, curvedRow and curvedColumn, basicCurvedText and curvedComposable (used to add normal composables to curved layouts)

CurvedScope.curvedColumn

fun CurvedScope.curvedColumn(
    modifier: CurvedModifier = CurvedModifier,
    radialDirection: CurvedDirection.Radial? = null,
    angularAlignment: CurvedAlignment.Angular? = null,
    contentBuilder: CurvedScope.() -> Unit
): Unit

A curved layout composable that places its children stacked as part of an arc (the first child will be the outermost). This is similar to a Column layout, but curved into a segment of an annulus.

The thickness of the layout (the difference between the outer and inner radius) will be the sum of the thickness of its children, and the angle taken will be the biggest angle of the children.

Example usage:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.wear.compose.foundation.CurvedAlignment
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.background
import androidx.wear.compose.foundation.curvedColumn
import androidx.wear.compose.foundation.curvedComposable
import androidx.wear.compose.foundation.curvedRow
import androidx.wear.compose.foundation.padding
import androidx.wear.compose.foundation.size
import androidx.wear.compose.material.Text

CurvedLayout(modifier = Modifier.fillMaxSize()) {
    curvedComposable { Box(modifier = Modifier.size(20.dp).background(Color.Red)) }
    curvedColumn(angularAlignment = CurvedAlignment.Angular.End) {
        repeat(3) {
            curvedRow {
                curvedComposable {
                    BasicText(
                        "Row #$it",
                        Modifier.background(Color.White).padding(2.dp),
                        TextStyle(color = Color.Black, fontSize = 14.sp),
                    )
                }
                curvedComposable {
                    Box(modifier = Modifier.size(10.dp).background(Color.Green))
                }
                curvedComposable {
                    BasicText(
                        "More",
                        Modifier.background(Color.Yellow).padding(2.dp),
                        TextStyle(color = Color.Black, fontSize = 14.sp),
                    )
                }
            }
        }
    }
    curvedComposable { Box(modifier = Modifier.size(20.dp).background(Color.Red)) }
}
Parameters
modifier: CurvedModifier = CurvedModifier

The CurvedModifier to apply to this curved column.

radialDirection: CurvedDirection.Radial? = null

Order to lay out components, outside in or inside out. The default is to inherit from the containing curvedColumn or CurvedLayout

angularAlignment: CurvedAlignment.Angular? = null

Angular alignment specifies where to lay down children that are thinner than the curved column, either at the CurvedAlignment.Angular.Start of the layout, at the CurvedAlignment.Angular.End, or CurvedAlignment.Angular.Center. If unspecified or null, they can choose for themselves.

contentBuilder: CurvedScope.() -> Unit

Scope used to provide the content for this column.

CurvedScope.curvedComposable

fun CurvedScope.curvedComposable(
    modifier: CurvedModifier = CurvedModifier,
    radialAlignment: CurvedAlignment.Radial = CurvedAlignment.Radial.Center,
    rotationLocked: Boolean = false,
    content: @Composable BoxScope.() -> Unit
): Unit

Component that allows normal composables to be part of a CurvedLayout.

Parameters
modifier: CurvedModifier = CurvedModifier

The CurvedModifier to apply to this curved composable.

radialAlignment: CurvedAlignment.Radial = CurvedAlignment.Radial.Center

How to align this component if it's thinner than the container.

rotationLocked: Boolean = false

by default (when this is false), the component will be rotated as it moves around the circle, so its base always faces the center. If set to true, it won't be rotated and only moved into position, for example, an upwards pointing arrow will remain pointing upwards wherever it appears on the circle. Note that this is not taken into account when computing the size this will take in the layout, so it's best suited for square/circular things and may require manual sizing when used in other contexts.

content: @Composable BoxScope.() -> Unit

The composable(s) that will be wrapped and laid out as part of the parent container. This has a BoxScope, since it's wrapped inside a Box.

CurvedScope.curvedRow

fun CurvedScope.curvedRow(
    modifier: CurvedModifier = CurvedModifier,
    radialAlignment: CurvedAlignment.Radial? = null,
    angularDirection: CurvedDirection.Angular? = null,
    contentBuilder: CurvedScope.() -> Unit
): Unit

A layout composable that places its children in an arc, rotating them as needed. This is similar to a Row layout, but curved into a segment of an annulus.

The thickness of the layout (the difference between the outer and inner radius) will be the same as the thickest child, and the total angle taken is the sum of the children's angles.

Example usage:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.BasicText
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.wear.compose.foundation.CurvedAlignment
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.background
import androidx.wear.compose.foundation.curvedColumn
import androidx.wear.compose.foundation.curvedComposable
import androidx.wear.compose.foundation.curvedRow
import androidx.wear.compose.foundation.padding
import androidx.wear.compose.foundation.size
import androidx.wear.compose.material.Text

CurvedLayout(modifier = Modifier.fillMaxSize()) {
    curvedComposable { Box(modifier = Modifier.size(20.dp).background(Color.Red)) }
    curvedColumn(angularAlignment = CurvedAlignment.Angular.End) {
        repeat(3) {
            curvedRow {
                curvedComposable {
                    BasicText(
                        "Row #$it",
                        Modifier.background(Color.White).padding(2.dp),
                        TextStyle(color = Color.Black, fontSize = 14.sp),
                    )
                }
                curvedComposable {
                    Box(modifier = Modifier.size(10.dp).background(Color.Green))
                }
                curvedComposable {
                    BasicText(
                        "More",
                        Modifier.background(Color.Yellow).padding(2.dp),
                        TextStyle(color = Color.Black, fontSize = 14.sp),
                    )
                }
            }
        }
    }
    curvedComposable { Box(modifier = Modifier.size(20.dp).background(Color.Red)) }
}
Parameters
modifier: CurvedModifier = CurvedModifier

The CurvedModifier to apply to this curved row.

radialAlignment: CurvedAlignment.Radial? = null

Radial alignment specifies where to lay down children that are thinner than the CurvedRow, either closer to the center CurvedAlignment.Radial.Inner, apart from the center CurvedAlignment.Radial.Outer or in the middle point CurvedAlignment.Radial.Center. If unspecified, they can choose for themselves.

angularDirection: CurvedDirection.Angular? = null

Specify if the children are laid out clockwise or anti-clockwise, and if those needs to be reversed in a Rtl layout. If not specified, it will be inherited from the enclosing curvedRow or CurvedLayout See CurvedDirection.Angular.

contentBuilder: CurvedScope.() -> Unit

Scope used to provide the content for this row.

ScalingLazyListScope.expandableButton

fun ScalingLazyListScope.expandableButton(
    state: ExpandableState,
    key: Any? = null,
    content: @Composable () -> Unit
): Unit

Adds a single item, for the button that controls expandable item(s). The button will be animated out when the corresponding expandables are expanded.

Example of an expandable text:

import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.expandableButton
import androidx.wear.compose.foundation.expandableItem
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.foundation.rememberExpandableState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.OutlinedCompactChip
import androidx.wear.compose.material.Text

val expandableState = rememberExpandableState()

ScalingLazyColumn(modifier = Modifier.fillMaxSize()) {
    expandableItem(expandableState) { expanded ->
        Text(
            "Account Alert: you have made a large purchase.\n" +
                "We have noticed that a large purchase was charged to " +
                "your credit card account. " +
                "Please contact us if you did not perform this purchase. " +
                "Our Customer Service team is available 24 hours a day, " +
                "7 days a week to answer your account or product support question.",
            maxLines = if (expanded) 20 else 3,
            modifier = Modifier.padding(horizontal = 10.dp),
        )
    }

    expandableButton(expandableState) {
        OutlinedCompactChip(
            label = {
                Text("Show More")
                Spacer(Modifier.size(6.dp))
                Icon(painterResource(R.drawable.ic_expand_more_24), "Expand")
            },
            onClick = { expandableState.expanded = true },
        )
    }
}
Parameters
state: ExpandableState

The ExpandableState to connect this button to.

key: Any? = null

A stable and unique key representing the item. Using the same key for multiple items in the list is not allowed. Type of the key should be saveable via Bundle on Android. If null is passed the position in the list will represent the key. When you specify the key the scroll position will be maintained based on the key, which means if you add/remove items before the current visible item the item with the given key will be kept as the first visible one.

content: @Composable () -> Unit

the content displayed, this should usually be a CompactChip or OutlineCompactChip.

ScalingLazyListScope.expandableItem

fun ScalingLazyListScope.expandableItem(
    state: ExpandableState,
    key: Any? = null,
    content: @Composable (expanded: Boolean) -> Unit
): Unit

Adds a single item, that will be expanded/collapsed according to the ExpandableState.

Example of an expandable text:

import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.expandableButton
import androidx.wear.compose.foundation.expandableItem
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.foundation.rememberExpandableState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.OutlinedCompactChip
import androidx.wear.compose.material.Text

val expandableState = rememberExpandableState()

ScalingLazyColumn(modifier = Modifier.fillMaxSize()) {
    expandableItem(expandableState) { expanded ->
        Text(
            "Account Alert: you have made a large purchase.\n" +
                "We have noticed that a large purchase was charged to " +
                "your credit card account. " +
                "Please contact us if you did not perform this purchase. " +
                "Our Customer Service team is available 24 hours a day, " +
                "7 days a week to answer your account or product support question.",
            maxLines = if (expanded) 20 else 3,
            modifier = Modifier.padding(horizontal = 10.dp),
        )
    }

    expandableButton(expandableState) {
        OutlinedCompactChip(
            label = {
                Text("Show More")
                Spacer(Modifier.size(6.dp))
                Icon(painterResource(R.drawable.ic_expand_more_24), "Expand")
            },
            onClick = { expandableState.expanded = true },
        )
    }
}

The item should support two levels of information display (for example, a text showing a few lines in the collapsed state, and more in the expanded state)

Parameters
state: ExpandableState

The ExpandableState connected to this item.

key: Any? = null

A stable and unique key representing the item. Using the same key for multiple items in the list is not allowed. Type of the key should be saveable via Bundle on Android. If null is passed the position in the list will represent the key. When you specify the key the scroll position will be maintained based on the key, which means if you add/remove items before the current visible item the item with the given key will be kept as the first visible one.

content: @Composable (expanded: Boolean) -> Unit

the content displayed by the item, according to its expanded/collapsed state.

ScalingLazyListScope.expandableItems

fun ScalingLazyListScope.expandableItems(
    state: ExpandableState,
    count: Int,
    key: ((index: Int) -> Any)? = null,
    itemContent: @Composable BoxScope.(index: Int) -> Unit
): Unit

Adds a series of items, that will be expanded/collapsed according to the ExpandableState

Example of an expandable list:

import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.expandableButton
import androidx.wear.compose.foundation.expandableItem
import androidx.wear.compose.foundation.expandableItems
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.foundation.rememberExpandableState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.OutlinedCompactChip
import androidx.wear.compose.material.Text

val expandableState = rememberExpandableState()

val sampleItem: @Composable (String) -> Unit = { label ->
    Chip(label = { Text(label) }, onClick = {}, secondaryLabel = { Text("line 2 - Secondary") })
}

val items = List(10) { "Item $it" }
val top = items.take(3)
val rest = items.drop(3)

ScalingLazyColumn(modifier = Modifier.fillMaxSize()) {
    items(top.size) { sampleItem(top[it]) }
    expandableItems(expandableState, rest.size) { sampleItem(rest[it]) }
    expandableButton(expandableState) {
        OutlinedCompactChip(
            label = {
                Text("Show More")
                Spacer(Modifier.size(6.dp))
                Icon(painterResource(R.drawable.ic_expand_more_24), "Expand")
            },
            onClick = { expandableState.expanded = true },
        )
    }
}
Parameters
state: ExpandableState

The ExpandableState connected to these items.

count: Int

The number of items

key: ((index: Int) -> Any)? = null

a factory of stable and unique keys representing the item. Using the same key for multiple items in the list is not allowed. Type of the key should be saveable via Bundle on Android. If null is passed the position in the list will represent the key. When you specify the key the scroll position will be maintained based on the key, which means if you add/remove items before the current visible item the item with the given key will be kept as the first visible one.

itemContent: @Composable BoxScope.(index: Int) -> Unit

the content displayed by a single item

CurvedModifier.padding

fun CurvedModifier.padding(all: Dp = 0.dp): CurvedModifier

Apply all dp space around the component.

Parameters
all: Dp = 0.dp

The space added to all edges.

CurvedModifier.padding

fun CurvedModifier.padding(paddingValues: ArcPaddingValues): CurvedModifier

Apply additional space along the edges of the content.

Parameters
paddingValues: ArcPaddingValues

The ArcPaddingValues to use. See that class and factory methods to see how paddings can be specified.

CurvedModifier.padding

fun CurvedModifier.padding(radial: Dp = 0.dp, angular: Dp = 0.dp): CurvedModifier

Apply angular dp space before and after the component, and radial dp space to the outer and inner edges.

Parameters
radial: Dp = 0.dp

The space added to the outer and inner edges of the content, in dp.

angular: Dp = 0.dp

The space added before and after the content, in dp.

CurvedModifier.padding

fun CurvedModifier.padding(outer: Dp, inner: Dp, before: Dp, after: Dp): CurvedModifier

Apply additional space along the edges of the content. Dimmensions are in dp. For before and after they will be considered as if they are at the midpoint of the content (for conversion between dimension and angle).

Parameters
outer: Dp

The space to add to the outer edge of the content (away from the center of the containing CurvedLayout)

inner: Dp

The space to add to the inner edge of the content (towards the center of the containing CurvedLayout)

before: Dp

The space added before the component, if it was draw clockwise. This is the edge of the component with the "smallest" angle.

after: Dp

The space added after the component, if it was draw clockwise. This is the edge of the component with the "biggest" angle.

CurvedModifier.parentDataModifier

fun CurvedModifier.parentDataModifier(modifyParentData: (Any?) -> Any?): CurvedModifier

A CurvedModifier that provides data to the parent layout. The parent data is commonly used to inform the parent how the child Layout should be measured and positioned.

Parameters
modifyParentData: (Any?) -> Any?

provides a parentData, given the parentData provided through the modifier's chain.

CurvedModifier.radialGradientBackground

fun CurvedModifier.radialGradientBackground(
    vararg colorStops: Pair<FloatColor>,
    cap: StrokeCap = StrokeCap.Butt
): CurvedModifier

Specifies a radial gradient background for a curved element.

Example usage:

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.CurvedTextStyle
import androidx.wear.compose.foundation.angularGradientBackground
import androidx.wear.compose.foundation.basicCurvedText
import androidx.wear.compose.foundation.padding
import androidx.wear.compose.foundation.radialGradientBackground
import androidx.wear.compose.material.Text

CurvedLayout(modifier = Modifier.fillMaxSize()) {
    basicCurvedText(
        "Radial",
        style = { CurvedTextStyle(fontSize = 16.sp, color = Color.Black) },
        modifier =
            CurvedModifier.radialGradientBackground(0f to Color.White, 1f to Color.Black)
                .padding(5.dp),
    )
    basicCurvedText(
        "Angular",
        style = { CurvedTextStyle(fontSize = 16.sp, color = Color.Black) },
        modifier =
            CurvedModifier.angularGradientBackground(0f to Color.White, 1f to Color.Black)
                .padding(5.dp),
    )
}
Parameters
vararg colorStops: Pair<FloatColor>

Colors and their offset in the gradient area. Note that the offsets should be in ascending order. 0 means the outer curve and 1 means the inner curve of the curved element.

cap: StrokeCap = StrokeCap.Butt

How to start and end the background.

CurvedModifier.radialGradientBackground

fun CurvedModifier.radialGradientBackground(
    colors: List<Color>,
    cap: StrokeCap = StrokeCap.Butt
): CurvedModifier

Specifies a radial gradient background for a curved element.

Parameters
colors: List<Color>

Colors in the gradient area. Gradient goes from the outer curve to the inner curve of the curved element.

cap: StrokeCap = StrokeCap.Butt

How to start and end the background.

CurvedModifier.radialSize

fun CurvedModifier.radialSize(thickness: Dp): CurvedModifier

Specify the radialSize (thickness) for the content.

Parameters
thickness: Dp

Indicates the thickness of the content.

CurvedModifier.semantics

fun CurvedModifier.semantics(properties: CurvedSemanticsScope.() -> Unit): CurvedModifier

Allow specifying semantic properties on a curved component. Note that currently only CurvedSemanticsScope.contentDescription and CurvedSemanticsScope.traversalIndex are supported, and they can be applied to curved text and curvedComposable

Sample for setting content description and traversal order:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.traversalIndex
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.CurvedTextStyle
import androidx.wear.compose.foundation.background
import androidx.wear.compose.foundation.basicCurvedText
import androidx.wear.compose.foundation.curvedComposable
import androidx.wear.compose.foundation.padding
import androidx.wear.compose.foundation.semantics
import androidx.wear.compose.foundation.size
import androidx.wear.compose.material.Text

val style =
    CurvedTextStyle(
        letterSpacing = 0.6.sp,
        letterSpacingCounterClockwise = 1.4.sp,
        color = Color.White,
    )
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
    CurvedLayout(modifier = Modifier.fillMaxSize()) {
        basicCurvedText(
            "2 - Left",
            style,
            CurvedModifier.semantics {
                contentDescription = "Left"
                traversalIndex = 2f
            },
        )
        curvedComposable { Box(Modifier.padding(5.dp).background(Color.Red).size(5.dp)) }
        basicCurvedText(
            "3 - Right",
            style,
            CurvedModifier.semantics {
                contentDescription = "Right"
                traversalIndex = 3f
            },
        )
    }
    Row {
        Text("Text 1", Modifier.semantics { traversalIndex = 1f })
        Spacer(Modifier.size(10.dp))
        Text("Text 4", Modifier.semantics { traversalIndex = 4f })
    }
}
Parameters
properties: CurvedSemanticsScope.() -> Unit

The properties to apply, SemanticsPropertyReceiver will be provided in the scope to allow access for common properties and its values.

CurvedModifier.size

fun CurvedModifier.size(
    sweepDegrees: @FloatRange(from = 0.0, to = 360.0) Float,
    thickness: Dp
): CurvedModifier

Specify the dimensions (sweep and thickness) for the content.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.CurvedTextStyle
import androidx.wear.compose.foundation.angularSize
import androidx.wear.compose.foundation.angularSizeDp
import androidx.wear.compose.foundation.background
import androidx.wear.compose.foundation.basicCurvedText
import androidx.wear.compose.foundation.radialSize
import androidx.wear.compose.foundation.size
import androidx.wear.compose.material.Text

CurvedLayout(modifier = Modifier.fillMaxSize()) {
    basicCurvedText(
        "45 deg",
        style = { CurvedTextStyle(fontSize = 16.sp, color = Color.Black) },
        modifier =
            CurvedModifier.background(Color.White).size(sweepDegrees = 45f, thickness = 40.dp),
    )
    basicCurvedText(
        "40 dp",
        style = { CurvedTextStyle(fontSize = 16.sp, color = Color.Black) },
        modifier =
            CurvedModifier.background(Color.Yellow).radialSize(40.dp).angularSizeDp(40.dp),
    )
}
Parameters
sweepDegrees: @FloatRange(from = 0.0, to = 360.0) Float

Indicates the sweep (angular size) of the content.

thickness: Dp

Indicates the thickness (radial size) of the content.

CurvedModifier.sizeIn

fun CurvedModifier.sizeIn(
    minSweepDegrees: @FloatRange(from = 0.0, to = 360.0) Float = 0.0f,
    maxSweepDegrees: @FloatRange(from = 0.0, to = 360.0) Float = 360.0f,
    minThickness: Dp = 0.dp,
    maxThickness: Dp = Dp.Infinity
): CurvedModifier

Specify the dimensions of the content to be restricted between the given bounds.

Parameters
minSweepDegrees: @FloatRange(from = 0.0, to = 360.0) Float = 0.0f

the minimum angle (in degrees) for the content.

maxSweepDegrees: @FloatRange(from = 0.0, to = 360.0) Float = 360.0f

the maximum angle (in degrees) for the content.

minThickness: Dp = 0.dp

the minimum thickness (radial size) for the content.

maxThickness: Dp = Dp.Infinity

the maximum thickness (radial size) for the content.

CurvedModifier.weight

fun CurvedModifier.weight(
    weight: @FloatRange(from = 0.0, fromInclusive = false) Float
): CurvedModifier

Size the element's proportional to its weight relative to other weighted sibling elements in the container (this will be the height in a curvedColumn and the width in a curvedRow). The parent will divide the space remaining after measuring unweighted child elements and distribute it according to this weight.

Example usage:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.sp
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.angularSize
import androidx.wear.compose.foundation.background
import androidx.wear.compose.foundation.basicCurvedText
import androidx.wear.compose.foundation.curvedRow
import androidx.wear.compose.foundation.weight
import androidx.wear.compose.material.Text

CurvedLayout(modifier = Modifier.fillMaxSize().background(Color.White)) {
    // Evenly spread A, B & C in a 90 degree angle.
    curvedRow(modifier = CurvedModifier.angularSize(90f)) {
        basicCurvedText("A")
        curvedRow(modifier = CurvedModifier.weight(1f)) {}
        basicCurvedText("B")
        curvedRow(modifier = CurvedModifier.weight(1f)) {}
        basicCurvedText("C")
    }
}
Parameters
weight: @FloatRange(from = 0.0, fromInclusive = false) Float

The proportional size to give to this element, as related to the total of all weighted siblings. Must be positive.

Top-level properties

LocalAmbientModeManager

val LocalAmbientModeManagerProvidableCompositionLocal<AmbientModeManager?>

A androidx.compose.runtime.CompositionLocal that provides the current AmbientModeManager interface.

This local is the primary way for any composable in the hierarchy to access the manager responsible for tracking the ambient (low-power) mode state.

Composables read the manager using LocalAmbientModeManager.current and subscribe to changes via the AmbientModeManager.currentAmbientMode property.

If no AmbientModeManager is explicitly provided higher up the tree (e.g., via rememberAmbientModeManager), this local returns null.

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.wear.compose.foundation.AmbientMode
import androidx.wear.compose.foundation.LocalAmbientModeManager
import androidx.wear.compose.foundation.rememberAmbientModeManager
import androidx.wear.compose.material.Text

// **Best Practice Note:** In a production application, the AmbientModeManager should be
// instantiated and provided at the highest level of the Compose hierarchy (typically in
// the host Activity's setContent block) using a CompositionLocalProvider. This ensures
// proper lifecycle management and broad accessibility.

// For this self-contained demo, AmbientModeManager is created and provided locally:
val activityAmbientModeManager = rememberAmbientModeManager()
CompositionLocalProvider(LocalAmbientModeManager provides activityAmbientModeManager) {
    val ambientModeManager = LocalAmbientModeManager.current
    val ambientMode = ambientModeManager?.currentAmbientMode
    Column(
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.fillMaxSize(),
    ) {
        val ambientModeName =
            when (ambientMode) {
                is AmbientMode.Interactive -> "Interactive"
                is AmbientMode.Ambient -> "Ambient"
                else -> "Unknown"
            }

        val color = if (ambientMode is AmbientMode.Ambient) Color.Gray else Color.Yellow
        Text(text = "$ambientModeName Mode", color = color)
    }
}

LocalReduceMotion

val LocalReduceMotionProvidableCompositionLocal<Boolean>

CompositionLocal for global reduce-motion setting, which turns off animations and screen movements. To use, call LocalReduceMotion.current, which returns a Boolean.

LocalScreenIsActive

val LocalScreenIsActiveProvidableCompositionLocal<Boolean>

CompositionLocal used to express/determine if a screen is active, as specified by each component (for example, it could be updated when the user is in the middle of the gesture to switch screens, or after the gesture is done). Components that manage multiple screens (like pager and swipe to dismiss) provide this, and can be used at the screen level to update the UI or perform optimizations on inactive screens.

Defaults to true

LocalSwipeToDismissBackgroundScrimColor

val LocalSwipeToDismissBackgroundScrimColorProvidableCompositionLocal<Color>

CompositionLocal containing the background scrim color of BasicSwipeToDismissBox.

Defaults to Color.Black if not explicitly set.

LocalSwipeToDismissContentScrimColor

val LocalSwipeToDismissContentScrimColorProvidableCompositionLocal<Color>

CompositionLocal containing the content scrim color of BasicSwipeToDismissBox.

Defaults to Color.Black if not explicitly set.