androidx.wear.compose.material

Interfaces

ButtonBorder

Represents the border stroke used in a Button in different states.

ButtonColors

Represents the background and content colors used in a button in different states.

CheckboxColors

Represents the content colors used in Checkbox in different states.

ChipBorder

Represents the border stroke used in a Chip in different states.

ChipColors

Represents the background and content colors used in a chip in different states.

InlineSliderColors

Represents the background and content colors used in InlineSlider in different states.

PageIndicatorState

An interface for connection between Pager and HorizontalPageIndicator.

PickerScope

Receiver scope which is used by Picker.

PositionIndicatorState

An object representing the relative position of a scrollbar or rolling side button or rotating bezel position.

RadioButtonColors

Represents the content colors used in RadioButton in different states.

ScalingLazyListItemInfo

This interface is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

ScalingLazyListItemScope

This interface is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

ScalingLazyListLayoutInfo

This interface is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

ScalingLazyListScope

This interface is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

ScalingParams

This interface is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

SelectableChipColors

Represents the background and content colors used in SelectableChips in different states.

SplitSelectableChipColors

Represents the background and content colors used in SplitSelectableChips in different states.

SplitToggleChipColors

Represents the background and content colors used in SplitToggleChips in different states.

SwitchColors

Represents the content colors used in Switch in different states.

ThresholdConfig

Interface to compute a threshold between two anchors/states in a swipeable.

TimeSource

An interface which is responsible for retrieving a formatted time.

ToggleButtonColors

Represents the background and content colors used in a toggle button in different states.

ToggleChipColors

Represents the background and content colors used in ToggleChips in different states.

TouchExplorationStateProvider

A functional interface for providing the state of touch exploration services.

Classes

AutoCenteringParams

This class is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

Colors
FixedThreshold

A fixed threshold will be at an offset away from the first anchor.

FractionalThreshold

A fractional threshold will be at a fraction of the way between the two anchors.

PageIndicatorStyle

The style of HorizontalPageIndicator.

PickerGroupItem

A class for representing Picker which will be composed inside a PickerGroup.

PickerGroupState

A state object that can be used to observe the selected Picker.

PickerState

A state object that can be hoisted to observe item selection.

PlaceholderState

A state object that can be used to control placeholders.

PositionIndicatorAlignment

Specifies where in the screen the Position indicator will be.

PositionIndicatorVisibility

Enum used by adapters to specify if the Position Indicator needs to be shown, hidden, or hidden after a small delay.

ResistanceConfig

Specifies how resistance is calculated in swipeable.

ScalingLazyListAnchorType

This class is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

ScalingLazyListState

This class is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

Shapes

Components are grouped into shape categories based on common features.

SwipeProgress

Collects information about the ongoing swipe or animation in swipeable.

SwipeToDismissBoxState

This class is deprecated. SwipeToDismissBoxState has been migrated, please import it from androidx.wear.compose.foundation.

SwipeToRevealActionColors

A class representing the colors applied in SwipeToReveal actions.

SwipeableState

State of the swipeable modifier.

Typography

Class holding typography definitions as defined by the Wear Material typography specification.

VignettePosition

Possible combinations for vignette state.

Objects

ButtonDefaults

Contains the default values used by Button.

CardDefaults

Contains the default values used by Card

CheckboxDefaults

Contains the default values used by Checkbox.

ChipDefaults

Contains the default values used by Chip

ContentAlpha

Default alpha levels used by Material components.

InlineSliderDefaults

Defaults used by slider

MaterialTheme
PageIndicatorDefaults

Contains the default values used by HorizontalPageIndicator

PickerDefaults

Contains the default values used by Picker

PlaceholderDefaults

Contains the default values used for providing placeholders.

PositionIndicatorDefaults

Contains the default values used for PositionIndicator.

ProgressIndicatorDefaults

Contains the default values used for CircularProgressIndicator.

RadioButtonDefaults

Contains the default values used by RadioButton.

ScalingLazyColumnDefaults

This object is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

SelectableChipDefaults

Contains the default values used by SelectableChips and SplitSelectableChips

StepperDefaults

Defaults used by stepper

SwipeToDismissBoxDefaults

This object is deprecated. Please import SwipeToDismissBoxDefaults from androidx.wear.compose.foundation.

SwipeToRevealDefaults

Defaults for Material SwipeToReveal.

SwipeableDefaults

Contains useful defaults for swipeable and SwipeableState.

SwitchDefaults

Contains the default values used by Switch.

TimeTextDefaults

Contains the default values used by TimeText

ToggleButtonDefaults

Contains the default values used by ToggleButton.

ToggleChipDefaults

Contains the default values used by ToggleChips and SplitToggleChips

Annotations

ExperimentalWearMaterialApi
ScalingLazyScopeMarker

This annotation is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

Enums

SwipeToDismissKeys

Keys used to persistent state in SwipeToDismissBox.

SwipeToDismissValue

This enum is deprecated. SwipeToDismiss has been migrated to androidx.wear.compose.foundation.

Top-level functions summary

Unit
@Composable
AppCard(
    onClick: () -> Unit,
    appName: @Composable RowScope.() -> Unit,
    time: @Composable RowScope.() -> Unit,
    title: @Composable RowScope.() -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    appImage: (@Composable RowScope.() -> Unit)?,
    backgroundPainter: Painter,
    contentColor: Color,
    appColor: Color,
    timeColor: Color,
    titleColor: Color,
    content: @Composable ColumnScope.() -> Unit
)

Opinionated Wear Material Card that offers a specific 5 slot layout to show information about an application, e.g. a notification.

Unit
@Composable
Button(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    colors: ButtonColors,
    interactionSource: MutableInteractionSource?,
    shape: Shape,
    border: ButtonBorder,
    content: @Composable BoxScope.() -> Unit
)

Wear Material Button that offers a single slot to take any content (text, icon or image).

Unit
@Composable
Card(
    onClick: () -> Unit,
    modifier: Modifier,
    backgroundPainter: Painter,
    contentColor: Color,
    enabled: Boolean,
    contentPadding: PaddingValues,
    shape: Shape,
    interactionSource: MutableInteractionSource?,
    role: Role?,
    content: @Composable ColumnScope.() -> Unit
)

Base level Wear Material Card that offers a single slot to take any content.

Unit
@Composable
Checkbox(
    checked: Boolean,
    modifier: Modifier,
    colors: CheckboxColors,
    enabled: Boolean,
    onCheckedChange: ((Boolean) -> Unit)?,
    interactionSource: MutableInteractionSource?
)

Checkbox provides an animated checkbox for use as a toggle control in ToggleChip or SplitToggleChip.

Unit
@Composable
Chip(
    onClick: () -> Unit,
    colors: ChipColors,
    border: ChipBorder,
    modifier: Modifier,
    enabled: Boolean,
    contentPadding: PaddingValues,
    shape: Shape,
    interactionSource: MutableInteractionSource?,
    role: Role?,
    content: @Composable RowScope.() -> Unit
)

Base level Wear Material Chip that offers a single slot to take any content.

Unit
@Composable
Chip(
    label: @Composable RowScope.() -> Unit,
    onClick: () -> Unit,
    modifier: Modifier,
    secondaryLabel: (@Composable RowScope.() -> Unit)?,
    icon: (@Composable BoxScope.() -> Unit)?,
    colors: ChipColors,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    contentPadding: PaddingValues,
    shape: Shape,
    border: ChipBorder
)

Wear Material Chip that offers three slots and a specific layout for an icon, label and secondaryLabel.

Unit
@Composable
CircularProgressIndicator(
    modifier: Modifier,
    startAngle: Float,
    indicatorColor: Color,
    trackColor: Color,
    strokeWidth: Dp
)

Indeterminate Material Design circular progress indicator.

Unit
@Composable
CircularProgressIndicator(
    progress: @FloatRange(from = 0.0, to = 1.0) Float,
    modifier: Modifier,
    startAngle: Float,
    endAngle: Float,
    indicatorColor: Color,
    trackColor: Color,
    strokeWidth: Dp
)

Determinate Material Design circular progress indicator.

Unit
@Composable
CompactButton(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    colors: ButtonColors,
    backgroundPadding: Dp,
    interactionSource: MutableInteractionSource?,
    shape: Shape,
    border: ButtonBorder,
    content: @Composable BoxScope.() -> Unit
)

Wear Material CompactButton that offers a single slot to take any content (text, icon or image).

Unit
@Composable
CompactChip(
    onClick: () -> Unit,
    modifier: Modifier,
    label: (@Composable RowScope.() -> Unit)?,
    icon: (@Composable BoxScope.() -> Unit)?,
    colors: ChipColors,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    contentPadding: PaddingValues,
    shape: Shape,
    border: ChipBorder
)

A compact Wear Material Chip that offers two slots and a specific layout for an icon and label.

Unit
@Composable
HorizontalPageIndicator(
    pageIndicatorState: PageIndicatorState,
    modifier: Modifier,
    indicatorStyle: PageIndicatorStyle,
    selectedColor: Color,
    unselectedColor: Color,
    indicatorSize: Dp,
    spacing: Dp,
    indicatorShape: Shape
)

A horizontal indicator for a Pager, representing the currently active page and total pages drawn using a Shape.

Unit
@Composable
Icon(
    bitmap: ImageBitmap,
    contentDescription: String?,
    modifier: Modifier,
    tint: Color
)

Icon component that draws bitmap using tint, defaulting to LocalContentColor.

Unit
@Composable
Icon(
    imageVector: ImageVector,
    contentDescription: String?,
    modifier: Modifier,
    tint: Color
)

Icon component that draws imageVector using tint, defaulting to LocalContentColor.

Unit
@Composable
Icon(
    painter: Painter,
    contentDescription: String?,
    modifier: Modifier,
    tint: Color
)

Icon component that draws a painter using tint, defaulting to LocalContentColor.

Unit
@Composable
InlineSlider(
    value: Int,
    onValueChange: (Int) -> Unit,
    valueProgression: IntProgression,
    decreaseIcon: @Composable () -> Unit,
    increaseIcon: @Composable () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    segmented: Boolean,
    colors: InlineSliderColors
)

InlineSlider allows users to make a selection from a range of values.

Unit
@Composable
InlineSlider(
    value: Float,
    onValueChange: (Float) -> Unit,
    steps: Int,
    decreaseIcon: @Composable () -> Unit,
    increaseIcon: @Composable () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    valueRange: ClosedFloatingPointRange<Float>,
    segmented: Boolean,
    colors: InlineSliderColors
)

InlineSlider allows users to make a selection from a range of values.

Unit
@Composable
ListHeader(
    modifier: Modifier,
    backgroundColor: Color,
    contentColor: Color,
    content: @Composable RowScope.() -> Unit
)

A slot based composable for creating a list header item.

Unit
@Composable
MaterialTheme(
    colors: Colors,
    typography: Typography,
    shapes: Shapes,
    content: @Composable () -> Unit
)

MaterialTheme defines the styling principles from the WearOS Material design specification which extends the Material design specification.

Unit
@Composable
OutlinedButton(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    colors: ButtonColors,
    interactionSource: MutableInteractionSource?,
    shape: Shape,
    border: ButtonBorder,
    content: @Composable BoxScope.() -> Unit
)

Wear Material OutlinedButton that offers a single slot to take any content (text, icon or image).

Unit
@Composable
OutlinedChip(
    label: @Composable RowScope.() -> Unit,
    onClick: () -> Unit,
    modifier: Modifier,
    secondaryLabel: (@Composable RowScope.() -> Unit)?,
    icon: (@Composable BoxScope.() -> Unit)?,
    colors: ChipColors,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    contentPadding: PaddingValues,
    shape: Shape,
    border: ChipBorder
)

Wear Material OutlinedChip that offers three slots and a specific layout for an icon, label and secondaryLabel.

Unit
@Composable
OutlinedCompactButton(
    onClick: () -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    colors: ButtonColors,
    backgroundPadding: Dp,
    interactionSource: MutableInteractionSource?,
    shape: Shape,
    border: ButtonBorder,
    content: @Composable BoxScope.() -> Unit
)

Wear Material OutlinedCompactButton that offers a single slot to take any content (text, icon or image).

Unit
@Composable
OutlinedCompactChip(
    onClick: () -> Unit,
    modifier: Modifier,
    label: (@Composable RowScope.() -> Unit)?,
    icon: (@Composable BoxScope.() -> Unit)?,
    colors: ChipColors,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    contentPadding: PaddingValues,
    shape: Shape,
    border: ChipBorder
)

A compact Outlined Wear Material Chip that offers two slots and a specific layout for an icon and label.

Unit
@Composable
Picker(
    state: PickerState,
    modifier: Modifier,
    readOnly: Boolean,
    readOnlyLabel: (@Composable BoxScope.() -> Unit)?,
    scalingParams: ScalingParams,
    separation: Dp,
    gradientRatio: @FloatRange(from = 0.0, to = 0.5) Float,
    gradientColor: Color,
    flingBehavior: FlingBehavior,
    option: @Composable PickerScope.(optionIndex: Int) -> Unit
)

This function is deprecated. This overload is provided for backwards compatibility with Compose for Wear OS 1.0.A newer overload is available with additional contentDescription, onSelected and userScrollEnabled parameters, which improves accessibility of [Picker].

Unit
@Composable
Picker(
    state: PickerState,
    contentDescription: String?,
    modifier: Modifier,
    readOnly: Boolean,
    readOnlyLabel: (@Composable BoxScope.() -> Unit)?,
    onSelected: () -> Unit,
    scalingParams: ScalingParams,
    separation: Dp,
    gradientRatio: @FloatRange(from = 0.0, to = 0.5) Float,
    gradientColor: Color,
    flingBehavior: FlingBehavior,
    userScrollEnabled: Boolean,
    rotaryScrollableBehavior: RotaryScrollableBehavior?,
    option: @Composable PickerScope.(optionIndex: Int) -> Unit
)

A scrollable list of items to pick from.

Unit
@Composable
PickerGroup(
    vararg pickers: PickerGroupItem,
    modifier: Modifier,
    pickerGroupState: PickerGroupState,
    onSelected: (selectedIndex: Int) -> Unit,
    autoCenter: Boolean,
    propagateMinConstraints: Boolean,
    touchExplorationStateProvider: TouchExplorationStateProvider,
    separator: (@Composable (Int) -> Unit)?
)

A group of Pickers to build components where multiple pickers are required to be combined together.

Unit
@Composable
PositionIndicator(
    scalingLazyListState: ScalingLazyListState,
    modifier: Modifier,
    reverseDirection: Boolean
)

This function is deprecated. This overload is provided for backwards compatibility with Compose for Wear OS 1.1.A newer overload is available which uses ScalingLazyListState from androidx.wear.compose.foundation.lazy package

Unit
@Composable
PositionIndicator(
    lazyListState: LazyListState,
    modifier: Modifier,
    reverseDirection: Boolean,
    fadeInAnimationSpec: AnimationSpec<Float>,
    fadeOutAnimationSpec: AnimationSpec<Float>,
    positionAnimationSpec: AnimationSpec<Float>
)

Creates an PositionIndicator based on the values in a LazyListState object that a LazyColumn uses.

Unit
@Composable
PositionIndicator(
    scalingLazyListState: ScalingLazyListState,
    modifier: Modifier,
    reverseDirection: Boolean,
    fadeInAnimationSpec: AnimationSpec<Float>,
    fadeOutAnimationSpec: AnimationSpec<Float>,
    positionAnimationSpec: AnimationSpec<Float>
)

Creates an PositionIndicator based on the values in a ScalingLazyListState object that a ScalingLazyColumn uses.

Unit
@Composable
PositionIndicator(
    scrollState: ScrollState,
    modifier: Modifier,
    reverseDirection: Boolean,
    fadeInAnimationSpec: AnimationSpec<Float>,
    fadeOutAnimationSpec: AnimationSpec<Float>,
    positionAnimationSpec: AnimationSpec<Float>
)

Creates an PositionIndicator based on the values in a ScrollState object. e.g. a Column implementing Modifier.verticalScroll provides a ScrollState.

Unit
@Composable
PositionIndicator(
    value: () -> Float,
    modifier: Modifier,
    range: ClosedFloatingPointRange<Float>,
    color: Color,
    reverseDirection: Boolean,
    position: PositionIndicatorAlignment,
    fadeInAnimationSpec: AnimationSpec<Float>,
    fadeOutAnimationSpec: AnimationSpec<Float>,
    positionAnimationSpec: AnimationSpec<Float>
)

Creates a PositionIndicator for controls like rotating side button, rotating bezel or slider.

Unit
@Composable
PositionIndicator(
    state: PositionIndicatorState,
    indicatorHeight: Dp,
    indicatorWidth: Dp,
    paddingHorizontal: Dp,
    modifier: Modifier,
    background: Color,
    color: Color,
    reverseDirection: Boolean,
    position: PositionIndicatorAlignment,
    fadeInAnimationSpec: AnimationSpec<Float>,
    fadeOutAnimationSpec: AnimationSpec<Float>,
    positionAnimationSpec: AnimationSpec<Float>
)

An indicator on one side of the screen to show the current PositionIndicatorState.

Unit

This function is used to set the current value of LocalTextStyle, merging the given style with the current style values for any missing attributes.

Unit
@Composable
RadioButton(
    selected: Boolean,
    modifier: Modifier,
    colors: RadioButtonColors,
    enabled: Boolean,
    onClick: (() -> Unit)?,
    interactionSource: MutableInteractionSource?
)

RadioButton provides an animated radio button for use as a toggle control in ToggleChip or SplitToggleChip.

Unit
@Composable
Scaffold(
    modifier: Modifier,
    vignette: (@Composable () -> Unit)?,
    positionIndicator: (@Composable () -> Unit)?,
    pageIndicator: (@Composable () -> Unit)?,
    timeText: (@Composable () -> Unit)?,
    content: @Composable () -> Unit
)

Scaffold implements the basic Wear Material Design visual layout structure.

Unit
@Composable
ScalingLazyColumn(
    modifier: Modifier,
    state: ScalingLazyListState,
    contentPadding: PaddingValues,
    reverseLayout: Boolean,
    verticalArrangement: Arrangement.Vertical,
    horizontalAlignment: Alignment.Horizontal,
    flingBehavior: FlingBehavior,
    userScrollEnabled: Boolean,
    scalingParams: ScalingParams,
    anchorType: ScalingLazyListAnchorType,
    autoCentering: AutoCenteringParams?,
    content: ScalingLazyListScope.() -> Unit
)

This function is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

Unit
@Composable
SelectableChip(
    selected: Boolean,
    onClick: (Boolean) -> Unit,
    label: @Composable RowScope.() -> Unit,
    modifier: Modifier,
    appIcon: (@Composable BoxScope.() -> Unit)?,
    secondaryLabel: (@Composable RowScope.() -> Unit)?,
    colors: SelectableChipColors,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    contentPadding: PaddingValues,
    shape: Shape,
    selectionControl: @Composable () -> Unit
)

A SelectableChip is a specialized type of Chip that includes a slot for a bi-state selection control such as a radio button.

Unit
@Composable
SplitSelectableChip(
    selected: Boolean,
    onSelectionClick: (Boolean) -> Unit,
    label: @Composable RowScope.() -> Unit,
    onContainerClick: () -> Unit,
    modifier: Modifier,
    secondaryLabel: (@Composable RowScope.() -> Unit)?,
    colors: SplitSelectableChipColors,
    enabled: Boolean,
    selectionInteractionSource: MutableInteractionSource?,
    containerInteractionSource: MutableInteractionSource?,
    contentPadding: PaddingValues,
    shape: Shape,
    selectionControl: @Composable BoxScope.() -> Unit
)

A SplitSelectableChip is a specialized type of Chip that includes a slot for a selection control, such as a radio button.

Unit
@Composable
SplitToggleChip(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    label: @Composable RowScope.() -> Unit,
    onClick: () -> Unit,
    toggleControl: @Composable BoxScope.() -> Unit,
    modifier: Modifier,
    secondaryLabel: (@Composable RowScope.() -> Unit)?,
    colors: SplitToggleChipColors,
    enabled: Boolean,
    checkedInteractionSource: MutableInteractionSource?,
    clickInteractionSource: MutableInteractionSource?,
    contentPadding: PaddingValues,
    shape: Shape
)

A SplitToggleChip is a specialized type of Chip that includes a slot for a toggle control, such as a toggle or checkbox.

Unit
@Composable
Stepper(
    value: Int,
    onValueChange: (Int) -> Unit,
    valueProgression: IntProgression,
    decreaseIcon: @Composable () -> Unit,
    increaseIcon: @Composable () -> Unit,
    modifier: Modifier,
    backgroundColor: Color,
    contentColor: Color,
    iconColor: Color,
    enableRangeSemantics: Boolean,
    content: @Composable BoxScope.() -> Unit
)

Stepper allows users to make a selection from a range of values.

Unit
@Composable
Stepper(
    value: Float,
    onValueChange: (Float) -> Unit,
    steps: Int,
    decreaseIcon: @Composable () -> Unit,
    increaseIcon: @Composable () -> Unit,
    modifier: Modifier,
    valueRange: ClosedFloatingPointRange<Float>,
    backgroundColor: Color,
    contentColor: Color,
    iconColor: Color,
    enableRangeSemantics: Boolean,
    content: @Composable BoxScope.() -> Unit
)

Stepper allows users to make a selection from a range of values.

Unit
@Composable
SwipeToDismissBox(
    state: SwipeToDismissBoxState,
    modifier: Modifier,
    backgroundScrimColor: Color,
    contentScrimColor: Color,
    backgroundKey: Any,
    contentKey: Any,
    hasBackground: Boolean,
    content: @Composable BoxScope.(isBackground: Boolean) -> Unit
)

Wear Material SwipeToDismissBox that handles the swipe-to-dismiss gesture.

Unit
@Composable
SwipeToDismissBox(
    state: SwipeToDismissBoxState,
    modifier: Modifier,
    backgroundScrimColor: Color,
    contentScrimColor: Color,
    backgroundKey: Any,
    contentKey: Any,
    hasBackground: Boolean,
    content: @Composable BoxScope.(isBackground: Boolean) -> Unit
)

This function is deprecated. This overload is provided for backwards compatibility.

Unit
@Composable
SwipeToDismissBox(
    onDismissed: () -> Unit,
    modifier: Modifier,
    state: SwipeToDismissBoxState,
    backgroundScrimColor: Color,
    contentScrimColor: Color,
    backgroundKey: Any,
    contentKey: Any,
    hasBackground: Boolean,
    content: @Composable BoxScope.(isBackground: Boolean) -> Unit
)

Wear Material SwipeToDismissBox that handles the swipe-to-dismiss gesture.

Unit
@ExperimentalWearMaterialApi
@Composable
SwipeToRevealCard(
    primaryAction: @Composable RevealScope.() -> Unit,
    revealState: RevealState,
    onFullSwipe: () -> Unit,
    modifier: Modifier,
    secondaryAction: (@Composable RevealScope.() -> Unit)?,
    undoPrimaryAction: (@Composable RevealScope.() -> Unit)?,
    undoSecondaryAction: (@Composable RevealScope.() -> Unit)?,
    colors: SwipeToRevealActionColors,
    shape: Shape,
    content: @Composable () -> Unit
)

SwipeToReveal Material composable for Cards.

Unit
@ExperimentalWearMaterialApi
@Composable
SwipeToRevealChip(
    primaryAction: @Composable RevealScope.() -> Unit,
    revealState: RevealState,
    onFullSwipe: () -> Unit,
    modifier: Modifier,
    secondaryAction: (@Composable RevealScope.() -> Unit)?,
    undoPrimaryAction: (@Composable RevealScope.() -> Unit)?,
    undoSecondaryAction: (@Composable RevealScope.() -> Unit)?,
    colors: SwipeToRevealActionColors,
    shape: Shape,
    content: @Composable () -> Unit
)

SwipeToReveal Material composable for Chips.

Unit
@Composable
Switch(
    checked: Boolean,
    modifier: Modifier,
    colors: SwitchColors,
    enabled: Boolean,
    onCheckedChange: ((Boolean) -> Unit)?,
    interactionSource: MutableInteractionSource?
)

Switch provides an animated switch for use as a toggle control in ToggleChip or SplitToggleChip.

Unit
@Composable
Text(
    text: String,
    modifier: Modifier,
    color: Color,
    fontSize: TextUnit,
    fontStyle: FontStyle?,
    fontWeight: FontWeight?,
    fontFamily: FontFamily?,
    letterSpacing: TextUnit,
    textDecoration: TextDecoration?,
    textAlign: TextAlign?,
    lineHeight: TextUnit,
    overflow: TextOverflow,
    softWrap: Boolean,
    maxLines: Int,
    minLines: Int,
    onTextLayout: (TextLayoutResult) -> Unit,
    style: TextStyle
)

High level element that displays text and provides semantics / accessibility information.

Unit
@Composable
Text(
    text: AnnotatedString,
    modifier: Modifier,
    color: Color,
    fontSize: TextUnit,
    fontStyle: FontStyle?,
    fontWeight: FontWeight?,
    fontFamily: FontFamily?,
    letterSpacing: TextUnit,
    textDecoration: TextDecoration?,
    textAlign: TextAlign?,
    lineHeight: TextUnit,
    overflow: TextOverflow,
    softWrap: Boolean,
    maxLines: Int,
    minLines: Int,
    inlineContent: Map<StringInlineTextContent>,
    onTextLayout: (TextLayoutResult) -> Unit,
    style: TextStyle
)

High level element that displays text and provides semantics / accessibility information.

Unit
@Composable
TimeText(
    modifier: Modifier,
    timeSource: TimeSource,
    timeTextStyle: TextStyle,
    contentPadding: PaddingValues,
    startLinearContent: (@Composable () -> Unit)?,
    startCurvedContent: (CurvedScope.() -> Unit)?,
    endLinearContent: (@Composable () -> Unit)?,
    endCurvedContent: (CurvedScope.() -> Unit)?,
    textLinearSeparator: @Composable () -> Unit,
    textCurvedSeparator: CurvedScope.() -> Unit
)

Layout to show the current time and a label at the top of the screen.

Unit
@Composable
TitleCard(
    onClick: () -> Unit,
    title: @Composable RowScope.() -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    time: (@Composable RowScope.() -> Unit)?,
    backgroundPainter: Painter,
    contentColor: Color,
    titleColor: Color,
    timeColor: Color,
    content: @Composable ColumnScope.() -> Unit
)

Opinionated Wear Material Card that offers a specific 3 slot layout to show interactive information about an application, e.g. a message.

Unit
@Composable
ToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier,
    enabled: Boolean,
    colors: ToggleButtonColors,
    interactionSource: MutableInteractionSource?,
    shape: Shape,
    role: Role,
    content: @Composable BoxScope.() -> Unit
)

Wear Material ToggleButton that offers a single slot to take any content (text, icon or image).

Unit
@Composable
ToggleChip(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    label: @Composable RowScope.() -> Unit,
    toggleControl: @Composable () -> Unit,
    modifier: Modifier,
    appIcon: (@Composable BoxScope.() -> Unit)?,
    secondaryLabel: (@Composable RowScope.() -> Unit)?,
    colors: ToggleChipColors,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    contentPadding: PaddingValues,
    shape: Shape
)

A ToggleChip is a specialized type of Chip that includes a slot for a bi-state toggle control such as a toggle or checkbox.

Unit
@Composable
Vignette(vignettePosition: VignettePosition, modifier: Modifier)

Vignette is whole screen decoration used to blur the top and bottom of the edges of a wearable screen when scrolling content is displayed.

Color
@Composable
contentColorFor(backgroundColor: Color)

The Material color system contains pairs of colors that are typically used for the background and content color inside a component.

PickerGroupState
@Composable
rememberPickerGroupState(initiallySelectedIndex: Int)

Creates a PickerGroupState that is remembered across compositions.

PickerState
@Composable
rememberPickerState(
    initialNumberOfOptions: Int,
    initiallySelectedOption: Int,
    repeatItems: Boolean
)

Creates a PickerState that is remembered across compositions.

PlaceholderState

Creates a PlaceholderState that is remembered across compositions.

ScalingLazyListState
@Composable
rememberScalingLazyListState(
    initialCenterItemIndex: Int,
    initialCenterItemScrollOffset: Int
)

This function is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

SwipeToDismissBoxState
@Composable
rememberSwipeToDismissBoxState(
    animationSpec: AnimationSpec<Float>,
    confirmStateChange: (SwipeToDismissValue) -> Boolean
)

This function is deprecated. Please import rememberSwipeToDismissBoxState from androidx.wear.compose.foundation.

SwipeableState<T>
@Composable
@ExperimentalWearMaterialApi
<T : Any> rememberSwipeableState(
    initialValue: T,
    animationSpec: AnimationSpec<Float>,
    confirmStateChange: (newValue) -> Boolean
)

Create and remember a SwipeableState with the default animation clock.

IndicationNodeFactory
ripple(bounded: Boolean, radius: Dp, color: Color)

Creates a Ripple using the provided values and values inferred from the theme.

IndicationNodeFactory
ripple(color: ColorProducer, bounded: Boolean, radius: Dp)

Creates a Ripple using the provided values and values inferred from the theme.

Extension functions summary

Unit
@ExperimentalWearMaterialApi
@Composable
RevealScope.SwipeToRevealPrimaryAction(
    revealState: RevealState,
    onClick: () -> Unit,
    icon: @Composable () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier,
    interactionSource: MutableInteractionSource?
)

A composable which can be used for setting the primary action of material SwipeToRevealCard and SwipeToRevealChip.

Unit
@ExperimentalWearMaterialApi
@Composable
RevealScope.SwipeToRevealSecondaryAction(
    revealState: RevealState,
    onClick: () -> Unit,
    modifier: Modifier,
    interactionSource: MutableInteractionSource?,
    content: @Composable () -> Unit
)

A composable which can be used for setting the secondary action of material SwipeToRevealCard and SwipeToRevealChip.

Unit
@ExperimentalWearMaterialApi
@Composable
RevealScope.SwipeToRevealUndoAction(
    revealState: RevealState,
    onClick: () -> Unit,
    modifier: Modifier,
    interactionSource: MutableInteractionSource?,
    icon: (@Composable () -> Unit)?,
    label: (@Composable () -> Unit)?
)

A composable which can be used for setting the undo action of material SwipeToRevealCard and SwipeToRevealChip.

Color
Colors.contentColorFor(backgroundColor: Color)

The Material color system contains pairs of colors that are typically used for the background and content color inside a component.

Unit
CurvedScope.curvedText(
    text: String,
    modifier: CurvedModifier,
    background: Color,
    color: Color,
    fontSize: TextUnit,
    fontFamily: FontFamily?,
    fontWeight: FontWeight?,
    fontStyle: FontStyle?,
    fontSynthesis: FontSynthesis?,
    style: CurvedTextStyle?,
    angularDirection: CurvedDirection.Angular?,
    overflow: TextOverflow
)

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

Modifier
Modifier.edgeSwipeToDismiss(
    swipeToDismissBoxState: SwipeToDismissBoxState,
    edgeWidth: Dp
)

This function is deprecated. SwipeToDismiss has been migrated to androidx.wear.compose.foundation.

inline Unit
<T : Any?> ScalingLazyListScope.items(
    items: Array<T>,
    noinline key: ((item) -> Any)?,
    crossinline itemContent: @Composable ScalingLazyListItemScope.(item) -> Unit
)

This function is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

inline Unit
<T : Any?> ScalingLazyListScope.items(
    items: List<T>,
    noinline key: ((item) -> Any)?,
    crossinline itemContent: @Composable ScalingLazyListItemScope.(item) -> Unit
)

This function is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

inline Unit
<T : Any?> ScalingLazyListScope.itemsIndexed(
    items: Array<T>,
    noinline key: ((index: Int, item) -> Any)?,
    crossinline itemContent: @Composable ScalingLazyListItemScope.(index: Int, item) -> Unit
)

This function is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

inline Unit
<T : Any?> ScalingLazyListScope.itemsIndexed(
    items: List<T>,
    noinline key: ((index: Int, item) -> Any)?,
    crossinline itemContent: @Composable ScalingLazyListItemScope.(index: Int, item) -> Unit
)

This function is deprecated. Was moved to androidx.wear.compose.foundation.lazy package.

Modifier
@ExperimentalWearMaterialApi
@Composable
Modifier.placeholder(
    placeholderState: PlaceholderState,
    shape: Shape,
    color: Color
)

Draws a placeholder shape over the top of a composable and animates a wipe off effect to remove the placeholder.

Modifier
@ExperimentalWearMaterialApi
@Composable
Modifier.placeholderShimmer(
    placeholderState: PlaceholderState,
    shape: Shape,
    color: Color
)

Modifier to draw a placeholder shimmer over a component.

Modifier
Modifier.scrollAway(scrollState: ScrollState, offset: Dp)

Scroll an item vertically in/out of view based on a ScrollState.

Modifier
Modifier.scrollAway(
    scrollState: LazyListState,
    itemIndex: Int,
    offset: Dp
)

Scroll an item vertically in/out of view based on a LazyListState.

Modifier
Modifier.scrollAway(
    scrollState: ScalingLazyListState,
    itemIndex: Int,
    offset: Dp
)

Scroll an item vertically in/out of view based on a ScalingLazyListState.

Modifier
Modifier.scrollAway(
    scrollState: ScalingLazyListState,
    itemIndex: Int,
    offset: Dp
)

This function is deprecated. This overload is provided for backwards compatibility with Compose for Wear OS 1.1.A newer overload is available which uses ScalingLazyListState from wear.compose.foundation.lazy package

Modifier
@ExperimentalWearMaterialApi
<T : Any?> Modifier.swipeable(
    state: SwipeableState<T>,
    anchors: Map<Float, T>,
    orientation: Orientation,
    enabled: Boolean,
    reverseDirection: Boolean,
    interactionSource: MutableInteractionSource?,
    thresholds: (from, to) -> ThresholdConfig,
    resistance: ResistanceConfig?,
    velocityThreshold: Dp
)

Enable swipe gestures between a set of predefined states.

Top-level properties summary

ProvidableCompositionLocal<Float>

CompositionLocal containing the preferred content alpha for a given position in the hierarchy.

ProvidableCompositionLocal<Color>

CompositionLocal containing the preferred content color for a given position in the hierarchy.

ProvidableCompositionLocal<TextStyle>

CompositionLocal containing the preferred TextStyle that will be used by Text components by default.

Top-level functions

@Composable
fun AppCard(
    onClick: () -> Unit,
    appName: @Composable RowScope.() -> Unit,
    time: @Composable RowScope.() -> Unit,
    title: @Composable RowScope.() -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    appImage: (@Composable RowScope.() -> Unit)? = null,
    backgroundPainter: Painter = CardDefaults.cardBackgroundPainter(),
    contentColor: Color = MaterialTheme.colors.onSurfaceVariant,
    appColor: Color = contentColor,
    timeColor: Color = contentColor,
    titleColor: Color = MaterialTheme.colors.onSurface,
    content: @Composable ColumnScope.() -> Unit
): Unit

Opinionated Wear Material Card that offers a specific 5 slot layout to show information about an application, e.g. a notification. AppCards are designed to show interactive elements from multiple applications. They will typically be used by the system UI, e.g. for showing a list of notifications from different applications. However it could also be adapted by individual application developers to show information about different parts of their application.

The first row of the layout has three slots, 1) a small optional application Image or Icon of size CardDefaults.AppImageSizexCardDefaults.AppImageSize dp, 2) an application name (emphasised with the CardColors.appColor() color), it is expected to be a short start aligned Text composable, and 3) the time that the application activity has occurred which will be shown on the top row of the card, this is expected to be an end aligned Text composable showing a time relevant to the contents of the Card.

The second row shows a title, this is expected to be a single row of start aligned Text.

The rest of the Card contains the content which can be either Text or an Image. If the content is text it can be single or multiple line and is expected to be Top and Start aligned.

If more than one composable is provided in the content slot it is the responsibility of the caller to determine how to layout the contents, e.g. provide either a row or a column.

Example of an AppCard with icon, title, time and two lines of body text:

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.wear.compose.material.AppCard
import androidx.wear.compose.material.CardDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.Text

AppCard(
    onClick = {},
    appName = { Text("AppName") },
    appImage = {
        Icon(
            painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
            contentDescription = "airplane",
            modifier =
                Modifier.size(CardDefaults.AppImageSize)
                    .wrapContentSize(align = Alignment.Center),
        )
    },
    title = { Text("AppCard") },
    time = { Text("now") },
) {
    Text("Some body content")
    Text("and some more body content")
}

Example of an AppCard with image content:

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.AppCard
import androidx.wear.compose.material.CardDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.Text

AppCard(
    onClick = {},
    appName = { Text("App name") },
    appImage = {
        Icon(
            painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
            contentDescription = "airplane",
            modifier =
                Modifier.size(CardDefaults.AppImageSize)
                    .wrapContentSize(align = Alignment.Center),
        )
    },
    title = {
        Text(
            text = "Title with maximum two lines",
            maxLines = 2,
        )
    },
    time = { Text("now") },
) {
    Spacer(Modifier.height(6.dp))
    Image(
        modifier =
            Modifier.padding(end = 28.dp).aspectRatio(16f / 9f).clip(RoundedCornerShape(16.dp)),
        painter = painterResource(R.drawable.card_background),
        contentScale = ContentScale.Crop,
        contentDescription = null
    )
}

For more information, see the Cards guide.

Parameters
onClick: () -> Unit

Will be called when the user clicks the card

appName: @Composable RowScope.() -> Unit

A slot for displaying the application name, expected to be a single line of start aligned text of Typography.title3

time: @Composable RowScope.() -> Unit

A slot for displaying the time relevant to the contents of the card, expected to be a short piece of end aligned text.

title: @Composable RowScope.() -> Unit

A slot for displaying the title of the card, expected to be one or two lines of start aligned text of Typography.button

modifier: Modifier = Modifier

Modifier to be applied to the card

enabled: Boolean = true

Controls the enabled state of the card. When false, this card will not be clickable and there will be no ripple effect on click. Wear cards do not have any specific elevation or alpha differences when not enabled - they are simply not clickable.

appImage: (@Composable RowScope.() -> Unit)? = null

A slot for a small (CardDefaults.AppImageSizexCardDefaults.AppImageSize ) Image associated with the application.

backgroundPainter: Painter = CardDefaults.cardBackgroundPainter()

A painter used to paint the background of the card. A card will normally have a gradient background. Use CardDefaults.cardBackgroundPainter() to obtain an appropriate painter

contentColor: Color = MaterialTheme.colors.onSurfaceVariant

The default color to use for content() slot unless explicitly set.

appColor: Color = contentColor

The default color to use for appName() and appImage() slots unless explicitly set.

timeColor: Color = contentColor

The default color to use for time() slot unless explicitly set.

titleColor: Color = MaterialTheme.colors.onSurface

The default color to use for title() slot unless explicitly set.

content: @Composable ColumnScope.() -> Unit

Slot for composable body content displayed on the Card

@Composable
fun Button(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = CircleShape,
    border: ButtonBorder = ButtonDefaults.buttonBorder(),
    content: @Composable BoxScope.() -> Unit
): Unit

Wear Material Button that offers a single slot to take any content (text, icon or image).

The recommended Button sizes can be obtained from ButtonDefaults - see ButtonDefaults.DefaultButtonSize, ButtonDefaults.LargeButtonSize, ButtonDefaults.SmallButtonSize. Icon content should be of size ButtonDefaults.DefaultIconSize, ButtonDefaults.LargeIconSize or ButtonDefaults.SmallIconSize respectively.

The recommended set of ButtonColors styles can be obtained from ButtonDefaults, e.g. ButtonDefaults.primaryButtonColors to get a color scheme for a primary Button which by default will have a solid background of Colors.primary and content color of Colors.onPrimary.

Buttons can be enabled or disabled. A disabled button will not respond to click events.

Example of a Button displaying an icon:

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.wear.compose.material.Button
import androidx.wear.compose.material.ButtonDefaults
import androidx.wear.compose.material.Icon

Button(
    onClick = { /* Do something */ },
    enabled = true,
) {
    Icon(
        painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
        contentDescription = "airplane",
        modifier =
            Modifier.size(ButtonDefaults.DefaultIconSize)
                .wrapContentSize(align = Alignment.Center),
    )
}

Example of a large Button displaying an icon:

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.wear.compose.material.Button
import androidx.wear.compose.material.ButtonDefaults
import androidx.wear.compose.material.Icon

Button(
    onClick = { /* Do something */ },
    enabled = true,
    modifier = Modifier.size(ButtonDefaults.LargeButtonSize)
) {
    Icon(
        painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
        contentDescription = "airplane",
        modifier =
            Modifier.size(ButtonDefaults.LargeIconSize)
                .wrapContentSize(align = Alignment.Center),
    )
}

Example of a Button with text content and size modified to LargeButtonSize:

import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.wear.compose.material.Button
import androidx.wear.compose.material.ButtonDefaults
import androidx.wear.compose.material.Text

Button(
    onClick = { /* Do something */ },
    enabled = true,
    modifier = Modifier.size(ButtonDefaults.LargeButtonSize)
) {
    Text("Big")
}

For more information, see the Buttons guide.

Parameters
onClick: () -> Unit

Will be called when the user clicks the button.

modifier: Modifier = Modifier

Modifier to be applied to the button.

enabled: Boolean = true

Controls the enabled state of the button. When false, this button will not be clickable.

colors: ButtonColors = ButtonDefaults.primaryButtonColors()

ButtonColors that will be used to resolve the background and content color for this button in different states. See ButtonDefaults.buttonColors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this button. You can use this to change the button's appearance or preview the button in different states. Note that if null is provided, interactions will still happen internally.

shape: Shape = CircleShape

Defines the button's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme.

border: ButtonBorder = ButtonDefaults.buttonBorder()

ButtonBorder that will be used to resolve the button border in different states. See ButtonDefaults.buttonBorder.

content: @Composable BoxScope.() -> Unit

The content displayed on the Button such as text, icon or image.

@Composable
fun Card(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    backgroundPainter: Painter = CardDefaults.cardBackgroundPainter(),
    contentColor: Color = MaterialTheme.colors.onSurfaceVariant,
    enabled: Boolean = true,
    contentPadding: PaddingValues = CardDefaults.ContentPadding,
    shape: Shape = MaterialTheme.shapes.large,
    interactionSource: MutableInteractionSource? = null,
    role: Role? = null,
    content: @Composable ColumnScope.() -> Unit
): Unit

Base level Wear Material Card that offers a single slot to take any content.

Is used as the container for more opinionated Card components that take specific content such as icons, images, titles, subtitles and labels.

The Card is Rectangle shaped rounded corners by default.

Cards can be enabled or disabled. A disabled card will not respond to click events.

For more information, see the Cards Wear OS Material design guide.

Note that the Wear OS design guidance recommends a gradient or image background for Cards which is not the case for Mobile Cards. As a result you will see a backgroundPainter rather than a backgroundColor for Cards. If you want to workaround this recommendation you could use a ColorPainter to produce a solid colored background.

Parameters
onClick: () -> Unit

Will be called when the user clicks the card

modifier: Modifier = Modifier

Modifier to be applied to the card

backgroundPainter: Painter = CardDefaults.cardBackgroundPainter()

A painter used to paint the background of the card. A card will normally have a gradient background. Use CardDefaults.cardBackgroundPainter() to obtain an appropriate painter

contentColor: Color = MaterialTheme.colors.onSurfaceVariant

The default color to use for content() unless explicitly set.

enabled: Boolean = true

Controls the enabled state of the card. When false, this card will not be clickable and there will be no ripple effect on click. Wear cards do not have any specific elevation or alpha differences when not enabled - they are simply not clickable.

contentPadding: PaddingValues = CardDefaults.ContentPadding

The spacing values to apply internally between the container and the content

shape: Shape = MaterialTheme.shapes.large

Defines the card's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this card. You can use this to change the card's appearance or preview the card in different states. Note that if null is provided, interactions will still happen internally.

role: Role? = null

The type of user interface element. Accessibility services might use this to describe the element or do customizations

content: @Composable ColumnScope.() -> Unit

Slot for composable body content displayed on the Card

@Composable
fun Checkbox(
    checked: Boolean,
    modifier: Modifier = Modifier,
    colors: CheckboxColors = CheckboxDefaults.colors(),
    enabled: Boolean = true,
    onCheckedChange: ((Boolean) -> Unit)? = null,
    interactionSource: MutableInteractionSource? = null
): Unit

Checkbox provides an animated checkbox for use as a toggle control in ToggleChip or SplitToggleChip.

Example of a SplitToggleChip with Checkbox toggle control:

import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.material.Checkbox
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.SplitToggleChip
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.ToggleChip

var checked by remember { mutableStateOf(true) }
// The primary label should have a maximum 3 lines of text
// and the secondary label should have max 2 lines of text.
SplitToggleChip(
    label = { Text("Split with CheckboxIcon", maxLines = 3, overflow = TextOverflow.Ellipsis) },
    checked = checked,
    toggleControl = {
        Checkbox(
            checked = checked,
            enabled = true,
        )
    },
    onCheckedChange = { checked = it },
    onClick = {
        /* Do something */
    },
    enabled = true,
)
Parameters
checked: Boolean

Boolean flag indicating whether this checkbox is currently checked.

modifier: Modifier = Modifier

Modifier to be applied to the checkbox. This can be used to provide a content description for accessibility.

colors: CheckboxColors = CheckboxDefaults.colors()

CheckboxColors from which the box and checkmark colors will be obtained.

enabled: Boolean = true

Boolean flag indicating the enabled state of the Checkbox (affects the color).

onCheckedChange: ((Boolean) -> Unit)? = null

Callback to be invoked when Checkbox is clicked. If null, then this is passive and relies entirely on a higher-level component to control the state (such as ToggleChip or SplitToggleChip).

interactionSource: MutableInteractionSource? = null

When also providing onCheckedChange, an optional hoisted MutableInteractionSource for observing and emitting Interactions for this checkbox. You can use this to change the checkbox's appearance or preview the checkbox in different states. Note that if null is provided, interactions will still happen internally.

@Composable
fun Chip(
    onClick: () -> Unit,
    colors: ChipColors,
    border: ChipBorder,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    contentPadding: PaddingValues = ChipDefaults.ContentPadding,
    shape: Shape = MaterialTheme.shapes.large,
    interactionSource: MutableInteractionSource? = null,
    role: Role? = Role.Button,
    content: @Composable RowScope.() -> Unit
): Unit

Base level Wear Material Chip that offers a single slot to take any content.

Is used as the container for more opinionated Chip components that take specific content such as icons and labels.

The Chip is Stadium shaped and has a max height designed to take no more than two lines of text of Typography.button style. The Chip can have an icon or image horizontally parallel to the two lines of text. With localisation and/or large font sizes, the Chip height adjusts to accommodate the contents.

The Chip can have different styles with configurable content colors, background colors including gradients, these are provided by ChipColors implementations.

The recommended set of ChipColors styles can be obtained from ChipDefaults, e.g. ChipDefaults.primaryChipColors to get a color scheme for a primary Chip which by default will have a solid background of Colors.primary and content color of Colors.onPrimary.

Chips can be enabled or disabled. A disabled chip will not respond to click events.

For more information, see the Chips guide.

Parameters
onClick: () -> Unit

Will be called when the user clicks the chip

colors: ChipColors

ChipColors that will be used to resolve the background and content color for this chip in different states. See ChipDefaults.chipColors.

border: ChipBorder

ChipBorder that will be used to resolve the border for this chip in different states. See ChipDefaults.chipBorder.

modifier: Modifier = Modifier

Modifier to be applied to the chip

enabled: Boolean = true

Controls the enabled state of the chip. When false, this chip will not be clickable

contentPadding: PaddingValues = ChipDefaults.ContentPadding

The spacing values to apply internally between the container and the content

shape: Shape = MaterialTheme.shapes.large

Defines the chip's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

role: Role? = Role.Button

The type of user interface element. Accessibility services might use this to describe the element or do customizations

content: @Composable RowScope.() -> Unit

Slot for composable body content displayed on the Chip

@Composable
fun Chip(
    label: @Composable RowScope.() -> Unit,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    secondaryLabel: (@Composable RowScope.() -> Unit)? = null,
    icon: (@Composable BoxScope.() -> Unit)? = null,
    colors: ChipColors = ChipDefaults.primaryChipColors(),
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    contentPadding: PaddingValues = ChipDefaults.ContentPadding,
    shape: Shape = MaterialTheme.shapes.large,
    border: ChipBorder = ChipDefaults.chipBorder()
): Unit

Wear Material Chip that offers three slots and a specific layout for an icon, label and secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the icon, if provided, at the start of a row, with a column next containing the two label slots.

The Chip is Stadium shaped and has a max height designed to take no more than two lines of text of Typography.button style. If no secondary label is provided then the label can be two lines of text. The label and secondary label should be consistently aligned. With localisation and/or large font sizes, the Chip height adjusts to accommodate the contents.

If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that the text starts next to the icon.

The Chip can have different styles with configurable content colors, background colors including gradients, these are provided by ChipColors implementations.

The recommended set of ChipColors styles can be obtained from ChipDefaults, e.g. ChipDefaults.primaryChipColors to get a color scheme for a primary Chip which by default will have a solid background of Colors.primary and content color of Colors.onPrimary.

Chips can be enabled or disabled. A disabled chip will not respond to click events.

Example of a Chip with icon and a label only with longer text:

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.Text

Chip(
    onClick = { /* Do something */ },
    enabled = true,
    // Primary label can have up to 3 lines of text
    label = {
        Text(
            text = "Main label can span up to 3 lines",
            maxLines = 3,
            overflow = TextOverflow.Ellipsis
        )
    },
    icon = {
        Icon(
            painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
            contentDescription = "airplane",
            modifier =
                Modifier.size(ChipDefaults.IconSize).wrapContentSize(align = Alignment.Center),
        )
    }
)

Example of a Chip with icon, label and secondary label:

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.Text

Chip(
    onClick = { /* Do something */ },
    enabled = true,
    // Primary label has maximum 3 lines, Secondary label has maximum 2 lines.
    label = { Text(text = "Main label", maxLines = 3, overflow = TextOverflow.Ellipsis) },
    secondaryLabel = {
        Text(text = "secondary label", maxLines = 2, overflow = TextOverflow.Ellipsis)
    },
    icon = {
        Icon(
            painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
            contentDescription = "airplane",
            modifier =
                Modifier.size(ChipDefaults.IconSize).wrapContentSize(align = Alignment.Center),
        )
    }
)

For more information, see the Chips guide.

Parameters
label: @Composable RowScope.() -> Unit

A slot for providing the chip's main label. The contents are expected to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.

onClick: () -> Unit

Will be called when the user clicks the chip

modifier: Modifier = Modifier

Modifier to be applied to the chip

secondaryLabel: (@Composable RowScope.() -> Unit)? = null

A slot for providing the chip's secondary label. The contents are expected to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned if not. label and secondaryLabel contents should be consistently aligned.

icon: (@Composable BoxScope.() -> Unit)? = null

A slot for providing the chip's icon. The contents are expected to be a horizontally and vertically aligned icon of size ChipDefaults.IconSize or ChipDefaults.LargeIconSize. In order to correctly render when the Chip is not enabled the icon must set its alpha value to LocalContentAlpha.

colors: ChipColors = ChipDefaults.primaryChipColors()

ChipColors that will be used to resolve the background and content color for this chip in different states. See ChipDefaults.chipColors. Defaults to ChipDefaults.primaryChipColors

enabled: Boolean = true

Controls the enabled state of the chip. When false, this chip will not be clickable

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

contentPadding: PaddingValues = ChipDefaults.ContentPadding

The spacing values to apply internally between the container and the content

shape: Shape = MaterialTheme.shapes.large

Defines the chip's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme

border: ChipBorder = ChipDefaults.chipBorder()

ChipBorder that will be used to resolve the chip border in different states. See ChipDefaults.chipBorder.

CircularProgressIndicator

@Composable
fun CircularProgressIndicator(
    modifier: Modifier = Modifier,
    startAngle: Float = 270.0f,
    indicatorColor: Color = MaterialTheme.colors.onBackground,
    trackColor: Color = MaterialTheme.colors.onBackground.copy(alpha = 0.3f),
    strokeWidth: Dp = IndeterminateStrokeWidth
): Unit

Indeterminate Material Design circular progress indicator.

Indeterminate progress indicator expresses an unspecified wait time and spins indefinitely.

Progress Indicator doc Progress indicator image

Example of indeterminate progress indicator:

import androidx.wear.compose.material.CircularProgressIndicator

CircularProgressIndicator()
Parameters
modifier: Modifier = Modifier

Modifier to be applied to the CircularProgressIndicator

startAngle: Float = 270.0f

The starting position of the progress arc, measured clockwise in degrees (0 to 360) from the 3 o'clock position. For example, 0 and 360 represent 3 o'clock, 90 and 180 represent 6 o'clock and 9 o'clock respectively. Default is 270 degrees (top of the screen)

indicatorColor: Color = MaterialTheme.colors.onBackground

The color of the progress indicator bar.

trackColor: Color = MaterialTheme.colors.onBackground.copy(alpha = 0.3f)

The color of the background progress track

strokeWidth: Dp = IndeterminateStrokeWidth

The stroke width for the progress indicator.

CircularProgressIndicator

@Composable
fun CircularProgressIndicator(
    progress: @FloatRange(from = 0.0, to = 1.0) Float,
    modifier: Modifier = Modifier,
    startAngle: Float = 270.0f,
    endAngle: Float = startAngle,
    indicatorColor: Color = MaterialTheme.colors.primary,
    trackColor: Color = MaterialTheme.colors.onBackground.copy(alpha = 0.1f),
    strokeWidth: Dp = ProgressIndicatorDefaults.StrokeWidth
): Unit

Determinate Material Design circular progress indicator.

Progress indicators express the proportion of completion of an ongoing task.

Progress Indicator doc Progress indicator image

There is no animation between progress values by default, but progress can be animated with the recommended ProgressIndicatorDefaults.ProgressAnimationSpec, as in the following example:

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.CircularProgressIndicator
import androidx.wear.compose.material.CompactChip
import androidx.wear.compose.material.ProgressIndicatorDefaults
import androidx.wear.compose.material.Text

var progress by remember { mutableStateOf(0.1f) }
val animatedProgress by
    animateFloatAsState(
        targetValue = progress,
        animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec
    )

Column(horizontalAlignment = Alignment.CenterHorizontally) {
    CircularProgressIndicator(
        progress = animatedProgress,
    )
    Spacer(Modifier.requiredHeight(10.dp))
    CompactChip(
        modifier = Modifier.width(90.dp),
        onClick = { if (progress < 1f) progress += 0.1f },
        label = { Text("Increase") }
    )
}

CircularProgressIndicator supports a gap in the circular track between endAngle and startAngle, which leaves room for other content, such as TimeText at the top of the screen. This sample also shows how to disable accessibility semantics for the fullscreen CircularProgressIndicator:

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.CircularProgressIndicator
import androidx.wear.compose.material.ProgressIndicatorDefaults

CircularProgressIndicator(
    modifier = Modifier.fillMaxSize().padding(all = 1.dp).clearAndSetSemantics {},
    startAngle = 295.5f,
    endAngle = 245.5f,
    progress = 0.3f,
    strokeWidth = ProgressIndicatorDefaults.FullScreenStrokeWidth
)
Parameters
progress: @FloatRange(from = 0.0, to = 1.0) Float

The progress of this progress indicator where 0.0 represents no progress and 1.0 represents completion. Values outside of this range are coerced into the range 0..1.

modifier: Modifier = Modifier

Modifier to be applied to the CircularProgressIndicator

startAngle: Float = 270.0f

The starting position of the progress arc, measured clockwise in degrees (0 to 360) from the 3 o'clock position. For example, 0 and 360 represent 3 o'clock, 90 and 180 represent 6 o'clock and 9 o'clock respectively. Default is 270 degrees (top of the screen)

endAngle: Float = startAngle

The ending position of the progress arc, measured clockwise in degrees (0 to 360) from the 3 o'clock position. For example, 0 and 360 represent 3 o'clock, 90 and 180 represent 6 o'clock and 9 o'clock respectively. By default equal to startAngle

indicatorColor: Color = MaterialTheme.colors.primary

The color of the progress indicator bar.

trackColor: Color = MaterialTheme.colors.onBackground.copy(alpha = 0.1f)

The color of the background progress track.

strokeWidth: Dp = ProgressIndicatorDefaults.StrokeWidth

The stroke width for the progress indicator.

@Composable
fun CompactButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
    backgroundPadding: Dp = ButtonDefaults.CompactButtonBackgroundPadding,
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = CircleShape,
    border: ButtonBorder = ButtonDefaults.buttonBorder(),
    content: @Composable BoxScope.() -> Unit
): Unit

Wear Material CompactButton that offers a single slot to take any content (text, icon or image).

The CompactButton has background size ButtonDefaults.ExtraSmallButtonSize. There is an optional transparent padding around the background, defaulted to ButtonDefaults.CompactButtonBackgroundPadding, which increases the clickable area. Icon content should have size ButtonDefaults.SmallIconSize.

The recommended set of ButtonColors styles can be obtained from ButtonDefaults, e.g. ButtonDefaults.primaryButtonColors to get a color scheme for a primary Button which by default will have a solid background of Colors.primary and content color of Colors.onPrimary.

CompactButtons can be enabled or disabled. A disabled button will not respond to click events.

Example usage:

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.wear.compose.material.Button
import androidx.wear.compose.material.ButtonDefaults
import androidx.wear.compose.material.CompactButton
import androidx.wear.compose.material.Icon

CompactButton(
    onClick = { /* Do something */ },
    enabled = true,
) {
    Icon(
        painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
        contentDescription = "airplane",
        modifier =
            Modifier.size(ButtonDefaults.SmallIconSize)
                .wrapContentSize(align = Alignment.Center),
    )
}

For more information, see the Buttons guide.

Parameters
onClick: () -> Unit

Will be called when the user clicks the button.

modifier: Modifier = Modifier

Modifier to be applied to the button.

enabled: Boolean = true

Controls the enabled state of the button. When false, this button will not be clickable.

colors: ButtonColors = ButtonDefaults.primaryButtonColors()

ButtonColors that will be used to resolve the background and content color for this button in different states. See ButtonDefaults.buttonColors.

backgroundPadding: Dp = ButtonDefaults.CompactButtonBackgroundPadding

Increases the transparent clickable area around the background, defaults to ButtonDefaults.CompactButtonBackgroundPadding

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this button. You can use this to change the button's appearance or preview the button in different states. Note that if null is provided, interactions will still happen internally.

shape: Shape = CircleShape

Defines the button's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme.

border: ButtonBorder = ButtonDefaults.buttonBorder()

ButtonBorder that will be used to resolve the button border in different states. See ButtonDefaults.outlinedButtonBorder.

content: @Composable BoxScope.() -> Unit

The content displayed on the CompactButton such as text, icon or image.

@Composable
fun CompactChip(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    label: (@Composable RowScope.() -> Unit)? = null,
    icon: (@Composable BoxScope.() -> Unit)? = null,
    colors: ChipColors = ChipDefaults.primaryChipColors(),
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    contentPadding: PaddingValues = ChipDefaults.CompactChipContentPadding,
    shape: Shape = MaterialTheme.shapes.large,
    border: ChipBorder = ChipDefaults.chipBorder()
): Unit

A compact Wear Material Chip that offers two slots and a specific layout for an icon and label. Both the icon and label are optional however it is expected that at least one will be provided.

The CompactChip is Stadium shaped and has a max height designed to take no more than one line of text of Typography.caption1 style and/or one icon. The default max height is ChipDefaults.CompactChipHeight. This includes a visible chip height of 32.dp and 8.dp of padding above and below the chip in order to meet accessibility guidelines that request a minimum of 48.dp height and width of tappable area.

If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that the text starts next to the icon.

The items are laid out as follows.

  1. If a label is provided then the chip will be laid out with the optional icon at the start of a row followed by the label with a default max height of ChipDefaults.CompactChipHeight.

  2. If only an icon is provided it will be laid out vertically and horizontally centered with a default height of ChipDefaults.CompactChipHeight and the default width of ChipDefaults.IconOnlyCompactChipWidth

If neither icon nor label is provided then the chip will displayed like an icon only chip but with no contents and ChipColors.background() color.

The CompactChip can have different styles with configurable content colors, background colors including gradients, these are provided by ChipColors implementations.

The recommended set of ChipColors styles can be obtained from ChipDefaults, e.g. ChipDefaults.primaryChipColors to get a color scheme for a primary Chip which by default will have a solid background of Colors.primary and content color of Colors.onPrimary.

Chips can be enabled or disabled. A disabled chip will not respond to click events.

Example of a CompactChip with icon and single line of label text:

import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.CompactChip
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.Text

CompactChip(
    onClick = { /* Do something */ },
    enabled = true,
    // CompactChip label should be no more than 1 line of text
    label = { Text("Single line label", maxLines = 1, overflow = TextOverflow.Ellipsis) },
    icon = {
        Icon(
            painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
            contentDescription = "airplane",
            modifier = Modifier.size(ChipDefaults.SmallIconSize),
        )
    },
)

Example of a CompactChip with a label, note that the text is center aligned:

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.CompactChip
import androidx.wear.compose.material.Text

CompactChip(
    onClick = { /* Do something */ },
    enabled = true,
    // CompactChip label should be no more than 1 line of text
    label = {
        Text(
            text = "Single line label",
            maxLines = 1,
            overflow = TextOverflow.Ellipsis,
            textAlign = TextAlign.Center,
            modifier = Modifier.fillMaxWidth()
        )
    },
)

Example of a CompactChip with an icon only, note that the recommended icon size is 24x24 when only an icon is displayed:

import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.CompactChip
import androidx.wear.compose.material.Icon

CompactChip(
    onClick = { /* Do something */ },
    enabled = true,
    icon = {
        Icon(
            painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
            contentDescription = "airplane",
            modifier = Modifier.size(ChipDefaults.IconSize)
        )
    },
)

For more information, see the Chips guide.

Parameters
onClick: () -> Unit

Will be called when the user clicks the chip

modifier: Modifier = Modifier

Modifier to be applied to the chip

label: (@Composable RowScope.() -> Unit)? = null

A slot for providing the chip's main label. The contents are expected to be text which is "start" aligned if there is an icon preset and "center" aligned if not.

icon: (@Composable BoxScope.() -> Unit)? = null

A slot for providing the chip's icon. The contents are expected to be a horizontally and vertically aligned icon of size ChipDefaults.SmallIconSize when used with a label or ChipDefaults.IconSize when used as the only content in the CompactChip. In order to correctly render when the Chip is not enabled the icon must set its alpha value to LocalContentAlpha.

colors: ChipColors = ChipDefaults.primaryChipColors()

ChipColors that will be used to resolve the background and content color for this chip in different states. See ChipDefaults.chipColors. Defaults to ChipDefaults.primaryChipColors

enabled: Boolean = true

Controls the enabled state of the chip. When false, this chip will not be clickable

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

contentPadding: PaddingValues = ChipDefaults.CompactChipContentPadding

The spacing values to apply internally between the container and the content

shape: Shape = MaterialTheme.shapes.large

Defines the chip's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme

border: ChipBorder = ChipDefaults.chipBorder()

ChipBorder that will be used to resolve the border for this chip in different states. See ChipDefaults.chipBorder.

HorizontalPageIndicator

@Composable
fun HorizontalPageIndicator(
    pageIndicatorState: PageIndicatorState,
    modifier: Modifier = Modifier,
    indicatorStyle: PageIndicatorStyle = PageIndicatorDefaults.style(),
    selectedColor: Color = MaterialTheme.colors.onBackground,
    unselectedColor: Color = selectedColor.copy(alpha = 0.3f),
    indicatorSize: Dp = 6.dp,
    spacing: Dp = 4.dp,
    indicatorShape: Shape = CircleShape
): Unit

A horizontal indicator for a Pager, representing the currently active page and total pages drawn using a Shape. It shows up to 6 pages on the screen and doesn't represent the exact page index if there are more than 6 pages. Instead of showing the exact position, HorizontalPageIndicator shows a half-size indicator on the left or on the right if there are more pages.

Here's how different positions 0..10 might be visually represented: "X" is selected item, "O" and "o" full and half size items respectively.

O X O O O o - 2nd position out of 10. There are no more items on the left but more on the right o O O O X o - might be 6, 7 or 8 out of 10, as there are more possible items on the left and on the right o O O O X O - is 9 out of 10, as there're no more items on the right

HorizontalPageIndicator may be linear or curved, depending on indicatorStyle. By default it depends on the screen shape of the device - for circular screens it will be curved, whilst for square screens it will be linear.

This component also allows customising the indicatorShape, which defines how the indicator is visually represented.

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.HorizontalPageIndicator
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.InlineSlider
import androidx.wear.compose.material.InlineSliderDefaults
import androidx.wear.compose.material.PageIndicatorState

val maxPages = 9
var selectedPage by remember { mutableStateOf(0) }
var finalValue by remember { mutableStateOf(0) }

val animatedSelectedPage by
    animateFloatAsState(
        targetValue = selectedPage.toFloat(),
    ) {
        finalValue = it.toInt()
    }

val pageIndicatorState: PageIndicatorState = remember {
    object : PageIndicatorState {
        override val pageOffset: Float
            get() = animatedSelectedPage - finalValue

        override val selectedPage: Int
            get() = finalValue

        override val pageCount: Int
            get() = maxPages
    }
}

Box(modifier = Modifier.fillMaxSize().padding(6.dp)) {
    InlineSlider(
        modifier = Modifier.align(Alignment.Center),
        value = selectedPage,
        increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
        decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
        valueProgression = 0 until maxPages,
        onValueChange = { selectedPage = it }
    )
    HorizontalPageIndicator(pageIndicatorState = pageIndicatorState)
}
Parameters
pageIndicatorState: PageIndicatorState

The state object of a HorizontalPageIndicator to be used to observe the Pager's state.

modifier: Modifier = Modifier

Modifier to be applied to the HorizontalPageIndicator

indicatorStyle: PageIndicatorStyle = PageIndicatorDefaults.style()

The style of HorizontalPageIndicator - may be linear or curved. By default determined by the screen shape.

selectedColor: Color = MaterialTheme.colors.onBackground

The color of the selected HorizontalPageIndicator item

unselectedColor: Color = selectedColor.copy(alpha = 0.3f)

The color of unselected HorizontalPageIndicator items. Defaults to selectedColor with 30% alpha

indicatorSize: Dp = 6.dp

The size of each HorizontalPageIndicator item in Dp

spacing: Dp = 4.dp

The spacing between indicator items in Dp

indicatorShape: Shape = CircleShape

The shape of each HorizontalPageIndicator item. Defaults to CircleShape

@Composable
fun Icon(
    bitmap: ImageBitmap,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
): Unit

Icon component that draws bitmap using tint, defaulting to LocalContentColor. For a clickable icon, see Chip.

Parameters
bitmap: ImageBitmap

ImageBitmap to draw inside this Icon

contentDescription: String?

Text used by accessibility services to describe what this icon represents. This should always be provided unless this icon is used for decorative purposes, and does not represent a meaningful action that a user can take. This text should be localized, such as by using androidx.compose.ui.res.stringResource or similar

modifier: Modifier = Modifier

Optional Modifier for this Icon

tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)

Tint to be applied to bitmap. If Color.Unspecified is provided, then no tint is applied

@Composable
fun Icon(
    imageVector: ImageVector,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
): Unit

Icon component that draws imageVector using tint, defaulting to LocalContentColor. For a clickable icon, see Chip.

Parameters
imageVector: ImageVector

ImageVector to draw inside this Icon

contentDescription: String?

Text used by accessibility services to describe what this icon represents. This should always be provided unless this icon is used for decorative purposes, and does not represent a meaningful action that a user can take. This text should be localized, such as by using androidx.compose.ui.res.stringResource or similar

modifier: Modifier = Modifier

Optional Modifier for this Icon

tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)

Tint to be applied to imageVector. If Color.Unspecified is provided, then no tint is applied

@Composable
fun Icon(
    painter: Painter,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
): Unit

Icon component that draws a painter using tint, defaulting to LocalContentColor. For a clickable icon, see Chip.

Parameters
painter: Painter

Painter to draw inside this Icon

contentDescription: String?

Text used by accessibility services to describe what this icon represents. This should always be provided unless this icon is used for decorative purposes, and does not represent a meaningful action that a user can take. This text should be localized, such as by using androidx.compose.ui.res.stringResource or similar

modifier: Modifier = Modifier

Optional Modifier for this Icon

tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current)

Tint to be applied to painter. If Color.Unspecified is provided, then no tint is applied

InlineSlider

@Composable
fun InlineSlider(
    value: Int,
    onValueChange: (Int) -> Unit,
    valueProgression: IntProgression,
    decreaseIcon: @Composable () -> Unit,
    increaseIcon: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    segmented: Boolean = valueProgression.stepsNumber() <= 8,
    colors: InlineSliderColors = InlineSliderDefaults.colors()
): Unit

InlineSlider allows users to make a selection from a range of values. The range of selections is shown as a bar between the minimum and maximum values of the range, from which users may select a single value. InlineSlider is ideal for adjusting settings such as volume or brightness.

Value can be increased and decreased by clicking on the increase and decrease buttons, located accordingly to the start and end of the control. Buttons can have custom icons - decreaseIcon and increaseIcon.

The bar in the middle of control can have separators if segmented flag is set to true. A number of steps is calculated as the difference between max and min values of valueProgression divided by valueProgression.step - 1. For example, with a range of 100..120 and a step 5, number of steps will be (120-100)/ 5 - 1 = 3. Steps are 100(first), 105, 110, 115, 120(last)

If valueProgression range is not equally divisible by valueProgression.step, then valueProgression.last will be adjusted to the closest divisible value in the range. For example, 1..13 range and a step = 5, steps will be 1(first) , 6 , 11(last)

A continuous non-segmented slider sample:

import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.InlineSlider
import androidx.wear.compose.material.InlineSliderDefaults

var value by remember { mutableStateOf(4) }
InlineSlider(
    value = value,
    onValueChange = { value = it },
    increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
    decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
    valueProgression = 0..10,
    segmented = false
)

A segmented slider sample:

import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.InlineSlider
import androidx.wear.compose.material.InlineSliderDefaults

var value by remember { mutableStateOf(2f) }
InlineSlider(
    value = value,
    onValueChange = { value = it },
    increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
    decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
    valueRange = 1f..4f,
    steps = 7,
    segmented = true
)
Parameters
value: Int

Current value of the Slider. If outside of valueProgression provided, value will be coerced to this range.

onValueChange: (Int) -> Unit

Lambda in which value should be updated

valueProgression: IntProgression

Progression of values that Slider value can take. Consists of rangeStart, rangeEnd and step. Range will be equally divided by step size

decreaseIcon: @Composable () -> Unit

A slot for an icon which is placed on the decrease (start) button

increaseIcon: @Composable () -> Unit

A slot for an icon which is placed on the increase (end) button

modifier: Modifier = Modifier

Modifiers for the Slider layout

enabled: Boolean = true

Controls the enabled state of the slider. When false, this slider will not be clickable

segmented: Boolean = valueProgression.stepsNumber() <= 8

A boolean value which specifies whether a bar will be split into segments or not. Recommendation is while using this flag do not have more than 8 steps as it might affect user experience. By default true if number of steps is <=8.

colors: InlineSliderColors = InlineSliderDefaults.colors()

InlineSliderColors that will be used to resolve the background and content color for this slider in different states

InlineSlider

@Composable
fun InlineSlider(
    value: Float,
    onValueChange: (Float) -> Unit,
    steps: Int,
    decreaseIcon: @Composable () -> Unit,
    increaseIcon: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    valueRange: ClosedFloatingPointRange<Float> = 0f..(steps + 1).toFloat(),
    segmented: Boolean = steps <= 8,
    colors: InlineSliderColors = InlineSliderDefaults.colors()
): Unit

InlineSlider allows users to make a selection from a range of values. The range of selections is shown as a bar between the minimum and maximum values of the range, from which users may select a single value. InlineSlider is ideal for adjusting settings such as volume or brightness.

Value can be increased and decreased by clicking on the increase and decrease buttons, located accordingly to the start and end of the control. Buttons can have custom icons - decreaseIcon and increaseIcon.

The bar in the middle of control can have separators if segmented flag is set to true. A single step value is calculated as the difference between min and max values of valueRange divided by steps + 1 value.

A continuous non-segmented slider sample:

import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.InlineSlider
import androidx.wear.compose.material.InlineSliderDefaults

var value by remember { mutableStateOf(4.5f) }
InlineSlider(
    value = value,
    onValueChange = { value = it },
    increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
    decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
    valueRange = 3f..6f,
    steps = 5,
    segmented = false
)

A segmented slider sample:

import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.InlineSlider
import androidx.wear.compose.material.InlineSliderDefaults

var value by remember { mutableStateOf(2f) }
InlineSlider(
    value = value,
    onValueChange = { value = it },
    increaseIcon = { Icon(InlineSliderDefaults.Increase, "Increase") },
    decreaseIcon = { Icon(InlineSliderDefaults.Decrease, "Decrease") },
    valueRange = 1f..4f,
    steps = 7,
    segmented = true
)
Parameters
value: Float

Current value of the Slider. If outside of valueRange provided, value will be coerced to this range.

onValueChange: (Float) -> Unit

Lambda in which value should be updated

steps: Int

Specifies the number of discrete values, excluding min and max values, evenly distributed across the whole value range. Must not be negative. If 0, slider will have only min and max values and no steps in between

decreaseIcon: @Composable () -> Unit

A slot for an icon which is placed on the decrease (start) button

increaseIcon: @Composable () -> Unit

A slot for an icon which is placed on the increase (end) button

modifier: Modifier = Modifier

Modifiers for the Slider layout

enabled: Boolean = true

Controls the enabled state of the slider. When false, this slider will not be clickable

valueRange: ClosedFloatingPointRange<Float> = 0f..(steps + 1).toFloat()

Range of values that Slider value can take. Passed value will be coerced to this range

segmented: Boolean = steps <= 8

A boolean value which specifies whether a bar will be split into segments or not. Recommendation is while using this flag do not have more than 8 steps as it might affect user experience. By default true if number of steps is <=8.

colors: InlineSliderColors = InlineSliderDefaults.colors()

InlineSliderColors that will be used to resolve the background and content color for this slider in different states

@Composable
fun ListHeader(
    modifier: Modifier = Modifier,
    backgroundColor: Color = Color.Transparent,
    contentColor: Color = MaterialTheme.colors.onSurfaceVariant,
    content: @Composable RowScope.() -> Unit
): Unit

A slot based composable for creating a list header item. List header items are typically expected to be text. The contents provided will have text and colors effects applied based on the MaterialTheme. The contents will be start and end padded and should cover up to 3 lines of text.

Example usage:

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.ui.Modifier
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.ListHeader
import androidx.wear.compose.material.Text

ScalingLazyColumn(
    modifier = Modifier.fillMaxWidth(),
) {
    item { ListHeader { Text("Header1") } }
    items(5) {
        Chip(
            onClick = {},
            label = { Text("List item $it") },
            colors = ChipDefaults.secondaryChipColors()
        )
    }
    item { ListHeader { Text("Header2") } }
    items(5) {
        Chip(
            onClick = {},
            label = { Text("List item ${it + 5}") },
            colors = ChipDefaults.secondaryChipColors()
        )
    }
}
Parameters
modifier: Modifier = Modifier

The modifier for the list header

backgroundColor: Color = Color.Transparent

The background color to apply - typically Color.Transparent

contentColor: Color = MaterialTheme.colors.onSurfaceVariant

The color to apply to content

content: @Composable RowScope.() -> Unit

Slot for displayed header text

MaterialTheme

@Composable
fun MaterialTheme(
    colors: Colors = MaterialTheme.colors,
    typography: Typography = MaterialTheme.typography,
    shapes: Shapes = MaterialTheme.shapes,
    content: @Composable () -> Unit
): Unit

MaterialTheme defines the styling principles from the WearOS Material design specification which extends the Material design specification.

Wear Material components from package/sub-packages in androidx.wear.compose.material use values provided here when retrieving default values.

It defines colors as specified in the Wear Material Color theme spec, typography defined in the Wear Material Type Scale spec, and shapes defined in the Wear Shape scheme.

All values may be set by providing this component with the colors, typography, and shapes attributes. Use this to configure the overall theme of elements within this MaterialTheme.

Any values that are not set will inherit the current value from the theme, falling back to the defaults if there is no parent MaterialTheme. This allows using a MaterialTheme at the top of your application, and then separate MaterialTheme(s) for different screens / parts of your UI, overriding only the parts of the theme definition that need to change.

For more information, see the Theming guide.

Parameters
colors: Colors = MaterialTheme.colors

A complete definition of the Wear Material Color theme for this hierarchy

typography: Typography = MaterialTheme.typography

A set of text styles to be used as this hierarchy's typography system

shapes: Shapes = MaterialTheme.shapes

A set of shapes to be used by the components in this hierarchy

content: @Composable () -> Unit

Slot for composable content displayed with this theme

OutlinedButton

@Composable
fun OutlinedButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: ButtonColors = ButtonDefaults.outlinedButtonColors(),
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = CircleShape,
    border: ButtonBorder = ButtonDefaults.outlinedButtonBorder(),
    content: @Composable BoxScope.() -> Unit
): Unit

Wear Material OutlinedButton that offers a single slot to take any content (text, icon or image).

The recommended Button sizes can be obtained from ButtonDefaults - see ButtonDefaults.DefaultButtonSize, ButtonDefaults.LargeButtonSize, ButtonDefaults.SmallButtonSize. Icon content should be of size ButtonDefaults.DefaultIconSize, ButtonDefaults.LargeIconSize or ButtonDefaults.SmallIconSize respectively.

Buttons can be enabled or disabled. A disabled button will not respond to click events.

An OutlinedButton has a transparent background and a thin border by default with content taking the theme primary color.

Example of a OutlinedButton displaying an icon:

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.wear.compose.material.Button
import androidx.wear.compose.material.ButtonDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.OutlinedButton

OutlinedButton(
    onClick = { /* Do something */ },
    enabled = true,
) {
    Icon(
        painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
        contentDescription = "airplane",
        modifier =
            Modifier.size(ButtonDefaults.DefaultIconSize)
                .wrapContentSize(align = Alignment.Center),
    )
}

For more information, see the Buttons guide.

Parameters
onClick: () -> Unit

Will be called when the user clicks the button.

modifier: Modifier = Modifier

Modifier to be applied to the button.

enabled: Boolean = true

Controls the enabled state of the button. When false, this button will not be clickable.

colors: ButtonColors = ButtonDefaults.outlinedButtonColors()

ButtonColors that will be used to resolve the background and content color for this button in different states. See ButtonDefaults.outlinedButtonColors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this button. You can use this to change the button's appearance or preview the button in different states. Note that if null is provided, interactions will still happen internally.

shape: Shape = CircleShape

Defines the button's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme.

border: ButtonBorder = ButtonDefaults.outlinedButtonBorder()

ButtonBorder that will be used to resolve the button border in different states. See ButtonDefaults.outlinedButtonBorder.

content: @Composable BoxScope.() -> Unit

The content displayed on the OutlinedButton such as text, icon or image.

OutlinedChip

@Composable
fun OutlinedChip(
    label: @Composable RowScope.() -> Unit,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    secondaryLabel: (@Composable RowScope.() -> Unit)? = null,
    icon: (@Composable BoxScope.() -> Unit)? = null,
    colors: ChipColors = ChipDefaults.outlinedChipColors(),
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    contentPadding: PaddingValues = ChipDefaults.ContentPadding,
    shape: Shape = MaterialTheme.shapes.large,
    border: ChipBorder = ChipDefaults.outlinedChipBorder()
): Unit

Wear Material OutlinedChip that offers three slots and a specific layout for an icon, label and secondaryLabel. The icon and secondaryLabel are optional. The items are laid out with the icon, if provided, at the start of a row, with a column next containing the two label slots.

The OutlinedChip is Stadium shaped and has a max height designed to take no more than two lines of text of Typography.button style. If no secondary label is provided then the label can be two lines of text. The label and secondary label should be consistently aligned. With localisation and/or large font sizes, the OutlinedChip height adjusts to accommodate the contents.

If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that the text starts next to the icon.

the OutlinedChip has a transparent background, a thin border and contents which are colored with the theme primary color. Colors can be obtained and customized using ChipDefaults.outlinedChipColors().

Chips can be enabled or disabled. A disabled chip will not respond to click events.

Example of a OutlinedChip with icon and a label only with longer text:

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.OutlinedChip
import androidx.wear.compose.material.Text

OutlinedChip(
    onClick = { /* Do something */ },
    enabled = true,
    // Primary label can have up to 3 lines of text
    label = {
        Text(
            text = "Main label can span up to 3 lines",
            maxLines = 3,
            overflow = TextOverflow.Ellipsis
        )
    },
    icon = {
        Icon(
            painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
            contentDescription = "airplane",
            modifier =
                Modifier.size(ChipDefaults.IconSize).wrapContentSize(align = Alignment.Center),
        )
    }
)

For more information, see the Chips guide.

Parameters
label: @Composable RowScope.() -> Unit

A slot for providing the chip's main label. The contents are expected to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned if not.

onClick: () -> Unit

Will be called when the user clicks the chip

modifier: Modifier = Modifier

Modifier to be applied to the chip

secondaryLabel: (@Composable RowScope.() -> Unit)? = null

A slot for providing the chip's secondary label. The contents are expected to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned if not. label and secondaryLabel contents should be consistently aligned.

icon: (@Composable BoxScope.() -> Unit)? = null

A slot for providing the chip's icon. The contents are expected to be a horizontally and vertically aligned icon of size ChipDefaults.IconSize or ChipDefaults.LargeIconSize. In order to correctly render when the Chip is not enabled the icon must set its alpha value to LocalContentAlpha.

colors: ChipColors = ChipDefaults.outlinedChipColors()

ChipColors that will be used to resolve the background and content color for this chip in different states.

enabled: Boolean = true

Controls the enabled state of the chip. When false, this chip will not be clickable

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

contentPadding: PaddingValues = ChipDefaults.ContentPadding

The spacing values to apply internally between the container and the content

shape: Shape = MaterialTheme.shapes.large

Defines the chip's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme

border: ChipBorder = ChipDefaults.outlinedChipBorder()

ChipBorder that will be used to resolve the chip border in different states.

OutlinedCompactButton

@Composable
fun OutlinedCompactButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: ButtonColors = ButtonDefaults.outlinedButtonColors(),
    backgroundPadding: Dp = ButtonDefaults.CompactButtonBackgroundPadding,
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = CircleShape,
    border: ButtonBorder = ButtonDefaults.outlinedButtonBorder(),
    content: @Composable BoxScope.() -> Unit
): Unit

Wear Material OutlinedCompactButton that offers a single slot to take any content (text, icon or image).

The OutlinedCompactButton has background size ButtonDefaults.ExtraSmallButtonSize. There is an transparent padding around the background, defaulted to ButtonDefaults.CompactButtonBackgroundPadding, which increases the clickable area. Icon content should have size ButtonDefaults.SmallIconSize.

An OutlinedCompactButton has a transparent background and a thin border by default with content taking the theme primary color.

OutlinedCompactButtons can be enabled or disabled. A disabled button will not respond to click events.

Example usage:

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.wear.compose.material.Button
import androidx.wear.compose.material.ButtonDefaults
import androidx.wear.compose.material.CompactButton
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.OutlinedCompactButton

OutlinedCompactButton(
    onClick = { /* Do something */ },
    enabled = true,
) {
    Icon(
        painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
        contentDescription = "airplane",
        modifier =
            Modifier.size(ButtonDefaults.SmallIconSize)
                .wrapContentSize(align = Alignment.Center),
    )
}

For more information, see the Buttons guide.

Parameters
onClick: () -> Unit

Will be called when the user clicks the button.

modifier: Modifier = Modifier

Modifier to be applied to the button.

enabled: Boolean = true

Controls the enabled state of the button. When false, this button will not be clickable.

colors: ButtonColors = ButtonDefaults.outlinedButtonColors()

ButtonColors that will be used to resolve the background and content color for this button in different states. See ButtonDefaults.outlinedButtonColors.

backgroundPadding: Dp = ButtonDefaults.CompactButtonBackgroundPadding

Increases the transparent clickable area around the background, defaults to ButtonDefaults.CompactButtonBackgroundPadding

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this button. You can use this to change the button's appearance or preview the button in different states. Note that if null is provided, interactions will still happen internally.

shape: Shape = CircleShape

Defines the button's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme.

border: ButtonBorder = ButtonDefaults.outlinedButtonBorder()

ButtonBorder that will be used to resolve the button border in different states. See ButtonDefaults.outlinedButtonBorder.

content: @Composable BoxScope.() -> Unit

The content displayed on the OutlinedCompactButton such as text, icon or image.

OutlinedCompactChip

@Composable
fun OutlinedCompactChip(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    label: (@Composable RowScope.() -> Unit)? = null,
    icon: (@Composable BoxScope.() -> Unit)? = null,
    colors: ChipColors = ChipDefaults.outlinedChipColors(),
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    contentPadding: PaddingValues = ChipDefaults.CompactChipContentPadding,
    shape: Shape = MaterialTheme.shapes.large,
    border: ChipBorder = ChipDefaults.outlinedChipBorder()
): Unit

A compact Outlined Wear Material Chip that offers two slots and a specific layout for an icon and label. Both the icon and label are optional however it is expected that at least one will be provided.

The CompactChip is Stadium shaped and has a max height designed to take no more than one line of text of Typography.caption1 style and/or one icon. The default max height is ChipDefaults.CompactChipHeight. This includes a visible chip height of 32.dp and 8.dp of padding above and below the chip in order to meet accessibility guidelines that request a minimum of 48.dp height and width of tappable area.

If a icon is provided then the labels should be "start" aligned, e.g. left aligned in ltr so that the text starts next to the icon.

The items are laid out as follows.

  1. If a label is provided then the chip will be laid out with the optional icon at the start of a row followed by the label with a default max height of ChipDefaults.CompactChipHeight.

  2. If only an icon is provided it will be laid out vertically and horizontally centered with a default height of ChipDefaults.CompactChipHeight and the default width of ChipDefaults.IconOnlyCompactChipWidth

If neither icon nor label is provided then the chip will displayed like an icon only chip but with no contents and ChipColors.background() color.

the OutlinedCompactChip has a transparent background, a thin border and contents which are colored with the theme primary color. Colors can be obtained and customized using ChipDefaults.outlinedChipColors().

Chips can be enabled or disabled. A disabled chip will not respond to click events.

Example of a OutlinedCompactChip with icon and single line of label text:

import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.CompactChip
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.OutlinedCompactChip
import androidx.wear.compose.material.Text

OutlinedCompactChip(
    onClick = { /* Do something */ },
    enabled = true,
    // CompactChip label should be no more than 1 line of text
    label = { Text("Single line label", maxLines = 1, overflow = TextOverflow.Ellipsis) },
    icon = {
        Icon(
            painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
            contentDescription = "airplane",
            modifier = Modifier.size(ChipDefaults.SmallIconSize),
        )
    },
)

For more information, see the Chips guide.

Parameters
onClick: () -> Unit

Will be called when the user clicks the chip

modifier: Modifier = Modifier

Modifier to be applied to the chip

label: (@Composable RowScope.() -> Unit)? = null

A slot for providing the chip's main label. The contents are expected to be text which is "start" aligned if there is an icon preset and "center" aligned if not.

icon: (@Composable BoxScope.() -> Unit)? = null

A slot for providing the chip's icon. The contents are expected to be a horizontally and vertically aligned icon of size ChipDefaults.SmallIconSize when used with a label or ChipDefaults.IconSize when used as the only content in the CompactChip. In order to correctly render when the Chip is not enabled the icon must set its alpha value to LocalContentAlpha.

colors: ChipColors = ChipDefaults.outlinedChipColors()

ChipColors that will be used to resolve the background and content color for this chip in different states. See ChipDefaults.outlinedChipColors. Defaults to ChipDefaults.primaryChipColors

enabled: Boolean = true

Controls the enabled state of the chip. When false, this chip will not be clickable

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

contentPadding: PaddingValues = ChipDefaults.CompactChipContentPadding

The spacing values to apply internally between the container and the content

shape: Shape = MaterialTheme.shapes.large

Defines the chip's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme

border: ChipBorder = ChipDefaults.outlinedChipBorder()

ChipBorder that will be used to resolve the border for this chip in different states. See ChipDefaults.outlinedChipBorder.

@Composable
fun Picker(
    state: PickerState,
    modifier: Modifier = Modifier,
    readOnly: Boolean = false,
    readOnlyLabel: (@Composable BoxScope.() -> Unit)? = null,
    scalingParams: ScalingParams = PickerDefaults.scalingParams(),
    separation: Dp = 0.dp,
    gradientRatio: @FloatRange(from = 0.0, to = 0.5) Float = PickerDefaults.DefaultGradientRatio,
    gradientColor: Color = MaterialTheme.colors.background,
    flingBehavior: FlingBehavior = PickerDefaults.flingBehavior(state),
    option: @Composable PickerScope.(optionIndex: Int) -> Unit
): Unit

A scrollable list of items to pick from. By default, items will be repeated "infinitely" in both directions, unless PickerState#repeatItems is specified as false.

Example of a simple picker to select one of five options:

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.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Picker
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.rememberPickerState

val items = listOf("One", "Two", "Three", "Four", "Five")
val state = rememberPickerState(items.size)
val contentDescription by remember { derivedStateOf { "${state.selectedOption + 1}" } }
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
    Text(
        modifier = Modifier.align(Alignment.TopCenter).padding(top = 10.dp),
        text = "Selected: ${items[state.selectedOption]}"
    )
    Picker(
        modifier = Modifier.size(100.dp, 100.dp),
        state = state,
        contentDescription = contentDescription,
    ) {
        Text(items[it])
    }
}

Example of dual pickers, where clicking switches which one is editable and which is read-only:

import androidx.compose.foundation.layout.Arrangement
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.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.Picker
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.rememberPickerState

var selectedColumn by remember { mutableStateOf(0) }
val textStyle = MaterialTheme.typography.display1

@Composable
fun Option(column: Int, text: String) =
    Box(modifier = Modifier.fillMaxSize()) {
        Text(
            text = text,
            style = textStyle,
            color =
                if (selectedColumn == column) MaterialTheme.colors.secondary
                else MaterialTheme.colors.onBackground,
            modifier =
                Modifier.align(Alignment.Center).wrapContentSize().pointerInteropFilter {
                    if (it.action == MotionEvent.ACTION_DOWN) selectedColumn = column
                    true
                }
        )
    }

Row(
    modifier = Modifier.fillMaxSize(),
    verticalAlignment = Alignment.CenterVertically,
    horizontalArrangement = Arrangement.Center,
) {
    val hourState =
        rememberPickerState(initialNumberOfOptions = 12, initiallySelectedOption = 5)
    val hourContentDescription by remember {
        derivedStateOf { "${hourState.selectedOption + 1 } hours" }
    }
    Picker(
        readOnly = selectedColumn != 0,
        state = hourState,
        modifier = Modifier.size(64.dp, 100.dp),
        contentDescription = hourContentDescription,
        option = { hour: Int -> Option(0, "%2d".format(hour + 1)) }
    )
    Spacer(Modifier.width(8.dp))
    Text(text = ":", style = textStyle, color = MaterialTheme.colors.onBackground)
    Spacer(Modifier.width(8.dp))
    val minuteState =
        rememberPickerState(initialNumberOfOptions = 60, initiallySelectedOption = 0)
    val minuteContentDescription by remember {
        derivedStateOf { "${minuteState.selectedOption} minutes" }
    }
    Picker(
        readOnly = selectedColumn != 1,
        state = minuteState,
        modifier = Modifier.size(64.dp, 100.dp),
        contentDescription = minuteContentDescription,
        option = { minute: Int -> Option(1, "%02d".format(minute)) }
    )
}
Parameters
state: PickerState

The state of the component

modifier: Modifier = Modifier

Modifier to be applied to the Picker

readOnly: Boolean = false

Determines whether the Picker should display other available options for this field, inviting the user to scroll to change the value. When readOnly = true, only displays the currently selected option (and optionally a label). This is intended to be used for screens that display multiple Pickers, only one of which has the focus at a time.

readOnlyLabel: (@Composable BoxScope.() -> Unit)? = null

A slot for providing a label, displayed above the selected option when the Picker is read-only. The label is overlaid with the currently selected option within a Box, so it is recommended that the label is given Alignment.TopCenter.

scalingParams: ScalingParams = PickerDefaults.scalingParams()

The parameters to configure the scaling and transparency effects for the component. See ScalingParams

separation: Dp = 0.dp

The amount of separation in Dp between items. Can be negative, which can be useful for Text if it has plenty of whitespace.

gradientRatio: @FloatRange(from = 0.0, to = 0.5) Float = PickerDefaults.DefaultGradientRatio

The size relative to the Picker height that the top and bottom gradients take. These gradients blur the picker content on the top and bottom. The default is 0.33, so the top 1/3 and the bottom 1/3 of the picker are taken by gradients. Should be between 0.0 and 0.5. Use 0.0 to disable the gradient.

gradientColor: Color = MaterialTheme.colors.background

Should be the color outside of the Picker, so there is continuity.

flingBehavior: FlingBehavior = PickerDefaults.flingBehavior(state)

logic describing fling behavior.

option: @Composable PickerScope.(optionIndex: Int) -> Unit

A block which describes the content. Inside this block you can reference PickerScope.selectedOption and other properties in PickerScope. When read-only mode is in use on a screen, it is recommended that this content is given Alignment.Center in order to align with the centrally selected Picker value.

@Composable
fun Picker(
    state: PickerState,
    contentDescription: String?,
    modifier: Modifier = Modifier,
    readOnly: Boolean = false,
    readOnlyLabel: (@Composable BoxScope.() -> Unit)? = null,
    onSelected: () -> Unit = {},
    scalingParams: ScalingParams = PickerDefaults.defaultScalingParams(),
    separation: Dp = 0.dp,
    gradientRatio: @FloatRange(from = 0.0, to = 0.5) Float = PickerDefaults.DefaultGradientRatio,
    gradientColor: Color = MaterialTheme.colors.background,
    flingBehavior: FlingBehavior = PickerDefaults.flingBehavior(state),
    userScrollEnabled: Boolean = true,
    rotaryScrollableBehavior: RotaryScrollableBehavior? = RotaryScrollableDefaults.snapBehavior(state, state.toRotarySnapLayoutInfoProvider()),
    option: @Composable PickerScope.(optionIndex: Int) -> Unit
): Unit

A scrollable list of items to pick from. By default, items will be repeated "infinitely" in both directions, unless PickerState#repeatItems is specified as false.

This overload supports rotary input. Rotary input allows users to scroll the content of the Picker - by using a crown or a rotating bezel on their Wear OS device. It can be modified with rotaryScrollableBehavior param. Note that rotary scroll and touch scroll should be aligned. If rotaryScrollableBehavior is set for snap (using RotaryScrollableDefaults.snapBehavior), flingBehavior should be set for snap as well (using PickerDefaults.flingBehavior).

Example of a simple picker to select one of five options:

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.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Picker
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.rememberPickerState

val items = listOf("One", "Two", "Three", "Four", "Five")
val state = rememberPickerState(items.size)
val contentDescription by remember { derivedStateOf { "${state.selectedOption + 1}" } }
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
    Text(
        modifier = Modifier.align(Alignment.TopCenter).padding(top = 10.dp),
        text = "Selected: ${items[state.selectedOption]}"
    )
    Picker(
        modifier = Modifier.size(100.dp, 100.dp),
        state = state,
        contentDescription = contentDescription,
    ) {
        Text(items[it])
    }
}

Example of dual pickers, where clicking switches which one is editable and which is read-only:

import androidx.compose.foundation.layout.Arrangement
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.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInteropFilter
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.Picker
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.rememberPickerState

var selectedColumn by remember { mutableStateOf(0) }
val textStyle = MaterialTheme.typography.display1

@Composable
fun Option(column: Int, text: String) =
    Box(modifier = Modifier.fillMaxSize()) {
        Text(
            text = text,
            style = textStyle,
            color =
                if (selectedColumn == column) MaterialTheme.colors.secondary
                else MaterialTheme.colors.onBackground,
            modifier =
                Modifier.align(Alignment.Center).wrapContentSize().pointerInteropFilter {
                    if (it.action == MotionEvent.ACTION_DOWN) selectedColumn = column
                    true
                }
        )
    }

Row(
    modifier = Modifier.fillMaxSize(),
    verticalAlignment = Alignment.CenterVertically,
    horizontalArrangement = Arrangement.Center,
) {
    val hourState =
        rememberPickerState(initialNumberOfOptions = 12, initiallySelectedOption = 5)
    val hourContentDescription by remember {
        derivedStateOf { "${hourState.selectedOption + 1 } hours" }
    }
    Picker(
        readOnly = selectedColumn != 0,
        state = hourState,
        modifier = Modifier.size(64.dp, 100.dp),
        contentDescription = hourContentDescription,
        option = { hour: Int -> Option(0, "%2d".format(hour + 1)) }
    )
    Spacer(Modifier.width(8.dp))
    Text(text = ":", style = textStyle, color = MaterialTheme.colors.onBackground)
    Spacer(Modifier.width(8.dp))
    val minuteState =
        rememberPickerState(initialNumberOfOptions = 60, initiallySelectedOption = 0)
    val minuteContentDescription by remember {
        derivedStateOf { "${minuteState.selectedOption} minutes" }
    }
    Picker(
        readOnly = selectedColumn != 1,
        state = minuteState,
        modifier = Modifier.size(64.dp, 100.dp),
        contentDescription = minuteContentDescription,
        option = { minute: Int -> Option(1, "%02d".format(minute)) }
    )
}
Parameters
state: PickerState

The state of the component

contentDescription: String?

Text used by accessibility services to describe what the selected option represents. This text should be localized, such as by using androidx.compose.ui.res.stringResource or similar. Typically, the content description is inferred via derivedStateOf to avoid unnecessary recompositions, like this: val description by remember { derivedStateOf { /* expression using state.selectedOption */ } }

modifier: Modifier = Modifier

Modifier to be applied to the Picker

readOnly: Boolean = false

Determines whether the Picker should display other available options for this field, inviting the user to scroll to change the value. When readOnly = true, only displays the currently selected option (and optionally a label). This is intended to be used for screens that display multiple Pickers, only one of which has the focus at a time.

readOnlyLabel: (@Composable BoxScope.() -> Unit)? = null

A slot for providing a label, displayed above the selected option when the Picker is read-only. The label is overlaid with the currently selected option within a Box, so it is recommended that the label is given Alignment.TopCenter.

onSelected: () -> Unit = {}

Action triggered when the Picker is selected by clicking. Used by accessibility semantics, which facilitates implementation of multi-picker screens.

scalingParams: ScalingParams = PickerDefaults.defaultScalingParams()

The parameters to configure the scaling and transparency effects for the component. See ScalingParams

separation: Dp = 0.dp

The amount of separation in Dp between items. Can be negative, which can be useful for Text if it has plenty of whitespace.

gradientRatio: @FloatRange(from = 0.0, to = 0.5) Float = PickerDefaults.DefaultGradientRatio

The size relative to the Picker height that the top and bottom gradients take. These gradients blur the picker content on the top and bottom. The default is 0.33, so the top 1/3 and the bottom 1/3 of the picker are taken by gradients. Should be between 0.0 and 0.5. Use 0.0 to disable the gradient.

gradientColor: Color = MaterialTheme.colors.background

Should be the color outside of the Picker, so there is continuity.

flingBehavior: FlingBehavior = PickerDefaults.flingBehavior(state)

logic describing fling behavior. Note that when configuring fling or snap behavior, this flingBehavior parameter and the rotaryScrollableBehavior parameter that controls rotary scroll are expected to be consistent.

userScrollEnabled: Boolean = true

Determines whether the picker should be scrollable or not. When userScrollEnabled = true, picker is scrollable. This is different from readOnly as it changes the scrolling behaviour.

rotaryScrollableBehavior: RotaryScrollableBehavior? = RotaryScrollableDefaults.snapBehavior(state, state.toRotarySnapLayoutInfoProvider())

Parameter for changing rotary behavior. Supports scroll RotaryScrollableDefaults.behavior and snap RotaryScrollableDefaults.snapBehavior. We do recommend to use RotaryScrollableDefaults.snapBehavior as this is a recommended behavior for Pickers. Note that when configuring fling or snap behavior, this rotaryBehavior parameter and the flingBehavior parameter that controls touch scroll are expected to be consistent. Can be null if rotary support is not required.

option: @Composable PickerScope.(optionIndex: Int) -> Unit

A block which describes the content. Inside this block you can reference PickerScope.selectedOption and other properties in PickerScope. When read-only mode is in use on a screen, it is recommended that this content is given Alignment.Center in order to align with the centrally selected Picker value.

@Composable
fun PickerGroup(
    vararg pickers: PickerGroupItem,
    modifier: Modifier = Modifier,
    pickerGroupState: PickerGroupState = rememberPickerGroupState(),
    onSelected: (selectedIndex: Int) -> Unit = {},
    autoCenter: Boolean = true,
    propagateMinConstraints: Boolean = false,
    touchExplorationStateProvider: TouchExplorationStateProvider = DefaultTouchExplorationStateProvider(),
    separator: (@Composable (Int) -> Unit)? = null
): Unit

A group of Pickers to build components where multiple pickers are required to be combined together. The component maintains the focus between different Pickers by using PickerGroupState. It can be handled from outside the component using the same instance and its properties. When touch exploration services are enabled, the focus moves to the picker which is clicked. To handle clicks in a different manner, use the onSelected lambda to control the focus of talkback and actual focus.

It is recommended to ensure that a Picker in non read only mode should have user scroll enabled when touch exploration services are running.

Example of a sample picker group with an hour and minute picker (24 hour format)

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.PickerGroup
import androidx.wear.compose.material.PickerGroupItem
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.rememberPickerGroupState
import androidx.wear.compose.material.rememberPickerState

val pickerGroupState = rememberPickerGroupState()
val pickerStateHour = rememberPickerState(initialNumberOfOptions = 24)
val pickerStateMinute = rememberPickerState(initialNumberOfOptions = 60)
Column(
    modifier = Modifier.fillMaxWidth(),
    verticalArrangement = Arrangement.Center,
    horizontalAlignment = Alignment.CenterHorizontally
) {
    Spacer(modifier = Modifier.size(30.dp))
    Text(text = if (pickerGroupState.selectedIndex == 0) "Hours" else "Minutes")
    Spacer(modifier = Modifier.size(10.dp))
    PickerGroup(
        PickerGroupItem(
            pickerState = pickerStateHour,
            option = { optionIndex, _ -> Text(text = "%02d".format(optionIndex)) },
            modifier = Modifier.size(80.dp, 100.dp)
        ),
        PickerGroupItem(
            pickerState = pickerStateMinute,
            option = { optionIndex, _ -> Text(text = "%02d".format(optionIndex)) },
            modifier = Modifier.size(80.dp, 100.dp)
        ),
        pickerGroupState = pickerGroupState,
        autoCenter = false
    )
}

Example of an auto centering picker group where the total width exceeds screen's width

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.PickerGroup
import androidx.wear.compose.material.PickerGroupItem
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.rememberPickerGroupState
import androidx.wear.compose.material.rememberPickerState

val pickerGroupState = rememberPickerGroupState()
val pickerStateHour = rememberPickerState(initialNumberOfOptions = 24)
val pickerStateMinute = rememberPickerState(initialNumberOfOptions = 60)
val pickerStateSeconds = rememberPickerState(initialNumberOfOptions = 60)
val pickerStateMilliSeconds = rememberPickerState(initialNumberOfOptions = 1000)
Column(
    modifier = Modifier.fillMaxWidth(),
    verticalArrangement = Arrangement.Center,
    horizontalAlignment = Alignment.CenterHorizontally
) {
    val headingText = mapOf(0 to "Hours", 1 to "Minutes", 2 to "Seconds", 3 to "Milli")
    Spacer(modifier = Modifier.size(30.dp))
    Text(text = headingText[pickerGroupState.selectedIndex]!!)
    Spacer(modifier = Modifier.size(10.dp))
    PickerGroup(
        PickerGroupItem(
            pickerState = pickerStateHour,
            option = { optionIndex, _ -> Text(text = "%02d".format(optionIndex)) },
            modifier = Modifier.size(80.dp, 100.dp)
        ),
        PickerGroupItem(
            pickerState = pickerStateMinute,
            option = { optionIndex, _ -> Text(text = "%02d".format(optionIndex)) },
            modifier = Modifier.size(80.dp, 100.dp)
        ),
        PickerGroupItem(
            pickerState = pickerStateSeconds,
            option = { optionIndex, _ -> Text(text = "%02d".format(optionIndex)) },
            modifier = Modifier.size(80.dp, 100.dp)
        ),
        PickerGroupItem(
            pickerState = pickerStateMilliSeconds,
            option = { optionIndex, _ -> Text(text = "%03d".format(optionIndex)) },
            modifier = Modifier.size(80.dp, 100.dp)
        ),
        pickerGroupState = pickerGroupState,
        autoCenter = true
    )
}
Parameters
vararg pickers: PickerGroupItem

List of Pickers represented using PickerGroupItem in the same order of display from left to right.

modifier: Modifier = Modifier

Modifier to be applied to the PickerGroup

pickerGroupState: PickerGroupState = rememberPickerGroupState()

The state of the component

onSelected: (selectedIndex: Int) -> Unit = {}

Action triggered when one of the Picker is selected inside the group

autoCenter: Boolean = true

Indicates whether the selected Picker should be centered on the screen. It is recommended to set this as true when all the pickers cannot be fit into the screen. Or provide a mechanism to navigate to pickers which are not visible on screen. If false, the whole row containing pickers would be centered.

propagateMinConstraints: Boolean = false

Whether the incoming min constraints should be passed to content.

touchExplorationStateProvider: TouchExplorationStateProvider = DefaultTouchExplorationStateProvider()

A TouchExplorationStateProvider to provide the current state of touch exploration service. This will be used to determine how the PickerGroup and talkback focus behaves/reacts to click and scroll events.

separator: (@Composable (Int) -> Unit)? = null

A composable block which describes the separator between different Pickers. The integer parameter to the composable depicts the index where it will be kept. For example, 0 would represent the separator between the first and second picker.

PositionIndicator

@Composable
fun PositionIndicator(
    scalingLazyListState: ScalingLazyListState,
    modifier: Modifier = Modifier,
    reverseDirection: Boolean = false
): Unit

Creates an PositionIndicator based on the values in a ScalingLazyListState object that a ScalingLazyColumn uses.

For more information, see the Scroll indicators guide.

Parameters
scalingLazyListState: ScalingLazyListState

the ScalingLazyListState to use as the basis for the PositionIndicatorState.

modifier: Modifier = Modifier

The modifier to be applied to the component

reverseDirection: Boolean = false

Reverses direction of PositionIndicator if true

PositionIndicator

@Composable
fun PositionIndicator(
    lazyListState: LazyListState,
    modifier: Modifier = Modifier,
    reverseDirection: Boolean = false,
    fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
    fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
    positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec
): Unit

Creates an PositionIndicator based on the values in a LazyListState object that a LazyColumn uses.

For more information, see the Scroll indicators guide.

Parameters
lazyListState: LazyListState

the LazyListState to use as the basis for the PositionIndicatorState.

modifier: Modifier = Modifier

The modifier to be applied to the component

reverseDirection: Boolean = false

Reverses direction of PositionIndicator if true

fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec

AnimationSpec for fade-in animation. Fade-in animation is triggered when the PositionIndicator becomes visible - either when state.visibility changes to Show, or state.visibility is AutoHide and state.positionFraction/state.sizeFraction are changed. To disable this animation snap AnimationSpec should be passed instead.

fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec

AnimationSpec for fade-out animation. The Fade-out animation is used for hiding the PositionIndicator and making it invisible. PositionIndicator will be hidden after a specified delay if no changes in state.positionFraction or state.sizeFraction were detected. If fadeOutAnimationSpec is snap, then after a delay it will be instantly hidden.

positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec

AnimationSpec for position animation. The Position animation is used for animating changes between state.positionFraction and state.sizeFraction of PositionIndicatorState. To disable this animation snap AnimationSpec should be passed instead.

PositionIndicator

@Composable
fun PositionIndicator(
    scalingLazyListState: ScalingLazyListState,
    modifier: Modifier = Modifier,
    reverseDirection: Boolean = false,
    fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
    fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
    positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec
): Unit

Creates an PositionIndicator based on the values in a ScalingLazyListState object that a ScalingLazyColumn uses.

For more information, see the Scroll indicators guide.

Parameters
scalingLazyListState: ScalingLazyListState

the ScalingLazyListState to use as the basis for the PositionIndicatorState.

modifier: Modifier = Modifier

The modifier to be applied to the component

reverseDirection: Boolean = false

Reverses direction of PositionIndicator if true

fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec

AnimationSpec for fade-in animation. Fade-in animation is triggered when the PositionIndicator becomes visible - either when state.visibility changes to Show, or state.visibility is AutoHide and state.positionFraction/state.sizeFraction are changed. To disable this animation snap AnimationSpec should be passed instead.

fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec

AnimationSpec for fade-out animation. The Fade-out animation is used for hiding the PositionIndicator and making it invisible. PositionIndicator will be hidden after a specified delay if no changes in state.positionFraction or state.sizeFraction were detected. If fadeOutAnimationSpec is snap, then after a delay it will be instantly hidden.

positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec

AnimationSpec for position animation. The Position animation is used for animating changes between state.positionFraction and state.sizeFraction of PositionIndicatorState. To disable this animation snap AnimationSpec should be passed instead.

PositionIndicator

@Composable
fun PositionIndicator(
    scrollState: ScrollState,
    modifier: Modifier = Modifier,
    reverseDirection: Boolean = false,
    fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
    fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
    positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec
): Unit

Creates an PositionIndicator based on the values in a ScrollState object. e.g. a Column implementing Modifier.verticalScroll provides a ScrollState.

For more information, see the Scroll indicators guide.

Parameters
scrollState: ScrollState

The scrollState to use as the basis for the PositionIndicatorState.

modifier: Modifier = Modifier

The modifier to be applied to the component

reverseDirection: Boolean = false

Reverses direction of PositionIndicator if true

fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec

AnimationSpec for fade-in animation. Fade-in animation is triggered when the PositionIndicator becomes visible - either when state.visibility changes to Show, or state.visibility is AutoHide and state.positionFraction/state.sizeFraction are changed. To disable this animation snap AnimationSpec should be passed instead.

fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec

AnimationSpec for fade-out animation. The Fade-out animation is used for hiding the PositionIndicator and making it invisible. PositionIndicator will be hidden after a specified delay if no changes in state.positionFraction or state.sizeFraction were detected. If fadeOutAnimationSpec is snap, then after a delay it will be instantly hidden.

positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec

AnimationSpec for position animation. The Position animation is used for animating changes between state.positionFraction and state.sizeFraction of PositionIndicatorState. To disable this animation snap AnimationSpec should be passed instead.

@Composable
fun PositionIndicator(
    value: () -> Float,
    modifier: Modifier = Modifier,
    range: ClosedFloatingPointRange<Float> = 0f..1f,
    color: Color = MaterialTheme.colors.onBackground,
    reverseDirection: Boolean = false,
    position: PositionIndicatorAlignment = PositionIndicatorAlignment.OppositeRsb,
    fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
    fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
    positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec
): Unit

Creates a PositionIndicator for controls like rotating side button, rotating bezel or slider.

For more information, see the Scroll indicators guide.

Parameters
value: () -> Float

Value of the indicator in the range where 1 represents the maximum value. E.g. If displaying a volume value from 0..11 then the value will be volume/11.

modifier: Modifier = Modifier

Modifier to be applied to the component

range: ClosedFloatingPointRange<Float> = 0f..1f

range of values that value can take

color: Color = MaterialTheme.colors.onBackground

Color to draw the indicator on.

reverseDirection: Boolean = false

Reverses direction of PositionIndicator if true

position: PositionIndicatorAlignment = PositionIndicatorAlignment.OppositeRsb

indicates where to put the PositionIndicator in the screen, default is PositionIndicatorPosition#OppositeRsb

fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec

AnimationSpec for fade-in animation. Fade-in animation is triggered when the PositionIndicator becomes visible - either when state.visibility changes to Show, or state.visibility is AutoHide and state.positionFraction/state.sizeFraction are changed. To disable this animation snap AnimationSpec should be passed instead.

fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec

AnimationSpec for fade-out animation. The Fade-out animation is used for hiding the PositionIndicator and making it invisible. PositionIndicator will be hidden after a specified delay if no changes in state.positionFraction or state.sizeFraction were detected. If fadeOutAnimationSpec is snap, then after a delay it will be instantly hidden.

positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec

AnimationSpec for position animation. The Position animation is used for animating changes between state.positionFraction and state.sizeFraction of PositionIndicatorState. To disable this animation snap AnimationSpec should be passed instead.

@Composable
fun PositionIndicator(
    state: PositionIndicatorState,
    indicatorHeight: Dp,
    indicatorWidth: Dp,
    paddingHorizontal: Dp,
    modifier: Modifier = Modifier,
    background: Color = MaterialTheme.colors.onBackground.copy(alpha = 0.3f),
    color: Color = MaterialTheme.colors.onBackground,
    reverseDirection: Boolean = false,
    position: PositionIndicatorAlignment = PositionIndicatorAlignment.End,
    fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
    fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec,
    positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec
): Unit

An indicator on one side of the screen to show the current PositionIndicatorState.

Typically used with the Scaffold but can be used to decorate any full screen situation.

This composable should only be used to fill the whole screen as Wear Material Design language requires the placement of the position indicator to be right center of the screen as the indicator is curved on circular devices.

It detects if the screen is round or square and draws itself as a curve or line.

Note that the composable will take the whole screen, but it will be drawn with the given dimensions indicatorHeight and indicatorWidth, and position with respect to the edge of the screen according to paddingHorizontal

This PositionIndicator has 3 separate animation specs to control different animations.

For performance reasons and for UX consistency, when PositionIndicator is used with scrollable list, we recommend to switch off fade-in and position animations by passing snap spec into fadeInAnimationSpec and positionAnimationSpec parameters. If PositionIndicator is used as a standalone indicator, for example as volume control, then we recommend to have all 3 animations turned on.

If color of PositionIndicator is not white and position animation is enabled - a short highlight animation will be triggered on any position change. This is a short animation accenting PositionIndicator with white color with 33% opacity.

For more information, see the Scroll indicators guide.

Parameters
state: PositionIndicatorState

the PositionIndicatorState of the state we are displaying.

indicatorHeight: Dp

the height of the position indicator in Dp.

indicatorWidth: Dp

the width of the position indicator in Dp.

paddingHorizontal: Dp

the padding to apply between the indicator and the border of the screen.

modifier: Modifier = Modifier

The modifier to be applied to the component.

background: Color = MaterialTheme.colors.onBackground.copy(alpha = 0.3f)

the color to draw the non-active part of the position indicator.

color: Color = MaterialTheme.colors.onBackground

the color to draw the active part of the indicator in.

reverseDirection: Boolean = false

Reverses direction of PositionIndicator if true.

position: PositionIndicatorAlignment = PositionIndicatorAlignment.End

indicates where to put the PositionIndicator on the screen, default is PositionIndicatorPosition#End

fadeInAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec

AnimationSpec for fade-in animation. Fade-in animation is triggered when the PositionIndicator becomes visible - either when state.visibility changes to Show, or state.visibility is AutoHide and state.positionFraction/state.sizeFraction are changed. To disable this animation snap AnimationSpec should be passed instead.

fadeOutAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.visibilityAnimationSpec

AnimationSpec for fade-out animation. The Fade-out animation is used for hiding the PositionIndicator and making it invisible. PositionIndicator will be hidden after a specified delay if no changes in state.positionFraction or state.sizeFraction were detected. If fadeOutAnimationSpec is snap, then after a delay it will be instantly hidden.

positionAnimationSpec: AnimationSpec<Float> = PositionIndicatorDefaults.positionAnimationSpec

AnimationSpec for position animation. The Position animation is used for animating changes between state.positionFraction and state.sizeFraction of PositionIndicatorState. To disable animation snap should be passed.

ProvideTextStyle

@Composable
fun ProvideTextStyle(value: TextStyle, content: @Composable () -> Unit): Unit

This function is used to set the current value of LocalTextStyle, merging the given style with the current style values for any missing attributes. Any Text components included in this component's content will be styled with this style unless styled explicitly.

See also
LocalTextStyle
@Composable
fun RadioButton(
    selected: Boolean,
    modifier: Modifier = Modifier,
    colors: RadioButtonColors = RadioButtonDefaults.colors(),
    enabled: Boolean = true,
    onClick: (() -> Unit)? = null,
    interactionSource: MutableInteractionSource? = null
): Unit

RadioButton provides an animated radio button for use as a toggle control in ToggleChip or SplitToggleChip.

Example of a ToggleChip with RadioButton toggle control:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.SelectableChip
import androidx.wear.compose.material.Text

var selectedRadioIndex by remember { mutableStateOf(0) }
Column(
    modifier = Modifier.fillMaxSize(),
    verticalArrangement = Arrangement.Center,
    horizontalAlignment = Alignment.CenterHorizontally,
) {
    SelectableChip(
        modifier = Modifier.fillMaxWidth(),
        selected = selectedRadioIndex == 0,
        onClick = { selectedRadioIndex = 0 },
        label = {
            // The primary label should have a maximum 3 lines of text
            Text("Primary label", maxLines = 3, overflow = TextOverflow.Ellipsis)
        },
        secondaryLabel = {
            // and the secondary label should have max 2 lines of text.
            Text("Secondary label", maxLines = 2, overflow = TextOverflow.Ellipsis)
        },
        appIcon = {
            Icon(
                painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
                contentDescription = "airplane",
                modifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center),
            )
        },
        enabled = true,
    )
    Spacer(modifier = Modifier.height(8.dp))
    SelectableChip(
        modifier = Modifier.fillMaxWidth(),
        selected = selectedRadioIndex == 1,
        onClick = { selectedRadioIndex = 1 },
        label = {
            // The primary label should have a maximum 3 lines of text
            Text("Alternative label", maxLines = 3, overflow = TextOverflow.Ellipsis)
        },
        secondaryLabel = {
            // and the secondary label should have max 2 lines of text.
            Text("Alternative secondary", maxLines = 2, overflow = TextOverflow.Ellipsis)
        },
        appIcon = {
            Icon(
                painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
                contentDescription = "airplane",
                modifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center),
            )
        },
        enabled = true,
    )
}
Parameters
selected: Boolean

Boolean flag indicating whether this radio button is currently toggled on.

modifier: Modifier = Modifier

Modifier to be applied to the radio button. This can be used to provide a content description for accessibility.

colors: RadioButtonColors = RadioButtonDefaults.colors()

ToggleChipColors from which the toggleControlColors will be obtained.

enabled: Boolean = true

Boolean flag indicating the enabled state of the RadioButton (affects the color).

onClick: (() -> Unit)? = null

Callback to be invoked when RadioButton is clicked. If null, then this is passive and relies entirely on a higher-level component to control the state (such as ToggleChip or SplitToggleChip).

interactionSource: MutableInteractionSource? = null

When also providing onClick, an optional hoisted MutableInteractionSource for observing and emitting Interactions for this radio button. You can use this to change the radio button's appearance or preview the radio button in different states. Note that if null is provided, interactions will still happen internally.

@Composable
fun Scaffold(
    modifier: Modifier = Modifier,
    vignette: (@Composable () -> Unit)? = null,
    positionIndicator: (@Composable () -> Unit)? = null,
    pageIndicator: (@Composable () -> Unit)? = null,
    timeText: (@Composable () -> Unit)? = null,
    content: @Composable () -> Unit
): Unit

Scaffold implements the basic Wear Material Design visual layout structure.

This component provides API to put together several material components to construct your screen, by ensuring proper layout strategy for them and collecting necessary data so these components will work together correctly.

The Scaffold provides the main application structure in a Wear Material application. It provides slots for the different parts of the application and sensible defaults were appropriate.

The layout of the Wear Scaffold is typically z-layered with decorations such as PositionIndicator, HorizontalPageIndicator and Vignette applied in the order laid out in the Wear Material Design guidance.

Simple example of a Scaffold with a ScalingLazyColumn as the main application content and a scroll indicator to show the position of the items in the ScalingLazyColumn as.

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.TimeText
import androidx.wear.compose.material.Vignette
import androidx.wear.compose.material.VignettePosition

val listState = rememberScalingLazyListState()
val vignetteState = mutableStateOf(VignettePosition.TopAndBottom)
val showVignette = mutableStateOf(true)

Scaffold(
    positionIndicator = {
        PositionIndicator(scalingLazyListState = listState, modifier = Modifier)
    },
    vignette = {
        if (showVignette.value) {
            Vignette(vignettePosition = vignetteState.value)
        }
    },
    timeText = { TimeText() }
) {
    ScalingLazyColumn(
        contentPadding = PaddingValues(top = 40.dp),
        state = listState,
        modifier = Modifier.fillMaxWidth()
    ) {
        item {
            Chip(
                onClick = { showVignette.value = false },
                label = { Text("No Vignette") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
        item {
            Chip(
                onClick = {
                    showVignette.value = true
                    vignetteState.value = VignettePosition.Top
                },
                label = { Text("Top Vignette only") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
        item {
            Chip(
                onClick = {
                    showVignette.value = true
                    vignetteState.value = VignettePosition.Bottom
                },
                label = { Text("Bottom Vignette only") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
        item {
            Chip(
                onClick = {
                    showVignette.value = true
                    vignetteState.value = VignettePosition.TopAndBottom
                },
                label = { Text("Top and Bottom Vignette") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
        items(20) {
            Chip(
                onClick = {},
                label = { Text("List item $it") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
    }
}
Parameters
modifier: Modifier = Modifier

optional Modifier for the root of the Scaffold

vignette: (@Composable () -> Unit)? = null

a full screen slot for applying a vignette over the contents of the scaffold. The vignette is used to blur the screen edges when the main content is scrollable content that extends beyond the screen edge.

positionIndicator: (@Composable () -> Unit)? = null

slot for optional position indicator used to display information about the position of the Scaffold's contents. Usually a PositionIndicator. Common use cases for the position indicator are scroll indication for a list or rsb/bezel indication such as volume.

pageIndicator: (@Composable () -> Unit)? = null

slot for optional page indicator used to display information about the selected page of the Scaffold's contents. Usually a HorizontalPageIndicator. Common use case for the page indicator is a pager with horizontally swipeable pages.

timeText: (@Composable () -> Unit)? = null

time and potential application status message to display at the top middle of the screen. Expected to be a TimeText component.

content: @Composable () -> Unit

Slot for composable screen content

@Composable
fun ScalingLazyColumn(
    modifier: Modifier = Modifier,
    state: ScalingLazyListState = rememberScalingLazyListState(),
    contentPadding: PaddingValues = PaddingValues(horizontal = 10.dp),
    reverseLayout: Boolean = false,
    verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy( space = 4.dp, alignment = if (!reverseLayout) Alignment.Top else Alignment.Bottom ),
    horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally,
    flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(),
    userScrollEnabled: Boolean = true,
    scalingParams: ScalingParams = ScalingLazyColumnDefaults.scalingParams(),
    anchorType: ScalingLazyListAnchorType = ScalingLazyListAnchorType.ItemCenter,
    autoCentering: AutoCenteringParams? = AutoCenteringParams(),
    content: ScalingLazyListScope.() -> Unit
): Unit

A scrolling scaling/fisheye list component that forms a key part of the Wear Material Design language. Provides scaling and transparency effects to the content items.

ScalingLazyColumn is designed to be able to handle potentially large numbers of content items. Content items are only materialized and composed when needed.

If scaling/fisheye functionality is not required then a LazyColumn should be considered instead to avoid any overhead of measuring and calculating scaling and transparency effects for the content items.

Example of a ScalingLazyColumn with default parameters:

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.ui.Modifier
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.ListHeader
import androidx.wear.compose.material.Text

ScalingLazyColumn(modifier = Modifier.fillMaxWidth()) {
    item { ListHeader { Text(text = "List Header") } }
    items(20) {
        Chip(
            onClick = {},
            label = { Text("List item $it") },
            colors = ChipDefaults.secondaryChipColors()
        )
    }
}

Example of a ScalingLazyColumn using ScalingLazyListAnchorType.ItemStart anchoring, in this configuration the edge of list items is aligned to the center of the screen. Also this example shows scrolling to a clicked list item with ScalingLazyListState.animateScrollToItem:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.AutoCenteringParams
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.foundation.lazy.ScalingLazyListAnchorType
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.ListHeader
import androidx.wear.compose.material.Text

val coroutineScope = rememberCoroutineScope()
val itemSpacing = 6.dp
// Line up the gap between the items on the center-line
val scrollOffset = with(LocalDensity.current) { -(itemSpacing / 2).roundToPx() }
val state =
    rememberScalingLazyListState(
        initialCenterItemIndex = 1,
        initialCenterItemScrollOffset = scrollOffset
    )

ScalingLazyColumn(
    modifier = Modifier.fillMaxWidth(),
    anchorType = ScalingLazyListAnchorType.ItemStart,
    verticalArrangement = Arrangement.spacedBy(itemSpacing),
    state = state,
    autoCentering = AutoCenteringParams(itemOffset = scrollOffset)
) {
    item { ListHeader { Text(text = "List Header") } }
    items(20) {
        Chip(
            onClick = {
                coroutineScope.launch {
                    // Add +1 to allow for the ListHeader
                    state.animateScrollToItem(it + 1, scrollOffset)
                }
            },
            label = { Text("List item $it") },
            colors = ChipDefaults.secondaryChipColors()
        )
    }
}

Example of a ScalingLazyColumn with snap of items to the viewport center:

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.ui.Modifier
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.foundation.lazy.ScalingLazyColumnDefaults
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.ListHeader
import androidx.wear.compose.material.Text

val state = rememberScalingLazyListState()
ScalingLazyColumn(
    modifier = Modifier.fillMaxWidth(),
    state = state,
    flingBehavior = ScalingLazyColumnDefaults.snapFlingBehavior(state = state)
) {
    item { ListHeader { Text(text = "List Header") } }
    items(20) {
        Chip(
            onClick = {},
            label = { Text("List item $it") },
            colors = ChipDefaults.secondaryChipColors()
        )
    }
}

Example of a ScalingLazyColumn where autoCentering has been disabled and explicit contentPadding provided to ensure there is space above the first and below the last list item to allow them to be scrolled into view on circular screens:

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.ListHeader
import androidx.wear.compose.material.Text

ScalingLazyColumn(
    modifier = Modifier.fillMaxWidth(),
    contentPadding = PaddingValues(top = 20.dp, bottom = 20.dp),
    autoCentering = null
) {
    item { ListHeader { Text(text = "List Header") } }
    items(20) {
        Chip(
            onClick = {},
            label = { Text("List item $it") },
            colors = ChipDefaults.secondaryChipColors()
        )
    }
}

For more information, see the Lists guide.

Parameters
modifier: Modifier = Modifier

The modifier to be applied to the component

state: ScalingLazyListState = rememberScalingLazyListState()

The state of the component

contentPadding: PaddingValues = PaddingValues(horizontal = 10.dp)

The padding to apply around the contents

reverseLayout: Boolean = false

reverse the direction of scrolling and layout, when true items will be composed from the bottom to the top

verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy( space = 4.dp, alignment = if (!reverseLayout) Alignment.Top else Alignment.Bottom )

The vertical arrangement of the layout's children. This allows us to add spacing between items and specify the arrangement of the items when we have not enough of them to fill the whole minimum size

horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally

the horizontal alignment applied to the items

flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior()

Logic describing fling behavior. If snapping is required use ScalingLazyColumnDefaults.snapFlingBehavior.

userScrollEnabled: Boolean = true

whether the scrolling via the user gestures or accessibility actions is allowed. You can still scroll programmatically using the state even when it is disabled.

scalingParams: ScalingParams = ScalingLazyColumnDefaults.scalingParams()

The parameters to configure the scaling and transparency effects for the component

anchorType: ScalingLazyListAnchorType = ScalingLazyListAnchorType.ItemCenter

How to anchor list items to the center-line of the viewport

autoCentering: AutoCenteringParams? = AutoCenteringParams()

AutoCenteringParams parameter to control whether space/padding should be automatically added to make sure that list items can be scrolled into the center of the viewport (based on their anchorType). If non-null then space will be added before the first list item, if needed, to ensure that items with indexes greater than or equal to the itemIndex (offset by itemOffset pixels) will be able to be scrolled to the center of the viewport. Similarly space will be added at the end of the list to ensure that items can be scrolled up to the center. If null no automatic space will be added and instead the developer can use contentPadding to manually arrange the items.

SelectableChip

@Composable
fun SelectableChip(
    selected: Boolean,
    onClick: (Boolean) -> Unit,
    label: @Composable RowScope.() -> Unit,
    modifier: Modifier = Modifier,
    appIcon: (@Composable BoxScope.() -> Unit)? = null,
    secondaryLabel: (@Composable RowScope.() -> Unit)? = null,
    colors: SelectableChipColors = SelectableChipDefaults.selectableChipColors(),
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    contentPadding: PaddingValues = SelectableChipDefaults.ContentPadding,
    shape: Shape = MaterialTheme.shapes.large,
    selectionControl: @Composable () -> Unit = { RadioButton(selected = selected, enabled = enabled) }
): Unit

A SelectableChip is a specialized type of Chip that includes a slot for a bi-state selection control such as a radio button. This overload provides suitable accessibility semantics for a selectable control like RadioButton. For toggleable controls like Checkbox and Switch, use ToggleChip instead.

The Wear Material SelectableChip offers four slots and a specific layout for an application icon, a label, a secondaryLabel and selection control. The application icon and secondaryLabel are optional. The items are laid out in a row with the optional icon at the start, a column containing the two label slots in the middle and a slot for the selection control at the end.

The SelectableChip is Stadium shaped and has a max height designed to take no more than two lines of text of Typography.button style. With localisation and/or large font sizes, the SelectableChip height adjusts to accommodate the contents. The label and secondary label should be consistently aligned.

The recommended set of SelectableChipColors can be obtained from SelectableChipDefaults, e.g. SelectableChipDefaults.selectableChipColors.

Chips can be enabled or disabled. A disabled chip will not respond to click events.

Example of a SelectableChip with an icon, label and secondary label (defaults to radio button):

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.SelectableChip
import androidx.wear.compose.material.Text

var selectedRadioIndex by remember { mutableStateOf(0) }
Column(
    modifier = Modifier.fillMaxSize(),
    verticalArrangement = Arrangement.Center,
    horizontalAlignment = Alignment.CenterHorizontally,
) {
    SelectableChip(
        modifier = Modifier.fillMaxWidth(),
        selected = selectedRadioIndex == 0,
        onClick = { selectedRadioIndex = 0 },
        label = {
            // The primary label should have a maximum 3 lines of text
            Text("Primary label", maxLines = 3, overflow = TextOverflow.Ellipsis)
        },
        secondaryLabel = {
            // and the secondary label should have max 2 lines of text.
            Text("Secondary label", maxLines = 2, overflow = TextOverflow.Ellipsis)
        },
        appIcon = {
            Icon(
                painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
                contentDescription = "airplane",
                modifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center),
            )
        },
        enabled = true,
    )
    Spacer(modifier = Modifier.height(8.dp))
    SelectableChip(
        modifier = Modifier.fillMaxWidth(),
        selected = selectedRadioIndex == 1,
        onClick = { selectedRadioIndex = 1 },
        label = {
            // The primary label should have a maximum 3 lines of text
            Text("Alternative label", maxLines = 3, overflow = TextOverflow.Ellipsis)
        },
        secondaryLabel = {
            // and the secondary label should have max 2 lines of text.
            Text("Alternative secondary", maxLines = 2, overflow = TextOverflow.Ellipsis)
        },
        appIcon = {
            Icon(
                painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
                contentDescription = "airplane",
                modifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center),
            )
        },
        enabled = true,
    )
}

For more information, see the Toggle Chips guide.

Parameters
selected: Boolean

Boolean flag indicating whether this button is currently selected.

onClick: (Boolean) -> Unit

Callback to be invoked when this button is selected.

label: @Composable RowScope.() -> Unit

A slot for providing the chip's main label. The contents are expected to be text which is "start" aligned.

modifier: Modifier = Modifier

Modifier to be applied to the chip

appIcon: (@Composable BoxScope.() -> Unit)? = null

An optional slot for providing an icon to indicate the purpose of the chip. The contents are expected to be a horizontally and vertically centre aligned icon of size SelectableChipDefaults.IconSize. In order to correctly render when the Chip is not enabled the icon must set its alpha value to LocalContentAlpha.

secondaryLabel: (@Composable RowScope.() -> Unit)? = null

A slot for providing the chip's secondary label. The contents are expected to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned if not. label and secondaryLabel contents should be consistently aligned.

colors: SelectableChipColors = SelectableChipDefaults.selectableChipColors()

SelectableChipColors that will be used to resolve the background and content color for this chip in different states, see SelectableChipDefaults.selectableChipColors.

enabled: Boolean = true

Controls the enabled state of the chip. When false, this chip will not be clickable

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip's "selectable" tap area. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

contentPadding: PaddingValues = SelectableChipDefaults.ContentPadding

The spacing values to apply internally between the container and the content

shape: Shape = MaterialTheme.shapes.large

Defines the chip's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme

selectionControl: @Composable () -> Unit = { RadioButton(selected = selected, enabled = enabled) }

A slot for providing the chip's selection control. One built-in type of selection control is supported, see RadioButton. For Checkbox and Switch, use ToggleChip in order to provide the correct semantics for accessibility.

SplitSelectableChip

@Composable
fun SplitSelectableChip(
    selected: Boolean,
    onSelectionClick: (Boolean) -> Unit,
    label: @Composable RowScope.() -> Unit,
    onContainerClick: () -> Unit,
    modifier: Modifier = Modifier,
    secondaryLabel: (@Composable RowScope.() -> Unit)? = null,
    colors: SplitSelectableChipColors = SelectableChipDefaults.splitSelectableChipColors(),
    enabled: Boolean = true,
    selectionInteractionSource: MutableInteractionSource? = null,
    containerInteractionSource: MutableInteractionSource? = null,
    contentPadding: PaddingValues = SelectableChipDefaults.ContentPadding,
    shape: Shape = MaterialTheme.shapes.large,
    selectionControl: @Composable BoxScope.() -> Unit = { RadioButton(selected = selected, enabled = enabled) }
): Unit

A SplitSelectableChip is a specialized type of Chip that includes a slot for a selection control, such as a radio button. The SplitSelectableChip differs from the SelectableChip by having two "tappable" areas, one clickable and one selectable.

The SplitSelectableChip provides suitable accessibility semantics for a selectable control like RadioButton. For toggleable controls like Checkbox and Switch, use SplitToggleChip.

The Wear Material SplitSelectableChip offers three slots and a specific layout for a label, secondaryLabel and selection control. The secondaryLabel is optional. The items are laid out with a column containing the two label slots and a slot for the selection control at the end.

A SplitSelectableChip has two tappable areas, one tap area for the labels and another for the selection control. The onContainerClick callback will be associated with the main body of the SplitSelectableChip with the onSelectionClick callback associated with the selection control area only.

For a SplitSelectableChip the background of the tappable background area behind the selection control will have a visual effect applied to provide a "divider" between the two tappable areas.

The SplitSelectableChip is Stadium shaped and has a max height designed to take no more than two lines of text of Typography.button style. With localisation and/or large font sizes, the SplitSelectableChip height adjusts to accommodate the contents. The label and secondary label should be consistently aligned.

The recommended set of SplitSelectableChipColors can be obtained from SelectableChipDefaults, e.g. SelectableChipDefaults.splitSelectableChipColors.

Chips can be enabled or disabled. A disabled chip will not respond to click events.

Example of a SplitSelectableChip with a label and the radio button selection control:

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.SelectableChip
import androidx.wear.compose.material.SplitSelectableChip
import androidx.wear.compose.material.Text

var selectedRadioIndex by remember { mutableStateOf(0) }
Column(
    modifier = Modifier.fillMaxSize(),
    verticalArrangement = Arrangement.Center,
    horizontalAlignment = Alignment.CenterHorizontally,
) {
    SplitSelectableChip(
        modifier = Modifier.fillMaxWidth(),
        selected = selectedRadioIndex == 0,
        onSelectionClick = { selectedRadioIndex = 0 },
        label = {
            // The primary label should have a maximum 3 lines of text
            Text("Primary label", maxLines = 3, overflow = TextOverflow.Ellipsis)
        },
        secondaryLabel = {
            // and the secondary label should have max 2 lines of text.
            Text("Secondary label", maxLines = 2, overflow = TextOverflow.Ellipsis)
        },
        onContainerClick = {
            /* Do something */
        },
        enabled = true,
    )
    Spacer(modifier = Modifier.height(8.dp))
    SplitSelectableChip(
        modifier = Modifier.fillMaxWidth(),
        selected = selectedRadioIndex == 1,
        onSelectionClick = { selectedRadioIndex = 1 },
        label = {
            // The primary label should have a maximum 3 lines of text
            Text("Alternative label", maxLines = 3, overflow = TextOverflow.Ellipsis)
        },
        secondaryLabel = {
            // and the secondary label should have max 2 lines of text.
            Text("Alternative secondary", maxLines = 2, overflow = TextOverflow.Ellipsis)
        },
        onContainerClick = {
            /* Do something */
        },
        enabled = true,
    )
}

For more information, see the Toggle Chips guide.

Parameters
selected: Boolean

Boolean flag indicating whether this button is currently selected.

onSelectionClick: (Boolean) -> Unit

Callback to be invoked when this button is selected.

label: @Composable RowScope.() -> Unit

A slot for providing the chip's main label. The contents are expected to be text which is "start" aligned.

onContainerClick: () -> Unit

Callback to be invoked when the user clicks the main body of the chip, the area containing the labels.

modifier: Modifier = Modifier

Modifier to be applied to the chip

secondaryLabel: (@Composable RowScope.() -> Unit)? = null

A slot for providing the chip's secondary label. The contents are expected to be "start" or "center" aligned. label and secondaryLabel contents should be consistently aligned.

colors: SplitSelectableChipColors = SelectableChipDefaults.splitSelectableChipColors()

SplitSelectableChipColors that will be used to resolve the background and content color for this chip in different states, see SelectableChipDefaults.splitSelectableChipColors.

enabled: Boolean = true

Controls the enabled state of the chip. When false, this chip will not be clickable

selectionInteractionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip's "selectable" tap area. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

containerInteractionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip's "clickable" tap area. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

contentPadding: PaddingValues = SelectableChipDefaults.ContentPadding

The spacing values to apply internally between the container and the content

shape: Shape = MaterialTheme.shapes.large

Defines the chip's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme

selectionControl: @Composable BoxScope.() -> Unit = { RadioButton(selected = selected, enabled = enabled) }

A slot for providing the chip's selection control. One built-in selection control is provided, see RadioButton. For Checkbox and Switch, use SplitToggleChip instead.

SplitToggleChip

@Composable
fun SplitToggleChip(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    label: @Composable RowScope.() -> Unit,
    onClick: () -> Unit,
    toggleControl: @Composable BoxScope.() -> Unit,
    modifier: Modifier = Modifier,
    secondaryLabel: (@Composable RowScope.() -> Unit)? = null,
    colors: SplitToggleChipColors = ToggleChipDefaults.splitToggleChipColors(),
    enabled: Boolean = true,
    checkedInteractionSource: MutableInteractionSource? = null,
    clickInteractionSource: MutableInteractionSource? = null,
    contentPadding: PaddingValues = ToggleChipDefaults.ContentPadding,
    shape: Shape = MaterialTheme.shapes.large
): Unit

A SplitToggleChip is a specialized type of Chip that includes a slot for a toggle control, such as a toggle or checkbox. The SplitToggleChip differs from the ToggleChip by having two "tappable" areas, one clickable and one toggleable.

This overload provides suitable accessibility semantics for a toggleable control like Checkbox and Switch. For selectable controls like RadioButton, use SelectableChip instead.

The Wear Material SplitToggleChip offers three slots and a specific layout for a label, secondaryLabel and toggle control. The secondaryLabel is optional. The items are laid out with a column containing the two label slots and a slot for the toggle control at the end.

A SplitToggleChip has two tappable areas, one tap area for the labels and another for the toggle control. The onClick listener will be associated with the main body of the split toggle chip with the onCheckedChange listener associated with the toggle control area only.

For a split toggle chip the background of the tappable background area behind the toggle control will have a visual effect applied to provide a "divider" between the two tappable areas.

The SplitToggleChip is Stadium shaped and has a max height designed to take no more than two lines of text of Typography.button style. With localisation and/or large font sizes, the SplitToggleChip height adjusts to accommodate the contents. The label and secondary label should be consistently aligned.

The recommended set of SplitToggleChipColors can be obtained from ToggleChipDefaults, e.g. ToggleChipDefaults.splitToggleChipColors.

Chips can be enabled or disabled. A disabled chip will not respond to click events.

Example of a SplitToggleChip with a label and the toggle control changed to checkbox:

import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.material.Checkbox
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.SplitToggleChip
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.ToggleChip

var checked by remember { mutableStateOf(true) }
// The primary label should have a maximum 3 lines of text
// and the secondary label should have max 2 lines of text.
SplitToggleChip(
    label = { Text("Split with CheckboxIcon", maxLines = 3, overflow = TextOverflow.Ellipsis) },
    checked = checked,
    toggleControl = {
        Checkbox(
            checked = checked,
            enabled = true,
        )
    },
    onCheckedChange = { checked = it },
    onClick = {
        /* Do something */
    },
    enabled = true,
)

For more information, see the Toggle Chips guide.

Parameters
checked: Boolean

Boolean flag indicating whether this button is currently checked.

onCheckedChange: (Boolean) -> Unit

Callback to be invoked when this buttons checked status is changed.

label: @Composable RowScope.() -> Unit

A slot for providing the chip's main label. The contents are expected to be text which is "start" aligned.

onClick: () -> Unit

Click listener called when the user clicks the main body of the chip, the area behind the labels.

toggleControl: @Composable BoxScope.() -> Unit

A slot for providing the chip's toggle controls(s). Two built-in types of toggle control are supported, see Checkbox and Switch. For RadioButton, use SelectableChip instead. ImageVectors can be obtained from ToggleChipDefaults.switchIcon, ToggleChipDefaults.radioIcon and ToggleChipDefaults.checkboxIcon. In order to correctly render when the Chip is not enabled the icon must set its alpha value to LocalContentAlpha.

modifier: Modifier = Modifier

Modifier to be applied to the chip

secondaryLabel: (@Composable RowScope.() -> Unit)? = null

A slot for providing the chip's secondary label. The contents are expected to be "start" or "center" aligned. label and secondaryLabel contents should be consistently aligned.

colors: SplitToggleChipColors = ToggleChipDefaults.splitToggleChipColors()

SplitToggleChipColors that will be used to resolve the background and content color for this chip in different states, see ToggleChipDefaults.splitToggleChipColors.

enabled: Boolean = true

Controls the enabled state of the chip. When false, this chip will not be clickable

checkedInteractionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip's "toggleable" tap area. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

clickInteractionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip's "clickable" tap area. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

contentPadding: PaddingValues = ToggleChipDefaults.ContentPadding

The spacing values to apply internally between the container and the content

shape: Shape = MaterialTheme.shapes.large

Defines the chip's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme

@Composable
fun Stepper(
    value: Int,
    onValueChange: (Int) -> Unit,
    valueProgression: IntProgression,
    decreaseIcon: @Composable () -> Unit,
    increaseIcon: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    backgroundColor: Color = MaterialTheme.colors.background,
    contentColor: Color = contentColorFor(backgroundColor),
    iconColor: Color = contentColor,
    enableRangeSemantics: Boolean = true,
    content: @Composable BoxScope.() -> Unit
): Unit

Stepper allows users to make a selection from a range of values. It's a full-screen control with increase button on the top, decrease button on the bottom and a slot (expected to have either Text or Chip) in the middle. Value can be increased and decreased by clicking on the increase and decrease buttons. Buttons can have custom icons - decreaseIcon and increaseIcon. Stepper itself doesn't show the current value but can be displayed via the content slot or PositionIndicator if required.

import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.Stepper
import androidx.wear.compose.material.StepperDefaults
import androidx.wear.compose.material.Text

var value by remember { mutableStateOf(2) }
Stepper(
    value = value,
    onValueChange = { value = it },
    increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
    decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
    valueProgression = 1..10
) {
    Text("Value: $value")
}

A number of steps is calculated as the difference between max and min values of valueProgression divided by valueProgression.step - 1. For example, with a range of 100..120 and a step 5, number of steps will be (120-100)/ 5 - 1 = 3. Steps are 100(first), 105, 110, 115, 120(last)

If valueProgression range is not equally divisible by valueProgression.step, then valueProgression.last will be adjusted to the closest divisible value in the range. For example, 1..13 range and a step = 5, steps will be 1(first) , 6 , 11(last)

If value is not equal to any step value, then it will be coerced to the closest step value. However, the value itself will not be changed and onValueChange in this case will not be triggered.

Parameters
value: Int

Current value of the Stepper. If outside of valueProgression provided, value will be coerced to this range.

onValueChange: (Int) -> Unit

Lambda in which value should be updated

valueProgression: IntProgression

Progression of values that Stepper value can take. Consists of rangeStart, rangeEnd and step. Range will be equally divided by step size

decreaseIcon: @Composable () -> Unit

A slot for an icon which is placed on the decrease (bottom) button

increaseIcon: @Composable () -> Unit

A slot for an icon which is placed on the increase (top) button

modifier: Modifier = Modifier

Modifiers for the Stepper layout

backgroundColor: Color = MaterialTheme.colors.background

Color representing the background color for the stepper.

contentColor: Color = contentColorFor(backgroundColor)

Color representing the color for content in the middle.

iconColor: Color = contentColor

Icon tint Color which used by increaseIcon and decreaseIcon that defaults to contentColor, unless specifically overridden.

enableRangeSemantics: Boolean = true

Boolean to decide if default stepper semantics should be enabled. Set to false to disable default stepper range semantics. Alternatively to customize semantics set this value as false and chain new semantics to the modifier.

content: @Composable BoxScope.() -> Unit

Content body for the Stepper.

@Composable
fun Stepper(
    value: Float,
    onValueChange: (Float) -> Unit,
    steps: Int,
    decreaseIcon: @Composable () -> Unit,
    increaseIcon: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    valueRange: ClosedFloatingPointRange<Float> = 0f..(steps + 1).toFloat(),
    backgroundColor: Color = MaterialTheme.colors.background,
    contentColor: Color = contentColorFor(backgroundColor),
    iconColor: Color = contentColor,
    enableRangeSemantics: Boolean = true,
    content: @Composable BoxScope.() -> Unit
): Unit

Stepper allows users to make a selection from a range of values. It's a full-screen control with increase button on the top, decrease button on the bottom and a slot (expected to have either Text or Chip) in the middle. Value can be increased and decreased by clicking on the increase and decrease buttons. Buttons can have custom icons - decreaseIcon and increaseIcon. Step value is calculated as the difference between min and max values divided by steps+1. Stepper itself doesn't show the current value but can be displayed via the content slot or PositionIndicator if required. If value is not equal to any step value, then it will be coerced to the closest step value. However, the value itself will not be changed and onValueChange in this case will not be triggered.

import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.Stepper
import androidx.wear.compose.material.StepperDefaults
import androidx.wear.compose.material.Text

var value by remember { mutableStateOf(2f) }
Stepper(
    value = value,
    onValueChange = { value = it },
    valueRange = 1f..4f,
    increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
    decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
    steps = 7
) {
    Text("Value: $value")
}
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.Stepper
import androidx.wear.compose.material.StepperDefaults
import androidx.wear.compose.material.Text

var value by remember { mutableStateOf(2f) }
Stepper(
    value = value,
    onValueChange = { value = it },
    valueRange = 1f..4f,
    increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
    decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
    steps = 7,
    enableRangeSemantics = false
) {
    Text("Value: $value")
}
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.Stepper
import androidx.wear.compose.material.StepperDefaults
import androidx.wear.compose.material.Text

var value by remember { mutableStateOf(2f) }
val valueRange = 1f..4f
val onValueChange = { i: Float -> value = i }
val steps = 7

Stepper(
    value = value,
    onValueChange = onValueChange,
    valueRange = valueRange,
    modifier = Modifier.customSemantics(value, true, onValueChange, valueRange, steps),
    increaseIcon = { Icon(StepperDefaults.Increase, "Increase") },
    decreaseIcon = { Icon(StepperDefaults.Decrease, "Decrease") },
    steps = steps,
    enableRangeSemantics = false
) {
    Text("Value: $value")
}
Parameters
value: Float

Current value of the Stepper. If outside of valueRange provided, value will be coerced to this range.

onValueChange: (Float) -> Unit

Lambda in which value should be updated

steps: Int

Specifies the number of discrete values, excluding min and max values, evenly distributed across the whole value range. Must not be negative. If 0, stepper will have only min and max values and no steps in between

decreaseIcon: @Composable () -> Unit

A slot for an icon which is placed on the decrease (bottom) button

increaseIcon: @Composable () -> Unit

A slot for an icon which is placed on the increase (top) button

modifier: Modifier = Modifier

Modifiers for the Stepper layout

valueRange: ClosedFloatingPointRange<Float> = 0f..(steps + 1).toFloat()

Range of values that Stepper value can take. Passed value will be coerced to this range

backgroundColor: Color = MaterialTheme.colors.background

Color representing the background color for the stepper.

contentColor: Color = contentColorFor(backgroundColor)

Color representing the color for content in the middle.

iconColor: Color = contentColor

Icon tint Color which used by increaseIcon and decreaseIcon that defaults to contentColor, unless specifically overridden.

enableRangeSemantics: Boolean = true

Boolean to decide if range semantics should be enabled. Set to false to disable default stepper range semantics. Alternatively to customize semantics set this value as false and chain new semantics to the modifier.

content: @Composable BoxScope.() -> Unit

Content body for the Stepper.

@Composable
fun SwipeToDismissBox(
    state: SwipeToDismissBoxState,
    modifier: Modifier = Modifier,
    backgroundScrimColor: Color = MaterialTheme.colors.background,
    contentScrimColor: Color = MaterialTheme.colors.background,
    backgroundKey: Any = SwipeToDismissKeys.Background,
    contentKey: Any = SwipeToDismissKeys.Content,
    hasBackground: Boolean = true,
    content: @Composable BoxScope.(isBackground: Boolean) -> Unit
): Unit

Wear Material SwipeToDismissBox that handles the swipe-to-dismiss gesture. Takes a single slot for the background (only displayed during the swipe gesture) and the foreground content.

Example of a SwipeToDismissBox with stateful composables:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.SwipeToDismissValue
import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.SplitToggleChip
import androidx.wear.compose.material.SwipeToDismissBox
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.ToggleChipDefaults

// State for managing a 2-level navigation hierarchy between
// MainScreen and ItemScreen composables.
// Alternatively, use SwipeDismissableNavHost from wear.compose.navigation.
var showMainScreen by remember { mutableStateOf(true) }
val saveableStateHolder = rememberSaveableStateHolder()

// Swipe gesture dismisses ItemScreen to return to MainScreen.
val state = rememberSwipeToDismissBoxState()
LaunchedEffect(state.currentValue) {
    if (state.currentValue == SwipeToDismissValue.Dismissed) {
        state.snapTo(SwipeToDismissValue.Default)
        showMainScreen = !showMainScreen
    }
}

// Hierarchy is ListScreen -> ItemScreen, so we show ListScreen as the background behind
// the ItemScreen, otherwise there's no background to show.
SwipeToDismissBox(
    state = state,
    hasBackground = !showMainScreen,
    backgroundKey = if (!showMainScreen) "MainKey" else "Background",
    contentKey = if (showMainScreen) "MainKey" else "ItemKey",
) { isBackground ->
    if (isBackground || showMainScreen) {
        // Best practice would be to use State Hoisting and leave this composable stateless.
        // Here, we want to support MainScreen being shown from different destinations
        // (either in the foreground or in the background during swiping) - that can be achieved
        // using SaveableStateHolder and rememberSaveable as shown below.
        saveableStateHolder.SaveableStateProvider(
            key = "MainKey",
            content = {
                // Composable that maintains its own state
                // and can be shown in foreground or background.
                val checked = rememberSaveable { mutableStateOf(true) }
                Column(
                    modifier =
                        Modifier.fillMaxSize().padding(horizontal = 8.dp, vertical = 8.dp),
                    verticalArrangement =
                        Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
                ) {
                    SplitToggleChip(
                        checked = checked.value,
                        label = { Text("Item details") },
                        modifier = Modifier.height(40.dp),
                        onCheckedChange = { v -> checked.value = v },
                        onClick = { showMainScreen = false },
                        toggleControl = {
                            Icon(
                                imageVector =
                                    ToggleChipDefaults.checkboxIcon(checked = checked.value),
                                contentDescription = null,
                            )
                        }
                    )
                }
            }
        )
    } else {
        Column(
            modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.primary),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            Text("Show details here...", color = MaterialTheme.colors.onPrimary)
            Text("Swipe right to dismiss", color = MaterialTheme.colors.onPrimary)
        }
    }
}

Example of using Modifier.edgeSwipeToDismiss with SwipeToDismissBox

import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.wear.compose.foundation.edgeSwipeToDismiss
import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.SwipeToDismissBox
import androidx.wear.compose.material.Text

val state = rememberSwipeToDismissBoxState()

// When using Modifier.edgeSwipeToDismiss, it is required that the element on which the
// modifier applies exists within a SwipeToDismissBox which shares the same state.
SwipeToDismissBox(state = state, onDismissed = navigateBack) { isBackground ->
    val horizontalScrollState = rememberScrollState(0)
    if (isBackground) {
        Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.secondaryVariant))
    } else {
        Box(modifier = Modifier.fillMaxSize()) {
            Text(
                modifier =
                    Modifier.align(Alignment.Center)
                        .edgeSwipeToDismiss(state)
                        .horizontalScroll(horizontalScrollState),
                text =
                    "This text can be scrolled horizontally - to dismiss, swipe " +
                        "right from the left edge of the screen (called Edge Swiping)",
            )
        }
    }
}

For more information, see the Swipe to dismiss guide.

Parameters
state: SwipeToDismissBoxState

State containing information about ongoing swipe or animation.

modifier: Modifier = Modifier

Optional Modifier for this component.

backgroundScrimColor: Color = MaterialTheme.colors.background

Color for background scrim

contentScrimColor: Color = MaterialTheme.colors.background

Optional Color used for the scrim over the content composable during the swipe gesture.

backgroundKey: Any = SwipeToDismissKeys.Background

Optional key which identifies the content currently composed in the content block when isBackground == true. Provide the backgroundKey if your background content will be displayed as a foreground after the swipe animation ends (as is common when SwipeToDismissBox is used for the navigation). This allows remembered state to be correctly moved between background and foreground.

contentKey: Any = SwipeToDismissKeys.Content

Optional key which identifies the content currently composed in the content block when isBackground == false. See backgroundKey.

hasBackground: Boolean = true

Optional Boolean used to indicate if the content has no background, in which case the swipe gesture is disabled (since there is no parent destination).

content: @Composable BoxScope.(isBackground: Boolean) -> Unit

Slot for content, with the isBackground parameter enabling content to be displayed behind the foreground content - the background is normally hidden, is shown behind a scrim during the swipe gesture, and is shown without scrim once the finger passes the swipe-to-dismiss threshold.

@Composable
fun SwipeToDismissBox(
    state: SwipeToDismissBoxState,
    modifier: Modifier = Modifier,
    backgroundScrimColor: Color = MaterialTheme.colors.background,
    contentScrimColor: Color = MaterialTheme.colors.background,
    backgroundKey: Any = SwipeToDismissKeys.Background,
    contentKey: Any = SwipeToDismissKeys.Content,
    hasBackground: Boolean = true,
    content: @Composable BoxScope.(isBackground: Boolean) -> Unit
): Unit

Wear Material SwipeToDismissBox that handles the swipe-to-dismiss gesture. Takes a single slot for the background (only displayed during the swipe gesture) and the foreground content.

Example of a SwipeToDismissBox with stateful composables:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.saveable.rememberSaveableStateHolder
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.SwipeToDismissValue
import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.SplitToggleChip
import androidx.wear.compose.material.SwipeToDismissBox
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.ToggleChipDefaults

// State for managing a 2-level navigation hierarchy between
// MainScreen and ItemScreen composables.
// Alternatively, use SwipeDismissableNavHost from wear.compose.navigation.
var showMainScreen by remember { mutableStateOf(true) }
val saveableStateHolder = rememberSaveableStateHolder()

// Swipe gesture dismisses ItemScreen to return to MainScreen.
val state = rememberSwipeToDismissBoxState()
LaunchedEffect(state.currentValue) {
    if (state.currentValue == SwipeToDismissValue.Dismissed) {
        state.snapTo(SwipeToDismissValue.Default)
        showMainScreen = !showMainScreen
    }
}

// Hierarchy is ListScreen -> ItemScreen, so we show ListScreen as the background behind
// the ItemScreen, otherwise there's no background to show.
SwipeToDismissBox(
    state = state,
    hasBackground = !showMainScreen,
    backgroundKey = if (!showMainScreen) "MainKey" else "Background",
    contentKey = if (showMainScreen) "MainKey" else "ItemKey",
) { isBackground ->
    if (isBackground || showMainScreen) {
        // Best practice would be to use State Hoisting and leave this composable stateless.
        // Here, we want to support MainScreen being shown from different destinations
        // (either in the foreground or in the background during swiping) - that can be achieved
        // using SaveableStateHolder and rememberSaveable as shown below.
        saveableStateHolder.SaveableStateProvider(
            key = "MainKey",
            content = {
                // Composable that maintains its own state
                // and can be shown in foreground or background.
                val checked = rememberSaveable { mutableStateOf(true) }
                Column(
                    modifier =
                        Modifier.fillMaxSize().padding(horizontal = 8.dp, vertical = 8.dp),
                    verticalArrangement =
                        Arrangement.spacedBy(4.dp, Alignment.CenterVertically),
                ) {
                    SplitToggleChip(
                        checked = checked.value,
                        label = { Text("Item details") },
                        modifier = Modifier.height(40.dp),
                        onCheckedChange = { v -> checked.value = v },
                        onClick = { showMainScreen = false },
                        toggleControl = {
                            Icon(
                                imageVector =
                                    ToggleChipDefaults.checkboxIcon(checked = checked.value),
                                contentDescription = null,
                            )
                        }
                    )
                }
            }
        )
    } else {
        Column(
            modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.primary),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            Text("Show details here...", color = MaterialTheme.colors.onPrimary)
            Text("Swipe right to dismiss", color = MaterialTheme.colors.onPrimary)
        }
    }
}

Example of using Modifier.edgeSwipeToDismiss with SwipeToDismissBox

import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.wear.compose.foundation.edgeSwipeToDismiss
import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.SwipeToDismissBox
import androidx.wear.compose.material.Text

val state = rememberSwipeToDismissBoxState()

// When using Modifier.edgeSwipeToDismiss, it is required that the element on which the
// modifier applies exists within a SwipeToDismissBox which shares the same state.
SwipeToDismissBox(state = state, onDismissed = navigateBack) { isBackground ->
    val horizontalScrollState = rememberScrollState(0)
    if (isBackground) {
        Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.secondaryVariant))
    } else {
        Box(modifier = Modifier.fillMaxSize()) {
            Text(
                modifier =
                    Modifier.align(Alignment.Center)
                        .edgeSwipeToDismiss(state)
                        .horizontalScroll(horizontalScrollState),
                text =
                    "This text can be scrolled horizontally - to dismiss, swipe " +
                        "right from the left edge of the screen (called Edge Swiping)",
            )
        }
    }
}

For more information, see the Swipe to dismiss guide.

Parameters
state: SwipeToDismissBoxState

State containing information about ongoing swipe or animation.

modifier: Modifier = Modifier

Optional Modifier for this component.

backgroundScrimColor: Color = MaterialTheme.colors.background

Color for background scrim

contentScrimColor: Color = MaterialTheme.colors.background

Optional Color used for the scrim over the content composable during the swipe gesture.

backgroundKey: Any = SwipeToDismissKeys.Background

Optional key which identifies the content currently composed in the content block when isBackground == true. Provide the backgroundKey if your background content will be displayed as a foreground after the swipe animation ends (as is common when SwipeToDismissBox is used for the navigation). This allows remembered state to be correctly moved between background and foreground.

contentKey: Any = SwipeToDismissKeys.Content

Optional key which identifies the content currently composed in the content block when isBackground == false. See backgroundKey.

hasBackground: Boolean = true

Optional Boolean used to indicate if the content has no background, in which case the swipe gesture is disabled (since there is no parent destination).

content: @Composable BoxScope.(isBackground: Boolean) -> Unit

Slot for content, with the isBackground parameter enabling content to be displayed behind the foreground content - the background is normally hidden, is shown behind a scrim during the swipe gesture, and is shown without scrim once the finger passes the swipe-to-dismiss threshold.

@Composable
fun SwipeToDismissBox(
    onDismissed: () -> Unit,
    modifier: Modifier = Modifier,
    state: SwipeToDismissBoxState = androidx.wear.compose.foundation.rememberSwipeToDismissBoxState(),
    backgroundScrimColor: Color = MaterialTheme.colors.background,
    contentScrimColor: Color = MaterialTheme.colors.background,
    backgroundKey: Any = SwipeToDismissKeys.Background,
    contentKey: Any = SwipeToDismissKeys.Content,
    hasBackground: Boolean = true,
    content: @Composable BoxScope.(isBackground: Boolean) -> Unit
): Unit

Wear Material SwipeToDismissBox that handles the swipe-to-dismiss gesture. This overload takes an onDismissed parameter which is used to execute a command when the swipe to dismiss has completed, such as navigating to another screen.

Example of a simple SwipeToDismissBox:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.SwipeToDismissBox
import androidx.wear.compose.material.Text

val state = rememberSwipeToDismissBoxState()
SwipeToDismissBox(state = state, onDismissed = navigateBack) { isBackground ->
    if (isBackground) {
        Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.secondaryVariant))
    } else {
        Column(
            modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.primary),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            Text("Swipe right to dismiss", color = MaterialTheme.colors.onPrimary)
        }
    }
}

Example of using Modifier.edgeSwipeToDismiss with SwipeToDismissBox

import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.wear.compose.foundation.edgeSwipeToDismiss
import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.SwipeToDismissBox
import androidx.wear.compose.material.Text

val state = rememberSwipeToDismissBoxState()

// When using Modifier.edgeSwipeToDismiss, it is required that the element on which the
// modifier applies exists within a SwipeToDismissBox which shares the same state.
SwipeToDismissBox(state = state, onDismissed = navigateBack) { isBackground ->
    val horizontalScrollState = rememberScrollState(0)
    if (isBackground) {
        Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.secondaryVariant))
    } else {
        Box(modifier = Modifier.fillMaxSize()) {
            Text(
                modifier =
                    Modifier.align(Alignment.Center)
                        .edgeSwipeToDismiss(state)
                        .horizontalScroll(horizontalScrollState),
                text =
                    "This text can be scrolled horizontally - to dismiss, swipe " +
                        "right from the left edge of the screen (called Edge Swiping)",
            )
        }
    }
}

For more information, see the Swipe to dismiss guide.

Parameters
onDismissed: () -> Unit

Executes when the swipe to dismiss has completed.

modifier: Modifier = Modifier

Optional Modifier for this component.

state: SwipeToDismissBoxState = androidx.wear.compose.foundation.rememberSwipeToDismissBoxState()

State containing information about ongoing swipe or animation.

backgroundScrimColor: Color = MaterialTheme.colors.background

Color for background scrim

contentScrimColor: Color = MaterialTheme.colors.background

Optional Color used for the scrim over the content composable during the swipe gesture.

backgroundKey: Any = SwipeToDismissKeys.Background

Optional key which identifies the content currently composed in the content block when isBackground == true. Provide the backgroundKey if your background content will be displayed as a foreground after the swipe animation ends (as is common when SwipeToDismissBox is used for the navigation). This allows remembered state to be correctly moved between background and foreground.

contentKey: Any = SwipeToDismissKeys.Content

Optional key which identifies the content currently composed in the content block when isBackground == false. See backgroundKey.

hasBackground: Boolean = true

Optional Boolean used to indicate if the content has no background, in which case the swipe gesture is disabled (since there is no parent destination).

content: @Composable BoxScope.(isBackground: Boolean) -> Unit

Slot for content, with the isBackground parameter enabling content to be displayed behind the foreground content - the background is normally hidden, is shown behind a scrim during the swipe gesture, and is shown without scrim once the finger passes the swipe-to-dismiss threshold.

SwipeToRevealCard

@ExperimentalWearMaterialApi
@Composable
fun SwipeToRevealCard(
    primaryAction: @Composable RevealScope.() -> Unit,
    revealState: RevealState,
    onFullSwipe: () -> Unit,
    modifier: Modifier = Modifier,
    secondaryAction: (@Composable RevealScope.() -> Unit)? = null,
    undoPrimaryAction: (@Composable RevealScope.() -> Unit)? = null,
    undoSecondaryAction: (@Composable RevealScope.() -> Unit)? = null,
    colors: SwipeToRevealActionColors = SwipeToRevealDefaults.actionColors(),
    shape: Shape = SwipeToRevealDefaults.CardActionShape,
    content: @Composable () -> Unit
): Unit

SwipeToReveal Material composable for Cards. This adds the option to configure up to two additional actions on the Card: a mandatory primaryAction and an optional secondaryAction. These actions are initially hidden and revealed only when the content is swiped. These additional actions can be triggered by clicking on them after they are revealed. It is recommended to trigger primaryAction on full swipe of the content.

For actions like "Delete", consider adding undoPrimaryAction (displayed when the primaryAction is activated) and/or undoSecondaryAction (displayed when the secondaryAction is activated). Adding undo composables allow users to undo the action that they just performed.

Example of SwipeToRevealCard with primary and secondary actions

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.semantics.CustomAccessibilityAction
import androidx.compose.ui.semantics.customActions
import androidx.compose.ui.semantics.semantics
import androidx.wear.compose.foundation.edgeSwipeToDismiss
import androidx.wear.compose.foundation.rememberRevealState
import androidx.wear.compose.material.AppCard
import androidx.wear.compose.material.CardDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.SwipeToRevealCard
import androidx.wear.compose.material.SwipeToRevealDefaults
import androidx.wear.compose.material.SwipeToRevealPrimaryAction
import androidx.wear.compose.material.SwipeToRevealSecondaryAction
import androidx.wear.compose.material.SwipeToRevealUndoAction
import androidx.wear.compose.material.Text

val revealState = rememberRevealState()
SwipeToRevealCard(
    revealState = revealState,
    modifier =
        Modifier.fillMaxWidth()
            // Use edgeSwipeToDismiss to allow SwipeToDismissBox to capture swipe events
            .edgeSwipeToDismiss(swipeToDismissBoxState)
            .semantics {
                // Use custom actions to make the primary and secondary actions accessible
                customActions =
                    listOf(
                        CustomAccessibilityAction("Delete") {
                            /* Add the primary action click handler here */
                            true
                        },
                        CustomAccessibilityAction("More Options") {
                            /* Add the secondary click handler here */
                            true
                        }
                    )
            },
    primaryAction = {
        SwipeToRevealPrimaryAction(
            revealState = revealState,
            icon = { Icon(SwipeToRevealDefaults.Delete, "Delete") },
            label = { Text("Delete") },
            onClick = { /* Add the click handler here */ }
        )
    },
    secondaryAction = {
        SwipeToRevealSecondaryAction(
            revealState = revealState,
            onClick = { /* Add the click handler here */ }
        ) {
            Icon(SwipeToRevealDefaults.MoreOptions, "More Options")
        }
    },
    undoPrimaryAction = {
        SwipeToRevealUndoAction(
            revealState = revealState,
            label = { Text("Undo") },
            onClick = { /* Add the undo handler for primary action */ }
        )
    },
    undoSecondaryAction = {
        SwipeToRevealUndoAction(
            revealState = revealState,
            label = { Text("Undo") },
            onClick = { /* Add the undo handler for secondary action */ }
        )
    },
    onFullSwipe = { /* Add the full swipe handler here */ }
) {
    AppCard(
        onClick = { /* Add the Card click handler */ },
        appName = { Text("AppName") },
        appImage = {
            Icon(
                painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
                contentDescription = "airplane",
                modifier =
                    Modifier.size(CardDefaults.AppImageSize)
                        .wrapContentSize(align = Alignment.Center),
            )
        },
        title = { Text("AppCard") },
        time = { Text("now") }
    ) {
        Text("Basic card with SwipeToReveal actions")
    }
}
Parameters
primaryAction: @Composable RevealScope.() -> Unit

A composable to describe the primary action when swiping. The action will be triggered on clicking the action. See SwipeToRevealPrimaryAction.

revealState: RevealState

RevealState of the SwipeToReveal

onFullSwipe: () -> Unit

A lambda which will be triggered on full swipe from either of the anchors. We recommend to keep this similar to primary action click action. This sets the RevealState.lastActionType to RevealActionType.PrimaryAction.

modifier: Modifier = Modifier

Modifier to be applied on the composable

secondaryAction: (@Composable RevealScope.() -> Unit)? = null

A composable to describe the contents of secondary action.The action will be triggered on clicking the action. See SwipeToRevealSecondaryAction

undoPrimaryAction: (@Composable RevealScope.() -> Unit)? = null

A composable to describe the contents of undo action when the primary action was triggered. See SwipeToRevealUndoAction

undoSecondaryAction: (@Composable RevealScope.() -> Unit)? = null

A composable to describe the contents of undo action when secondary action was triggered. See SwipeToRevealUndoAction

colors: SwipeToRevealActionColors = SwipeToRevealDefaults.actionColors()

An instance of SwipeToRevealActionColors to describe the colors of actions. See SwipeToRevealDefaults.actionColors.

shape: Shape = SwipeToRevealDefaults.CardActionShape

The shape of primary and secondary action composables. Recommended shape for cards is SwipeToRevealDefaults.CardActionShape.

content: @Composable () -> Unit

The initial content shown prior to the swipe-to-reveal gesture.

See also
SwipeToReveal

SwipeToRevealChip

@ExperimentalWearMaterialApi
@Composable
fun SwipeToRevealChip(
    primaryAction: @Composable RevealScope.() -> Unit,
    revealState: RevealState,
    onFullSwipe: () -> Unit,
    modifier: Modifier = Modifier,
    secondaryAction: (@Composable RevealScope.() -> Unit)? = null,
    undoPrimaryAction: (@Composable RevealScope.() -> Unit)? = null,
    undoSecondaryAction: (@Composable RevealScope.() -> Unit)? = null,
    colors: SwipeToRevealActionColors = SwipeToRevealDefaults.actionColors(),
    shape: Shape = MaterialTheme.shapes.small,
    content: @Composable () -> Unit
): Unit

SwipeToReveal Material composable for Chips. This adds the option to configure up to two additional actions on the Chip: a mandatory primaryAction and an optional secondaryAction. These actions are initially hidden and revealed only when the content is swiped. These additional actions can be triggered by clicking on them after they are revealed. It is recommended to trigger primaryAction on full swipe of the content.

For actions like "Delete", consider adding undoPrimaryAction (displayed when the primaryAction is activated) and/or undoSecondaryAction (displayed when the secondaryAction is activated). Adding undo composables allow users to undo the action that they just performed.

Example of SwipeToRevealChip with primary and secondary actions

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.CustomAccessibilityAction
import androidx.compose.ui.semantics.customActions
import androidx.compose.ui.semantics.semantics
import androidx.wear.compose.foundation.edgeSwipeToDismiss
import androidx.wear.compose.foundation.rememberRevealState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.SwipeToRevealChip
import androidx.wear.compose.material.SwipeToRevealDefaults
import androidx.wear.compose.material.SwipeToRevealPrimaryAction
import androidx.wear.compose.material.SwipeToRevealSecondaryAction
import androidx.wear.compose.material.SwipeToRevealUndoAction
import androidx.wear.compose.material.Text

val revealState = rememberRevealState()
SwipeToRevealChip(
    revealState = revealState,
    modifier =
        Modifier.fillMaxWidth()
            // Use edgeSwipeToDismiss to allow SwipeToDismissBox to capture swipe events
            .edgeSwipeToDismiss(swipeToDismissBoxState)
            .semantics {
                // Use custom actions to make the primary and secondary actions accessible
                customActions =
                    listOf(
                        CustomAccessibilityAction("Delete") {
                            /* Add the primary action click handler here */
                            true
                        },
                        CustomAccessibilityAction("More Options") {
                            /* Add the secondary click handler here */
                            true
                        }
                    )
            },
    primaryAction = {
        SwipeToRevealPrimaryAction(
            revealState = revealState,
            icon = { Icon(SwipeToRevealDefaults.Delete, "Delete") },
            label = { Text("Delete") },
            onClick = { /* Add the click handler here */ }
        )
    },
    secondaryAction = {
        SwipeToRevealSecondaryAction(
            revealState = revealState,
            onClick = { /* Add the click handler here */ }
        ) {
            Icon(SwipeToRevealDefaults.MoreOptions, "More Options")
        }
    },
    undoPrimaryAction = {
        SwipeToRevealUndoAction(
            revealState = revealState,
            label = { Text("Undo") },
            onClick = { /* Add the undo handler for primary action */ }
        )
    },
    undoSecondaryAction = {
        SwipeToRevealUndoAction(
            revealState = revealState,
            label = { Text("Undo") },
            onClick = { /* Add the undo handler for secondary action */ }
        )
    },
    onFullSwipe = { /* Add the full swipe handler here */ }
) {
    Chip(
        modifier = Modifier.fillMaxWidth(),
        onClick = { /* Add the chip click handler here */ },
        colors = ChipDefaults.primaryChipColors(),
        border = ChipDefaults.outlinedChipBorder(),
        label = { Text("SwipeToReveal Chip", maxLines = 3) }
    )
}
Parameters
primaryAction: @Composable RevealScope.() -> Unit

A composable to describe the primary action when swiping. The action will be triggered on clicking the action. See SwipeToRevealPrimaryAction.

revealState: RevealState

RevealState of the SwipeToReveal

onFullSwipe: () -> Unit

A lambda which will be triggered on full swipe from either of the anchors. We recommend to keep this similar to primary action click action. This sets the RevealState.lastActionType to RevealActionType.PrimaryAction.

modifier: Modifier = Modifier

Modifier to be applied on the composable

secondaryAction: (@Composable RevealScope.() -> Unit)? = null

A composable to describe the contents of secondary action. The action will be triggered on clicking the action. See SwipeToRevealSecondaryAction

undoPrimaryAction: (@Composable RevealScope.() -> Unit)? = null

A composable to describe the contents of undo action when the primary action was triggered. See SwipeToRevealUndoAction

undoSecondaryAction: (@Composable RevealScope.() -> Unit)? = null

composable to describe the contents of undo action when secondary action was triggered. See SwipeToRevealUndoAction

colors: SwipeToRevealActionColors = SwipeToRevealDefaults.actionColors()

An instance of SwipeToRevealActionColors to describe the colors of actions. See SwipeToRevealDefaults.actionColors.

shape: Shape = MaterialTheme.shapes.small

The shape of primary and secondary action composables. Recommended shape for chips is Shapes.small.

content: @Composable () -> Unit

The initial content shown prior to the swipe-to-reveal gesture.

See also
SwipeToReveal
@Composable
fun Switch(
    checked: Boolean,
    modifier: Modifier = Modifier,
    colors: SwitchColors = SwitchDefaults.colors(),
    enabled: Boolean = true,
    onCheckedChange: ((Boolean) -> Unit)? = null,
    interactionSource: MutableInteractionSource? = null
): Unit

Switch provides an animated switch for use as a toggle control in ToggleChip or SplitToggleChip.

Example of a ToggleChip with Switch toggle control:

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.Switch
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.ToggleChip
import androidx.wear.compose.material.ToggleChipDefaults

var checked by remember { mutableStateOf(true) }
// The primary label should have a maximum 3 lines of text
// and the secondary label should have max 2 lines of text.
ToggleChip(
    label = { Text("SwitchIcon", maxLines = 3, overflow = TextOverflow.Ellipsis) },
    secondaryLabel = {
        Text("With secondary label", maxLines = 2, overflow = TextOverflow.Ellipsis)
    },
    checked = checked,
    // For Switch  toggle controls the Wear Material UX guidance is to set the
    // unselected toggle control color to ToggleChipDefaults.switchUncheckedIconColor()
    // rather than the default.
    colors =
        ToggleChipDefaults.toggleChipColors(
            uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
        ),
    toggleControl = {
        Switch(
            checked = checked,
            enabled = true,
        )
    },
    onCheckedChange = { checked = it },
    appIcon = {
        Icon(
            painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
            contentDescription = "airplane",
            modifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center),
        )
    },
    enabled = true,
)
Parameters
checked: Boolean

Boolean flag indicating whether this switch is currently toggled on.

modifier: Modifier = Modifier

Modifier to be applied to the switch. This can be used to provide a content description for accessibility.

colors: SwitchColors = SwitchDefaults.colors()

SwitchColors from which the colors of the thumb and track will be obtained.

enabled: Boolean = true

Boolean flag indicating the enabled state of the Switch (affects the color).

onCheckedChange: ((Boolean) -> Unit)? = null

Callback to be invoked when Switch is clicked. If null, then this is passive and relies entirely on a higher-level component to control the state (such as ToggleChip or SplitToggleChip).

interactionSource: MutableInteractionSource? = null

When also providing onCheckedChange, an optional hoisted MutableInteractionSource for observing and emitting Interactions for this switch. You can use this to change the switch's appearance or preview the switch in different states. Note that if null is provided, interactions will still happen internally.

@Composable
fun Text(
    text: String,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
    textAlign: TextAlign? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    overflow: TextOverflow = TextOverflow.Clip,
    softWrap: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    minLines: Int = 1,
    onTextLayout: (TextLayoutResult) -> Unit = {},
    style: TextStyle = LocalTextStyle.current
): Unit

High level element that displays text and provides semantics / accessibility information.

The default style uses the LocalTextStyle provided by the MaterialTheme / components. If you are setting your own style, you may want to consider first retrieving LocalTextStyle, and using TextStyle.copy to keep any theme defined attributes, only modifying the specific attributes you want to override.

For ease of use, commonly used parameters from TextStyle are also present here. The order of precedence is as follows:

  • If a parameter is explicitly set here (i.e, it is not null or TextUnit.Unspecified), then this parameter will always be used.

  • If a parameter is not set, (null or TextUnit.Unspecified), then the corresponding value from style will be used instead.

Additionally, for color, if color is not set, and style does not have a color, then LocalContentColor will be used with an alpha of LocalContentAlpha- this allows this Text or element containing this Text to adapt to different background colors and still maintain contrast and accessibility.

Parameters
text: String

The text to be displayed.

modifier: Modifier = Modifier

Modifier to apply to this layout node.

color: Color = Color.Unspecified

Color to apply to the text. If Color.Unspecified, and style has no color set, this will be LocalContentColor.

fontSize: TextUnit = TextUnit.Unspecified

The size of glyphs to use when painting the text. See TextStyle.fontSize.

fontStyle: FontStyle? = null

The typeface variant to use when drawing the letters (e.g., italic). See TextStyle.fontStyle.

fontWeight: FontWeight? = null

The typeface thickness to use when painting the text (e.g., FontWeight.Bold).

fontFamily: FontFamily? = null

The font family to be used when rendering the text. See TextStyle.fontFamily.

letterSpacing: TextUnit = TextUnit.Unspecified

The amount of space to add between each letter. See TextStyle.letterSpacing.

textDecoration: TextDecoration? = null

The decorations to paint on the text (e.g., an underline). See TextStyle.textDecoration.

textAlign: TextAlign? = null

The alignment of the text within the lines of the paragraph. See TextStyle.textAlign.

lineHeight: TextUnit = TextUnit.Unspecified

Line height for the Paragraph in TextUnit unit, e.g. SP or EM. See TextStyle.lineHeight.

overflow: TextOverflow = TextOverflow.Clip

How visual overflow should be handled.

softWrap: Boolean = true

Whether the text should break at soft line breaks. If false, the glyphs in the text will be positioned as if there was unlimited horizontal space. If softWrap is false, overflow and TextAlign may have unexpected effects.

maxLines: Int = Int.MAX_VALUE

An optional maximum number of lines for the text to span, wrapping if necessary. If the text exceeds the given number of lines, it will be truncated according to overflow and softWrap. If it is not null, then it must be greater than zero.

minLines: Int = 1

The minimum height in terms of minimum number of visible lines. It is required that 1 <= minLines<= maxLines.

onTextLayout: (TextLayoutResult) -> Unit = {}

Callback that is executed when a new text layout is calculated. A TextLayoutResult object that callback provides contains paragraph information, size of the text, baselines and other details. The callback can be used to add additional decoration or functionality to the text. For example, to draw selection around the text.

style: TextStyle = LocalTextStyle.current

Style configuration for the text such as color, font, line height etc.

@Composable
fun Text(
    text: AnnotatedString,
    modifier: Modifier = Modifier,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontStyle: FontStyle? = null,
    fontWeight: FontWeight? = null,
    fontFamily: FontFamily? = null,
    letterSpacing: TextUnit = TextUnit.Unspecified,
    textDecoration: TextDecoration? = null,
    textAlign: TextAlign? = null,
    lineHeight: TextUnit = TextUnit.Unspecified,
    overflow: TextOverflow = TextOverflow.Clip,
    softWrap: Boolean = true,
    maxLines: Int = Int.MAX_VALUE,
    minLines: Int = 1,
    inlineContent: Map<StringInlineTextContent> = mapOf(),
    onTextLayout: (TextLayoutResult) -> Unit = {},
    style: TextStyle = LocalTextStyle.current
): Unit

High level element that displays text and provides semantics / accessibility information.

The default style uses the LocalTextStyle provided by the MaterialTheme / components. If you are setting your own style, you may want to consider first retrieving LocalTextStyle, and using TextStyle.copy to keep any theme defined attributes, only modifying the specific attributes you want to override.

For ease of use, commonly used parameters from TextStyle are also present here. The order of precedence is as follows:

  • If a parameter is explicitly set here (i.e, it is not null or TextUnit.Unspecified), then this parameter will always be used.

  • If a parameter is not set, (null or TextUnit.Unspecified), then the corresponding value from style will be used instead.

Additionally, for color, if color is not set, and style does not have a color, then LocalContentColor will be used with an alpha of LocalContentAlpha- this allows this Text or element containing this Text to adapt to different background colors and still maintain contrast and accessibility.

Parameters
text: AnnotatedString

The text to be displayed, where AnnotatedString allows multiple styles to be used.

modifier: Modifier = Modifier

Modifier to apply to this layout node.

color: Color = Color.Unspecified

Color to apply to the text. If Color.Unspecified, and style has no color set, this will be LocalContentColor.

fontSize: TextUnit = TextUnit.Unspecified

The size of glyphs to use when painting the text. See TextStyle.fontSize.

fontStyle: FontStyle? = null

The typeface variant to use when drawing the letters (e.g., italic). See TextStyle.fontStyle.

fontWeight: FontWeight? = null

The typeface thickness to use when painting the text (e.g., FontWeight.Bold).

fontFamily: FontFamily? = null

The font family to be used when rendering the text. See TextStyle.fontFamily.

letterSpacing: TextUnit = TextUnit.Unspecified

The amount of space to add between each letter. See TextStyle.letterSpacing.

textDecoration: TextDecoration? = null

The decorations to paint on the text (e.g., an underline). See TextStyle.textDecoration.

textAlign: TextAlign? = null

The alignment of the text within the lines of the paragraph. See TextStyle.textAlign.

lineHeight: TextUnit = TextUnit.Unspecified

Line height for the Paragraph in TextUnit unit, e.g. SP or EM. See TextStyle.lineHeight.

overflow: TextOverflow = TextOverflow.Clip

How visual overflow should be handled.

softWrap: Boolean = true

Whether the text should break at soft line breaks. If false, the glyphs in the text will be positioned as if there was unlimited horizontal space. If softWrap is false, overflow and TextAlign may have unexpected effects.

maxLines: Int = Int.MAX_VALUE

An optional maximum number of lines for the text to span, wrapping if necessary. If the text exceeds the given number of lines, it will be truncated according to overflow and softWrap. If it is not null, then it must be greater than zero.

minLines: Int = 1

The minimum height in terms of minimum number of visible lines. It is required that 1 <= minLines<= maxLines.

inlineContent: Map<StringInlineTextContent> = mapOf()

A map store composables that replaces certain ranges of the text. It's used to insert composables into text layout. Check InlineTextContent for more information.

onTextLayout: (TextLayoutResult) -> Unit = {}

Callback that is executed when a new text layout is calculated. A TextLayoutResult object that callback provides contains paragraph information, size of the text, baselines and other details. The callback can be used to add additional decoration or functionality to the text. For example, to draw selection around the text.

style: TextStyle = LocalTextStyle.current

Style configuration for the text such as color, font, line height etc.

@Composable
fun TimeText(
    modifier: Modifier = Modifier,
    timeSource: TimeSource = TimeTextDefaults.timeSource(timeFormat()),
    timeTextStyle: TextStyle = TimeTextDefaults.timeTextStyle(),
    contentPadding: PaddingValues = TimeTextDefaults.ContentPadding,
    startLinearContent: (@Composable () -> Unit)? = null,
    startCurvedContent: (CurvedScope.() -> Unit)? = null,
    endLinearContent: (@Composable () -> Unit)? = null,
    endCurvedContent: (CurvedScope.() -> Unit)? = null,
    textLinearSeparator: @Composable () -> Unit = { TextSeparator(textStyle = timeTextStyle) },
    textCurvedSeparator: CurvedScope.() -> Unit = { CurvedTextSeparator(curvedTextStyle = CurvedTextStyle(timeTextStyle)) }
): Unit

Layout to show the current time and a label at the top of the screen. If device has a round screen, then the time will be curved along the top edge of the screen, if rectangular - then the text and the time will be straight

This composable supports additional composable views to the left and to the right of the clock: Start Content and End Content. startCurvedContent, endCurvedContent and textCurvedSeparator are used for Round screens. startLinearContent, endLinearContent and textLinearSeparator are used for Square screens. For proper support of Square and Round screens both Linear and Curved methods should be implemented.

Note that Wear Material UX guidance recommends that time text should not be larger than 90 degrees of the screen edge on round devices and prefers short status messages be shown in start content only using the MaterialTheme.colors.primary color for the status message.

For more information, see the Curved Text guide.

A TimeText with a short app status message shown in the start content:

import androidx.wear.compose.foundation.CurvedTextStyle
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.TimeText
import androidx.wear.compose.material.TimeTextDefaults
import androidx.wear.compose.material.curvedText

val leadingTextStyle = TimeTextDefaults.timeTextStyle(color = MaterialTheme.colors.primary)

TimeText(
    startLinearContent = { Text(text = "ETA 12:48", style = leadingTextStyle) },
    startCurvedContent = {
        curvedText(text = "ETA 12:48", style = CurvedTextStyle(leadingTextStyle))
    },
)

An example of a TimeText with a different date and time format:

import androidx.wear.compose.material.Text
import androidx.wear.compose.material.TimeText
import androidx.wear.compose.material.TimeTextDefaults

TimeText(
    timeSource =
        TimeTextDefaults.timeSource(
            DateFormat.getBestDateTimePattern(Locale.getDefault(), "yyyy-MM-dd hh:mm")
        )
)

An example of a TimeText animating a message that is added or removed

import androidx.compose.animation.animateColor
import androidx.compose.animation.core.CubicBezierEasing
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.coerceAtMost
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.CurvedModifier
import androidx.wear.compose.foundation.CurvedTextStyle
import androidx.wear.compose.foundation.angularSize
import androidx.wear.compose.foundation.curvedColumn
import androidx.wear.compose.foundation.curvedRow
import androidx.wear.compose.foundation.sizeIn
import androidx.wear.compose.material.Button
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.TimeText
import androidx.wear.compose.material.TimeTextDefaults
import androidx.wear.compose.material.curvedText

var showState by remember { mutableStateOf(false) }
val showTransition = updateTransition(showState)

val time = 350
val animatedColor by
    showTransition.animateColor(
        label = "animatedColor",
        transitionSpec = {
            tween(
                time,
                easing =
                    when {
                        false isTransitioningTo true ->
                            // Fade In
                            CubicBezierEasing(0.4f, 0.0f, 1.0f, 1.0f)
                        else ->
                            // Fade Out
                            CubicBezierEasing(0.0f, 0.0f, 0.2f, 1.0f)
                    }
            )
        }
    ) { state ->
        when (state) {
            true -> Color.White
            false -> Color.Transparent
        }
    }
val animateSize by
    showTransition.animateFloat(
        label = "animatedSize",
        transitionSpec = { tween(time, easing = CubicBezierEasing(0.4f, 0.0f, 0.2f, 1.0f)) }
    ) { state ->
        when (state) {
            true -> 1f
            false -> 0f
        }
    }

val text = "Long text to animate"

val curvedSeparatorSweep = 10f
val curvedTextSweep = 80f
val curvedAnimatedSweep = animateSize * (curvedSeparatorSweep + curvedTextSweep)
val curvedSeparatorGap = curvedAnimatedSweep.coerceAtMost(curvedSeparatorSweep) / 2f

val linearSeparatorSize = 10.dp
val linearTextSize = 70.dp
val linearAnimatedSize = animateSize * (linearSeparatorSize + linearTextSize)
val linearSeparatorGap = linearAnimatedSize.coerceAtMost(linearSeparatorSize) / 2f

val textStyle =
    TimeTextDefaults.timeTextStyle().copy(fontWeight = FontWeight.Normal, color = animatedColor)
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
    TimeText(
        // Curved
        textCurvedSeparator = {
            curvedColumn(modifier = CurvedModifier.angularSize(curvedSeparatorGap)) {}
            curvedText("·", style = CurvedTextStyle(textStyle))
            curvedColumn(modifier = CurvedModifier.angularSize(curvedSeparatorGap)) {}
        },
        startCurvedContent = {
            curvedRow(
                modifier =
                    CurvedModifier.sizeIn(
                        maxSweepDegrees =
                            (curvedAnimatedSweep - curvedSeparatorSweep).coerceAtLeast(0f)
                    )
            ) {
                curvedText(
                    text,
                    CurvedModifier.sizeIn(maxSweepDegrees = curvedTextSweep),
                    style = CurvedTextStyle(textStyle),
                    overflow = TextOverflow.Ellipsis
                )
            }
        },
        // Linear
        textLinearSeparator = {
            Spacer(modifier = Modifier.width(linearSeparatorGap))
            Text("·", style = textStyle)
            Spacer(modifier = Modifier.width(linearSeparatorGap))
        },
        startLinearContent = {
            Box(
                modifier =
                    Modifier.clipToBounds()
                        .widthIn(
                            max = (linearAnimatedSize - linearSeparatorSize).coerceAtLeast(0.dp)
                        )
            ) {
                Text(
                    text,
                    maxLines = 1,
                    style = textStyle,
                    modifier =
                        Modifier.wrapContentWidth(align = Alignment.Start, unbounded = true)
                            .widthIn(max = linearTextSize),
                    overflow = TextOverflow.Ellipsis
                )
            }
        },
    )
    Button(onClick = { showState = !showState }) { Text("Go!") }
}
Parameters
modifier: Modifier = Modifier

Current modifier.

timeSource: TimeSource = TimeTextDefaults.timeSource(timeFormat())

TimeSource which retrieves the current time and formats it.

timeTextStyle: TextStyle = TimeTextDefaults.timeTextStyle()

Optional textStyle for the time text itself

contentPadding: PaddingValues = TimeTextDefaults.ContentPadding

The spacing values between the container and the content

startLinearContent: (@Composable () -> Unit)? = null

a slot before the time which is used only on Square screens

startCurvedContent: (CurvedScope.() -> Unit)? = null

a slot before the time which is used only on Round screens

endLinearContent: (@Composable () -> Unit)? = null

a slot after the time which is used only on Square screens

endCurvedContent: (CurvedScope.() -> Unit)? = null

a slot after the time which is used only on Round screens

textLinearSeparator: @Composable () -> Unit = { TextSeparator(textStyle = timeTextStyle) }

a separator slot which is used only on Square screens

textCurvedSeparator: CurvedScope.() -> Unit = { CurvedTextSeparator(curvedTextStyle = CurvedTextStyle(timeTextStyle)) }

a separator slot which is used only on Round screens

@Composable
fun TitleCard(
    onClick: () -> Unit,
    title: @Composable RowScope.() -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    time: (@Composable RowScope.() -> Unit)? = null,
    backgroundPainter: Painter = CardDefaults.cardBackgroundPainter(),
    contentColor: Color = MaterialTheme.colors.onSurfaceVariant,
    titleColor: Color = MaterialTheme.colors.onSurface,
    timeColor: Color = contentColor,
    content: @Composable ColumnScope.() -> Unit
): Unit

Opinionated Wear Material Card that offers a specific 3 slot layout to show interactive information about an application, e.g. a message. TitleCards are designed for use within an application.

The first row of the layout has two slots. 1. a start aligned title (emphasised with the titleColor and expected to be start aligned text). The title text is expected to be a maximum of 2 lines of text. 2. An optional time that the application activity has occurred shown at the end of the row, expected to be an end aligned Text composable showing a time relevant to the contents of the Card.

The rest of the Card contains the content which is expected to be Text or a contained Image.

If the content is text it can be single or multiple line and is expected to be Top and Start aligned and of type of Typography.body1.

Overall the title and content text should be no more than 5 rows of text combined.

If more than one composable is provided in the content slot it is the responsibility of the caller to determine how to layout the contents, e.g. provide either a row or a column.

Example of a TitleCard with two lines of body text:

import androidx.wear.compose.material.Text
import androidx.wear.compose.material.TitleCard

TitleCard(
    onClick = {},
    title = { Text("TitleCard") },
    time = { Text("now") },
) {
    Text("Some body content")
    Text("and some more body content")
}

Example of a title card with a background image:

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.CardDefaults
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.TitleCard

TitleCard(
    onClick = { /* Do something */ },
    title = { Text("TitleCard With an ImageBackground") },
    backgroundPainter =
        CardDefaults.imageWithScrimBackgroundPainter(
            backgroundImagePainter = painterResource(id = R.drawable.backgroundimage)
        ),
    contentColor = MaterialTheme.colors.onSurface,
    titleColor = MaterialTheme.colors.onSurface,
) {
    // Apply 24.dp padding in bottom for TitleCard with an ImageBackground.
    // Already 12.dp padding exists. Ref - [CardDefaults.ContentPadding]
    Column(
        modifier = Modifier.fillMaxSize().padding(bottom = 12.dp),
    ) {
        Text("Text coloured to stand out on the image")
    }
}

For more information, see the Cards guide.

Parameters
onClick: () -> Unit

Will be called when the user clicks the card

title: @Composable RowScope.() -> Unit

A slot for displaying the title of the card, expected to be one or two lines of text of Typography.button

modifier: Modifier = Modifier

Modifier to be applied to the card

enabled: Boolean = true

Controls the enabled state of the card. When false, this card will not be clickable and there will be no ripple effect on click. Wear cards do not have any specific elevation or alpha differences when not enabled - they are simply not clickable.

time: (@Composable RowScope.() -> Unit)? = null

An optional slot for displaying the time relevant to the contents of the card, expected to be a short piece of end aligned text.

backgroundPainter: Painter = CardDefaults.cardBackgroundPainter()

A painter used to paint the background of the card. A title card can have either a gradient background or an image background, use CardDefaults.cardBackgroundPainter() or CardDefaults.imageBackgroundPainter() to obtain an appropriate painter

contentColor: Color = MaterialTheme.colors.onSurfaceVariant

The default color to use for content() slot unless explicitly set.

titleColor: Color = MaterialTheme.colors.onSurface

The default color to use for title() slot unless explicitly set.

timeColor: Color = contentColor

The default color to use for time() slot unless explicitly set.

content: @Composable ColumnScope.() -> Unit

Slot for composable body content displayed on the Card

@Composable
fun ToggleButton(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: ToggleButtonColors = ToggleButtonDefaults.toggleButtonColors(),
    interactionSource: MutableInteractionSource? = null,
    shape: Shape = CircleShape,
    role: Role = ToggleButtonDefaults.DefaultRole,
    content: @Composable BoxScope.() -> Unit
): Unit

Wear Material ToggleButton that offers a single slot to take any content (text, icon or image).

The ToggleButton defaults to size ToggleButtonDefaults.DefaultToggleButtonSize or ToggleButtonDefaults.SmallToggleButtonSize. Icon content should be of size ToggleButtonDefaults.DefaultIconSize or ToggleButtonDefaults.SmallIconSize respectively.

The recommended set of checked and unchecked ToggleButtonColors can be obtained from ToggleButtonDefaults.toggleButtonColors, which defaults to checked colors being a solid background of Colors.primary with content color of Colors.onPrimary and unchecked colors being a solid background of Colors.surface with content color of Colors.onSurface.

ToggleButtons can be enabled or disabled. A disabled toggle button will not respond to click events.

Example of a ToggleButton with an icon:

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.ToggleButton
import androidx.wear.compose.material.ToggleButtonDefaults

var checked by remember { mutableStateOf(true) }
ToggleButton(
    checked = checked,
    onCheckedChange = { checked = it },
    enabled = true,
) {
    Icon(
        painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
        contentDescription = "airplane",
        modifier =
            Modifier.size(ToggleButtonDefaults.DefaultIconSize)
                .wrapContentSize(align = Alignment.Center),
    )
}

For more information, see the Buttons guide.

Parameters
checked: Boolean

Boolean flag indicating whether this toggle button is currently checked.

onCheckedChange: (Boolean) -> Unit

Callback to be invoked when this toggle button is clicked.

modifier: Modifier = Modifier

Modifier to be applied to the toggle button.

enabled: Boolean = true

Controls the enabled state of the toggle button. When false, this toggle button will not be clickable.

colors: ToggleButtonColors = ToggleButtonDefaults.toggleButtonColors()

ToggleButtonColors that will be used to resolve the background and content color for this toggle button. See ToggleButtonDefaults.toggleButtonColors.

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this toggle button. You can use this to change the toggle button's appearance or preview the toggle button in different states. Note that if null is provided, interactions will still happen internally.

shape: Shape = CircleShape

Defines the shape for this toggle button. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme.

role: Role = ToggleButtonDefaults.DefaultRole

Role semantics that accessibility services can use to provide more context to users.

content: @Composable BoxScope.() -> Unit

The icon, image or text to be drawn inside the toggle button.

@Composable
fun ToggleChip(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    label: @Composable RowScope.() -> Unit,
    toggleControl: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    appIcon: (@Composable BoxScope.() -> Unit)? = null,
    secondaryLabel: (@Composable RowScope.() -> Unit)? = null,
    colors: ToggleChipColors = ToggleChipDefaults.toggleChipColors(),
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    contentPadding: PaddingValues = ToggleChipDefaults.ContentPadding,
    shape: Shape = MaterialTheme.shapes.large
): Unit

A ToggleChip is a specialized type of Chip that includes a slot for a bi-state toggle control such as a toggle or checkbox. This overload provides suitable accessibility semantics for a toggleable control like Checkbox and Switch. For selectable controls like RadioButton, use SelectableChip in order to provide the correct semantics for accessibility.

The Wear Material ToggleChip offers four slots and a specific layout for an application icon, a label, a secondaryLabel and toggle control. The application icon and secondaryLabel are optional. The items are laid out in a row with the optional icon at the start, a column containing the two label slots in the middle and a slot for the toggle control at the end.

The ToggleChip is Stadium shaped and has a max height designed to take no more than two lines of text of Typography.button style. With localisation and/or large font sizes, the ToggleChip height adjusts to accommodate the contents. The label and secondary label should be consistently aligned.

The recommended set of ToggleChipColors can be obtained from ToggleChipDefaults, e.g. ToggleChipDefaults.toggleChipColors.

Chips can be enabled or disabled. A disabled chip will not respond to click events.

Example of a ToggleChip with an icon, label and secondary label (defaults to switch toggle):

import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.Switch
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.ToggleChip
import androidx.wear.compose.material.ToggleChipDefaults

var checked by remember { mutableStateOf(true) }
// The primary label should have a maximum 3 lines of text
// and the secondary label should have max 2 lines of text.
ToggleChip(
    label = { Text("SwitchIcon", maxLines = 3, overflow = TextOverflow.Ellipsis) },
    secondaryLabel = {
        Text("With secondary label", maxLines = 2, overflow = TextOverflow.Ellipsis)
    },
    checked = checked,
    // For Switch  toggle controls the Wear Material UX guidance is to set the
    // unselected toggle control color to ToggleChipDefaults.switchUncheckedIconColor()
    // rather than the default.
    colors =
        ToggleChipDefaults.toggleChipColors(
            uncheckedToggleControlColor = ToggleChipDefaults.SwitchUncheckedIconColor
        ),
    toggleControl = {
        Switch(
            checked = checked,
            enabled = true,
        )
    },
    onCheckedChange = { checked = it },
    appIcon = {
        Icon(
            painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
            contentDescription = "airplane",
            modifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center),
        )
    },
    enabled = true,
)

For more information, see the Toggle Chips guide.

Parameters
checked: Boolean

Boolean flag indicating whether this button is currently checked.

onCheckedChange: (Boolean) -> Unit

Callback to be invoked when this button's checked status changes

label: @Composable RowScope.() -> Unit

A slot for providing the chip's main label. The contents are expected to be text which is "start" aligned.

toggleControl: @Composable () -> Unit

A slot for providing the chip's toggle control. Two built-in types of toggle control are supported - Checkbox and Switch. For RadioButton, use SelectableChip, in order to provide the correct semantics for accessibility.

modifier: Modifier = Modifier

Modifier to be applied to the chip

appIcon: (@Composable BoxScope.() -> Unit)? = null

An optional slot for providing an icon to indicate the purpose of the chip. The contents are expected to be a horizontally and vertically centre aligned icon of size ToggleChipDefaults.IconSize. In order to correctly render when the Chip is not enabled the icon must set its alpha value to LocalContentAlpha.

secondaryLabel: (@Composable RowScope.() -> Unit)? = null

A slot for providing the chip's secondary label. The contents are expected to be text which is "start" aligned if there is an icon preset and "start" or "center" aligned if not. label and secondaryLabel contents should be consistently aligned.

colors: ToggleChipColors = ToggleChipDefaults.toggleChipColors()

ToggleChipColors that will be used to resolve the background and content color for this chip in different states, see ToggleChipDefaults.toggleChipColors.

enabled: Boolean = true

Controls the enabled state of the chip. When false, this chip will not be clickable

interactionSource: MutableInteractionSource? = null

an optional hoisted MutableInteractionSource for observing and emitting Interactions for this chip's "toggleable" tap area. You can use this to change the chip's appearance or preview the chip in different states. Note that if null is provided, interactions will still happen internally.

contentPadding: PaddingValues = ToggleChipDefaults.ContentPadding

The spacing values to apply internally between the container and the content

shape: Shape = MaterialTheme.shapes.large

Defines the chip's shape. It is strongly recommended to use the default as this shape is a key characteristic of the Wear Material Theme

@Composable
fun Vignette(vignettePosition: VignettePosition, modifier: Modifier = Modifier): Unit

Vignette is whole screen decoration used to blur the top and bottom of the edges of a wearable screen when scrolling content is displayed. The vignette is split between a top and bottom image which can be displayed independently depending on the use case.

The vignette is designed to be used as an overlay, typically in the Scaffold.

Simple example of a Vignette with a ScalingLazyColumn as the main application content where the top/bottom vignette images can be turned on/off can be found at

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.PositionIndicator
import androidx.wear.compose.material.Scaffold
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.TimeText
import androidx.wear.compose.material.Vignette
import androidx.wear.compose.material.VignettePosition

val listState = rememberScalingLazyListState()
val vignetteState = mutableStateOf(VignettePosition.TopAndBottom)
val showVignette = mutableStateOf(true)

Scaffold(
    positionIndicator = {
        PositionIndicator(scalingLazyListState = listState, modifier = Modifier)
    },
    vignette = {
        if (showVignette.value) {
            Vignette(vignettePosition = vignetteState.value)
        }
    },
    timeText = { TimeText() }
) {
    ScalingLazyColumn(
        contentPadding = PaddingValues(top = 40.dp),
        state = listState,
        modifier = Modifier.fillMaxWidth()
    ) {
        item {
            Chip(
                onClick = { showVignette.value = false },
                label = { Text("No Vignette") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
        item {
            Chip(
                onClick = {
                    showVignette.value = true
                    vignetteState.value = VignettePosition.Top
                },
                label = { Text("Top Vignette only") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
        item {
            Chip(
                onClick = {
                    showVignette.value = true
                    vignetteState.value = VignettePosition.Bottom
                },
                label = { Text("Bottom Vignette only") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
        item {
            Chip(
                onClick = {
                    showVignette.value = true
                    vignetteState.value = VignettePosition.TopAndBottom
                },
                label = { Text("Top and Bottom Vignette") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
        items(20) {
            Chip(
                onClick = {},
                label = { Text("List item $it") },
                colors = ChipDefaults.secondaryChipColors()
            )
        }
    }
}
Parameters
vignettePosition: VignettePosition

whether to draw top and/or bottom images for this Vignette

modifier: Modifier = Modifier

optional Modifier for the root of the Vignette

@Composable
fun contentColorFor(backgroundColor: Color): Color

The Material color system contains pairs of colors that are typically used for the background and content color inside a component. For example, a Button typically uses primary for its background, and onPrimary for the color of its content (usually text or iconography).

This function tries to match the provided backgroundColor to a 'background' color in this Colors, and then will return the corresponding color used for content. For example, when backgroundColor is Colors.primary, this will return Colors.onPrimary.

If backgroundColor does not match a background color in the theme, this will return the current value of LocalContentColor as a best-effort color.

Returns
Color

the matching content color for backgroundColor. If backgroundColor is not present in the theme's Colors, then returns the current value of LocalContentColor.

See also
contentColorFor

rememberPickerGroupState

@Composable
fun rememberPickerGroupState(initiallySelectedIndex: Int = 0): PickerGroupState

Creates a PickerGroupState that is remembered across compositions.

Parameters
initiallySelectedIndex: Int = 0

the picker index that will be initially focused

rememberPickerState

@Composable
fun rememberPickerState(
    initialNumberOfOptions: Int,
    initiallySelectedOption: Int = 0,
    repeatItems: Boolean = true
): PickerState

Creates a PickerState that is remembered across compositions.

Parameters
initialNumberOfOptions: Int

the number of options

initiallySelectedOption: Int = 0

the option to show in the center at the start

repeatItems: Boolean = true

if true (the default), the contents of the component will be repeated

rememberPlaceholderState

@ExperimentalWearMaterialApi
@Composable
fun rememberPlaceholderState(isContentReady: () -> Boolean): PlaceholderState

Creates a PlaceholderState that is remembered across compositions. To start placeholder animations run PlaceholderState.startPlaceholderAnimation.

A PlaceholderState should be created for each component that has placeholder data. The state is used to coordinate all of the different placeholder effects and animations.

Placeholder has a number of different effects designed to work together. Modifier.placeholder draws a placeholder shape on top of content that is waiting to load. There can be multiple placeholders in a component. Modifier.placeholderShimmer does a shimmer animation over the whole component that includes the placeholders. There should only be one placeholderShimmer for each component.

Background placeholder effects are used to mask the background of components like chips and cards until all of the data has loaded. Use PlaceholderDefaults.placeholderChipColors and PlaceholderDefaults.painterWithPlaceholderOverlayBackgroundBrush to draw the component background.

Once all of the components content is loaded, isContentReady is true the shimmer will stop and a wipe off animation will remove the placeholders to reveal the content.

Parameters
isContentReady: () -> Boolean

a lambda to determine whether all of the data/content has been loaded for a given component and is ready to be displayed.

rememberScalingLazyListState

@Composable
fun rememberScalingLazyListState(
    initialCenterItemIndex: Int = 1,
    initialCenterItemScrollOffset: Int = 0
): ScalingLazyListState

Creates a ScalingLazyListState that is remembered across compositions.

Parameters
initialCenterItemIndex: Int = 1

the initial value for ScalingLazyListState.centerItemIndex, defaults to 1. This will place the 2nd list item (index == 1) in the center of the viewport and the first item (index == 0) before it.

initialCenterItemScrollOffset: Int = 0

the initial value for ScalingLazyListState.centerItemScrollOffset in pixels

rememberSwipeToDismissBoxState

@Composable
fun rememberSwipeToDismissBoxState(
    animationSpec: AnimationSpec<Float> = SWIPE_TO_DISMISS_BOX_ANIMATION_SPEC,
    confirmStateChange: (SwipeToDismissValue) -> Boolean = { true }
): SwipeToDismissBoxState

Create a SwipeToDismissBoxState and remember it.

Parameters
animationSpec: AnimationSpec<Float> = SWIPE_TO_DISMISS_BOX_ANIMATION_SPEC

The default animation used to animate to a new state.

confirmStateChange: (SwipeToDismissValue) -> Boolean = { true }

Optional callback to confirm or veto a pending state change.

rememberSwipeableState

@Composable
@ExperimentalWearMaterialApi
fun <T : Any> rememberSwipeableState(
    initialValue: T,
    animationSpec: AnimationSpec<Float> = SwipeableDefaults.AnimationSpec,
    confirmStateChange: (newValue) -> Boolean = { true }
): SwipeableState<T>

Create and remember a SwipeableState with the default animation clock.

Parameters
initialValue: T

The initial value of the state.

animationSpec: AnimationSpec<Float> = SwipeableDefaults.AnimationSpec

The default animation that will be used to animate to a new state.

confirmStateChange: (newValue) -> Boolean = { true }

Optional callback invoked to confirm or veto a pending state change.

fun ripple(
    bounded: Boolean = true,
    radius: Dp = Dp.Unspecified,
    color: Color = Color.Unspecified
): IndicationNodeFactory

Creates a Ripple using the provided values and values inferred from the theme.

A Ripple is a Material implementation of Indication that expresses different Interactions by drawing ripple animations and state layers.

A Ripple responds to PressInteraction.Press by starting a new animation, and responds to other Interactions by showing a fixed state layer with varying alpha values depending on the Interaction.

MaterialTheme provides Ripples using androidx.compose.foundation.LocalIndication, so a Ripple will be used as the default Indication inside components such as androidx.compose.foundation.clickable and androidx.compose.foundation.indication, in addition to Material provided components that use a Ripple as well.

You can also explicitly create a Ripple and provide it to custom components in order to change the parameters from the default, such as to create an unbounded ripple with a fixed size.

To create a Ripple with a manually defined color that can change over time, see the other ripple overload with a ColorProducer parameter. This will avoid unnecessary recompositions when changing the color, and preserve existing ripple state when the color changes.

Parameters
bounded: Boolean = true

If true, ripples are clipped by the bounds of the target layout. Unbounded ripples always animate from the target layout center, bounded ripples animate from the touch position.

radius: Dp = Dp.Unspecified

the radius for the ripple. If Dp.Unspecified is provided then the size will be calculated based on the target layout size.

color: Color = Color.Unspecified

the color of the ripple. This color is usually the same color used by the text or iconography in the component. This color will then have alpha applied to calculate the final color used to draw the ripple. If Color.Unspecified is provided the color used will be the default ripple color instead.

fun ripple(
    color: ColorProducer,
    bounded: Boolean = true,
    radius: Dp = Dp.Unspecified
): IndicationNodeFactory

Creates a Ripple using the provided values and values inferred from the theme.

A Ripple is a Material implementation of Indication that expresses different Interactions by drawing ripple animations and state layers.

A Ripple responds to PressInteraction.Press by starting a new ripple animation, and responds to other Interactions by showing a fixed state layer with varying alpha values depending on the Interaction.

MaterialTheme provides Ripples using androidx.compose.foundation.LocalIndication, so a Ripple will be used as the default Indication inside components such as androidx.compose.foundation.clickable and androidx.compose.foundation.indication, in addition to Material provided components that use a Ripple as well.

You can also explicitly create a Ripple and provide it to custom components in order to change the parameters from the default, such as to create an unbounded ripple with a fixed size.

To create a Ripple with a static color, see the ripple overload with a Color parameter. This overload is optimized for Ripples that have dynamic colors that change over time, to reduce unnecessary recompositions.

Parameters
color: ColorProducer

the color of the ripple. This color is usually the same color used by the text or iconography in the component. This color will then have alpha applied to calculate the final * color used to draw the ripple. If you are creating this ColorProducer outside of composition (where it will be automatically remembered), make sure that its instance is stable (such as by remembering the object that holds it), or remember the returned ripple object to make sure that ripple nodes are not being created each recomposition.

bounded: Boolean = true

If true, ripples are clipped by the bounds of the target layout. Unbounded ripples always animate from the target layout center, bounded ripples animate from the touch position.

radius: Dp = Dp.Unspecified

the radius for the ripple. If Dp.Unspecified is provided then the size will be calculated based on the target layout size.

Extension functions

SwipeToRevealPrimaryAction

@ExperimentalWearMaterialApi
@Composable
fun RevealScope.SwipeToRevealPrimaryAction(
    revealState: RevealState,
    onClick: () -> Unit,
    icon: @Composable () -> Unit,
    label: @Composable () -> Unit,
    modifier: Modifier = Modifier,
    interactionSource: MutableInteractionSource? = null
): Unit

A composable which can be used for setting the primary action of material SwipeToRevealCard and SwipeToRevealChip.

Parameters
revealState: RevealState

The RevealState of the SwipeToReveal where this action is used.

onClick: () -> Unit

A lambda which gets triggered when the action is clicked.

icon: @Composable () -> Unit

The icon which will be displayed initially on the action

label: @Composable () -> Unit

The label which will be displayed on the expanded action

modifier: Modifier = Modifier

Modifier to be applied on the action

interactionSource: MutableInteractionSource? = null

The MutableInteractionSource representing the stream of interactions with this action.

SwipeToRevealSecondaryAction

@ExperimentalWearMaterialApi
@Composable
fun RevealScope.SwipeToRevealSecondaryAction(
    revealState: RevealState,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    interactionSource: MutableInteractionSource? = null,
    content: @Composable () -> Unit
): Unit

A composable which can be used for setting the secondary action of material SwipeToRevealCard and SwipeToRevealChip.

Parameters
revealState: RevealState

The RevealState of the SwipeToReveal where this action is used.

onClick: () -> Unit

A lambda which gets triggered when the action is clicked.

modifier: Modifier = Modifier

Modifier to be applied on the action

interactionSource: MutableInteractionSource? = null

The MutableInteractionSource representing the stream of interactions with this action.

content: @Composable () -> Unit

The composable which will be displayed on the action. It is recommended to keep this content as an Icon composable.

SwipeToRevealUndoAction

@ExperimentalWearMaterialApi
@Composable
fun RevealScope.SwipeToRevealUndoAction(
    revealState: RevealState,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    interactionSource: MutableInteractionSource? = null,
    icon: (@Composable () -> Unit)? = null,
    label: (@Composable () -> Unit)? = null
): Unit

A composable which can be used for setting the undo action of material SwipeToRevealCard and SwipeToRevealChip.

Parameters
revealState: RevealState

The RevealState of the SwipeToReveal where this action is used.

onClick: () -> Unit

A lambda which gets triggered when the action is clicked.

modifier: Modifier = Modifier

Modifier to be applied on the action

interactionSource: MutableInteractionSource? = null

The MutableInteractionSource representing the stream of interactions with this action.

icon: (@Composable () -> Unit)? = null

An optional icon which will be displayed on the action

label: (@Composable () -> Unit)? = null

An optional label which will be displayed on the action. We strongly recommend to set icon and/or label for the action.

fun Colors.contentColorFor(backgroundColor: Color): Color

The Material color system contains pairs of colors that are typically used for the background and content color inside a component. For example, a Button typically uses primary for its background, and onPrimary for the color of its content (usually text or iconography).

This function tries to match the provided backgroundColor to a 'background' color in this Colors, and then will return the corresponding color used for content. For example, when backgroundColor is Colors.primary, this will return Colors.onPrimary.

If backgroundColor does not match a background color in the theme, this will return Color.Unspecified.

Returns
Color

the matching content color for backgroundColor. If backgroundColor is not present in the theme's Colors, then returns Color.Unspecified.

See also
contentColorFor
fun CurvedScope.curvedText(
    text: String,
    modifier: CurvedModifier = CurvedModifier,
    background: Color = Color.Unspecified,
    color: Color = Color.Unspecified,
    fontSize: TextUnit = TextUnit.Unspecified,
    fontFamily: FontFamily? = null,
    fontWeight: FontWeight? = null,
    fontStyle: FontStyle? = null,
    fontSynthesis: FontSynthesis? = null,
    style: CurvedTextStyle? = null,
    angularDirection: CurvedDirection.Angular? = null,
    overflow: TextOverflow = TextOverflow.Clip
): Unit

CurvedText is a component allowing developers to easily write curved text following the curvature a circle (usually at the edge of a circular screen). CurvedText can be only created within the CurvedLayout to ensure the best experience, like being able to specify to positioning.

The default style uses the LocalTextStyle provided by the MaterialTheme / components, converting it to a CurvedTextStyle. Note that not all parameters are used by curvedText.

If you are setting your own style, you may want to consider first retrieving LocalTextStyle, and using TextStyle.copy to keep any theme defined attributes, only modifying the specific attributes you want to override, then convert to CurvedTextStyle

For ease of use, commonly used parameters from CurvedTextStyle are also present here. The order of precedence is as follows:

  • If a parameter is explicitly set here (i.e, it is not null or TextUnit.Unspecified), then this parameter will always be used.

  • If a parameter is not set, (null or TextUnit.Unspecified), then the corresponding value from style will be used instead.

Additionally, for color, if color is not set, and style does not have a color, then LocalContentColor will be used with an alpha of LocalContentAlpha- this allows this curvedText or element containing this curvedText to adapt to different background colors and still maintain contrast and accessibility.

For samples explicitly specifying style see:

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
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.CurvedModifier
import androidx.wear.compose.foundation.curvedColumn
import androidx.wear.compose.foundation.curvedRow
import androidx.wear.compose.foundation.padding
import androidx.wear.compose.material.curvedText

CurvedLayout() {
    curvedColumn(angularAlignment = CurvedAlignment.Angular.Center) {
        curvedRow {
            curvedText("Red", color = Color.Red)
            curvedText(
                "White On Green",
                color = Color.White,
                background = Color.Green,
                modifier = CurvedModifier.padding(angular = 5.dp)
            )
            curvedText("Big", fontSize = 24.sp)
            curvedText(
                "Extra Bold",
                fontWeight = FontWeight.ExtraBold,
                modifier = CurvedModifier.padding(angular = 5.dp)
            )
        }
        curvedRow {
            curvedText("Default")
            curvedText(
                "Italic",
                fontStyle = FontStyle.Italic,
                modifier = CurvedModifier.padding(angular = 5.dp)
            )
            curvedText("Monospaced", fontFamily = FontFamily.Monospace)
        }
    }
}

For examples using CompositionLocal to specify the style, see:

import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.wear.compose.foundation.CurvedLayout
import androidx.wear.compose.foundation.CurvedTextStyle
import androidx.wear.compose.material.LocalContentAlpha
import androidx.wear.compose.material.LocalContentColor
import androidx.wear.compose.material.LocalTextStyle
import androidx.wear.compose.material.ProvideTextStyle
import androidx.wear.compose.material.curvedText

CompositionLocalProvider(
    LocalContentColor provides Color.Cyan,
    LocalContentAlpha provides 0.5f,
    LocalTextStyle provides TextStyle(fontFamily = FontFamily.Serif)
) {
    val greenStyle = LocalTextStyle.current.copy(color = Color.Green)
    CurvedLayout {
        curvedText("Serif Cyan 50%")
        curvedText("Green", style = CurvedTextStyle(greenStyle))
    }
}

ProvideTextStyle(
    value =
        TextStyle(color = Color.Green, background = Color.White, fontWeight = FontWeight.Bold)
) {
    CurvedLayout(anchor = 90f) { curvedText("Green On White") }
}

For more information, see the Curved Text guide.

Parameters
text: String

The text to display

modifier: CurvedModifier = CurvedModifier

The CurvedModifier to apply to this curved text.

background: Color = Color.Unspecified

The background color for the text.

color: Color = Color.Unspecified

Color to apply to the text. If Color.Unspecified, and style has no color set, this will be LocalContentColor.

fontSize: TextUnit = TextUnit.Unspecified

The size of glyphs to use when painting the text. See TextStyle.fontSize.

fontFamily: FontFamily? = null

The font family to be used when rendering the text.

fontWeight: FontWeight? = null

The thickness of the glyphs, in a range of 1, 1000. see FontWeight

fontStyle: FontStyle? = null

The typeface variant to use when drawing the letters (e.g. italic).

fontSynthesis: FontSynthesis? = null

Whether to synthesize font weight and/or style when the requested weight or style cannot be found in the provided font family.

style: CurvedTextStyle? = null

Specifies the style to use.

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.

fun Modifier.edgeSwipeToDismiss(
    swipeToDismissBoxState: SwipeToDismissBoxState,
    edgeWidth: Dp = SwipeToDismissBoxDefaults.EdgeWidth
): Modifier

Limits swipe to dismiss to be active from the edge of the viewport only. Used when the center of the screen needs to be able to handle horizontal paging, such as 2-d scrolling a Map or swiping horizontally between pages. Swipe to the right is intercepted on the left part of the viewport with width specified by edgeWidth, with other touch events ignored - vertical scroll, click, long click, etc.

Currently Edge swipe, like swipe to dismiss, is only supported on the left part of the viewport regardless of layout direction as content is swiped away from left to right.

Requires that the element to which this modifier is applied exists within a SwipeToDismissBox which is using the same SwipeToDismissBoxState instance.

Example of a modifier usage with SwipeToDismiss

import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.wear.compose.foundation.edgeSwipeToDismiss
import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
import androidx.wear.compose.material.MaterialTheme
import androidx.wear.compose.material.SwipeToDismissBox
import androidx.wear.compose.material.Text

val state = rememberSwipeToDismissBoxState()

// When using Modifier.edgeSwipeToDismiss, it is required that the element on which the
// modifier applies exists within a SwipeToDismissBox which shares the same state.
SwipeToDismissBox(state = state, onDismissed = navigateBack) { isBackground ->
    val horizontalScrollState = rememberScrollState(0)
    if (isBackground) {
        Box(modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.secondaryVariant))
    } else {
        Box(modifier = Modifier.fillMaxSize()) {
            Text(
                modifier =
                    Modifier.align(Alignment.Center)
                        .edgeSwipeToDismiss(state)
                        .horizontalScroll(horizontalScrollState),
                text =
                    "This text can be scrolled horizontally - to dismiss, swipe " +
                        "right from the left edge of the screen (called Edge Swiping)",
            )
        }
    }
}
Parameters
swipeToDismissBoxState: SwipeToDismissBoxState

A state of SwipeToDismissBox. Used to trigger swipe gestures on SwipeToDismissBox

edgeWidth: Dp = SwipeToDismissBoxDefaults.EdgeWidth

A width of edge, where swipe should be recognised

items

inline fun <T : Any?> ScalingLazyListScope.items(
    items: Array<T>,
    noinline key: ((item) -> Any)? = null,
    crossinline itemContent: @Composable ScalingLazyListItemScope.(item) -> Unit
): Unit

Adds an array of items.

Parameters
items: Array<T>

the data array

noinline key: ((item) -> 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.

crossinline itemContent: @Composable ScalingLazyListItemScope.(item) -> Unit

the content displayed by a single item

inline fun <T : Any?> ScalingLazyListScope.items(
    items: List<T>,
    noinline key: ((item) -> Any)? = null,
    crossinline itemContent: @Composable ScalingLazyListItemScope.(item) -> Unit
): Unit

Adds a list of items.

Parameters
items: List<T>

the data list

noinline key: ((item) -> 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.

crossinline itemContent: @Composable ScalingLazyListItemScope.(item) -> Unit

the content displayed by a single item

itemsIndexed

inline fun <T : Any?> ScalingLazyListScope.itemsIndexed(
    items: Array<T>,
    noinline key: ((index: Int, item) -> Any)? = null,
    crossinline itemContent: @Composable ScalingLazyListItemScope.(index: Int, item) -> Unit
): Unit

Adds an array of items where the content of an item is aware of its index.

Parameters
items: Array<T>

the data array

noinline key: ((index: Int, item) -> 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.

crossinline itemContent: @Composable ScalingLazyListItemScope.(index: Int, item) -> Unit

the content displayed by a single item

inline fun <T : Any?> ScalingLazyListScope.itemsIndexed(
    items: List<T>,
    noinline key: ((index: Int, item) -> Any)? = null,
    crossinline itemContent: @Composable ScalingLazyListItemScope.(index: Int, item) -> Unit
): Unit

Adds a list of items where the content of an item is aware of its index.

Parameters
items: List<T>

the data list

noinline key: ((index: Int, item) -> 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.

crossinline itemContent: @Composable ScalingLazyListItemScope.(index: Int, item) -> Unit

the content displayed by a single item

@ExperimentalWearMaterialApi
@Composable
fun Modifier.placeholder(
    placeholderState: PlaceholderState,
    shape: Shape = MaterialTheme.shapes.small,
    color: Color = MaterialTheme.colors.onSurface .copy(alpha = 0.1f) .compositeOver(MaterialTheme.colors.surface)
): Modifier

Draws a placeholder shape over the top of a composable and animates a wipe off effect to remove the placeholder. Typically used whilst content is 'loading' and then 'revealed'.

Example of a Chip with icon and a label that put placeholders over individual content slots:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.PlaceholderDefaults
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.placeholder
import androidx.wear.compose.material.placeholderShimmer
import androidx.wear.compose.material.rememberPlaceholderState

var labelText by remember { mutableStateOf("") }
var iconResource: Int? by remember { mutableStateOf(null) }
val chipPlaceholderState = rememberPlaceholderState {
    labelText.isNotEmpty() && iconResource != null
}

Chip(
    onClick = { /* Do something */ },
    enabled = true,
    label = {
        Text(
            text = labelText,
            maxLines = 2,
            overflow = TextOverflow.Ellipsis,
            modifier = Modifier.fillMaxWidth().placeholder(chipPlaceholderState)
        )
    },
    icon = {
        Box(modifier = Modifier.size(ChipDefaults.IconSize).placeholder(chipPlaceholderState)) {
            if (iconResource != null) {
                Icon(
                    painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
                    contentDescription = "airplane",
                    modifier =
                        Modifier.wrapContentSize(align = Alignment.Center)
                            .size(ChipDefaults.IconSize)
                            .fillMaxSize(),
                )
            }
        }
    },
    colors =
        PlaceholderDefaults.placeholderChipColors(
            originalChipColors = ChipDefaults.primaryChipColors(),
            placeholderState = chipPlaceholderState
        ),
    modifier = Modifier.fillMaxWidth().placeholderShimmer(chipPlaceholderState)
)
// Simulate content loading completing in stages
LaunchedEffect(Unit) {
    delay(2000)
    iconResource = R.drawable.ic_airplanemode_active_24px
    delay(1000)
    labelText = "A label"
}
if (!chipPlaceholderState.isShowContent) {
    LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}

Example of a Chip with icon and a primary and secondary labels that draws another Chip over the top of it when waiting for placeholder data to load:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.PlaceholderDefaults
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.placeholder
import androidx.wear.compose.material.placeholderShimmer
import androidx.wear.compose.material.rememberPlaceholderState

var labelText by remember { mutableStateOf("") }
var secondaryLabelText by remember { mutableStateOf("") }
var iconResource: Int? by remember { mutableStateOf(null) }

val chipPlaceholderState = rememberPlaceholderState {
    labelText.isNotEmpty() && secondaryLabelText.isNotEmpty() && iconResource != null
}
Box {
    if (chipPlaceholderState.isShowContent || chipPlaceholderState.isWipeOff) {
        Chip(
            onClick = { /* Do something */ },
            enabled = true,
            label = {
                Text(
                    text = labelText,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.fillMaxWidth()
                )
            },
            secondaryLabel = {
                Text(
                    text = secondaryLabelText,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.fillMaxWidth()
                )
            },
            icon = {
                if (iconResource != null) {
                    Icon(
                        painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
                        contentDescription = "airplane",
                        modifier =
                            Modifier.wrapContentSize(align = Alignment.Center)
                                .size(ChipDefaults.IconSize)
                    )
                }
            },
            colors = ChipDefaults.gradientBackgroundChipColors(),
            modifier = Modifier.fillMaxWidth()
        )
    }
    if (!chipPlaceholderState.isShowContent) {
        Chip(
            onClick = { /* Do something */ },
            enabled = true,
            label = {
                Box(
                    modifier =
                        Modifier.fillMaxWidth()
                            .height(16.dp)
                            .padding(top = 1.dp, bottom = 1.dp)
                            .placeholder(placeholderState = chipPlaceholderState)
                )
            },
            secondaryLabel = {
                Box(
                    modifier =
                        Modifier.fillMaxWidth()
                            .height(16.dp)
                            .padding(top = 1.dp, bottom = 1.dp)
                            .placeholder(placeholderState = chipPlaceholderState)
                )
            },
            icon = {
                Box(
                    modifier =
                        Modifier.size(ChipDefaults.IconSize).placeholder(chipPlaceholderState)
                )
                // Simulate the icon becoming ready after a period of time
                LaunchedEffect(Unit) {
                    delay(2000)
                    iconResource = R.drawable.ic_airplanemode_active_24px
                }
            },
            colors =
                PlaceholderDefaults.placeholderChipColors(
                    placeholderState = chipPlaceholderState
                ),
            modifier = Modifier.fillMaxWidth().placeholderShimmer(chipPlaceholderState)
        )
    }
}
// Simulate data being loaded after a delay
LaunchedEffect(Unit) {
    delay(2500)
    secondaryLabelText = "A secondary label"
    delay(500)
    labelText = "A label"
}
if (!chipPlaceholderState.isShowContent) {
    LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}

The placeholderState determines when to 'show' and 'wipe off' the placeholder.

NOTE: The order of modifiers is important. If you are adding both Modifier.placeholder and Modifier.placeholderShimmer to the same composable then the shimmer must be first in the modifier chain. Example of Text composable with both placeholderShimmer and placeholder modifiers.

import androidx.compose.foundation.layout.width
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.placeholder
import androidx.wear.compose.material.placeholderShimmer
import androidx.wear.compose.material.rememberPlaceholderState

var labelText by remember { mutableStateOf("") }
val chipPlaceholderState = rememberPlaceholderState { labelText.isNotEmpty() }

Text(
    text = labelText,
    overflow = TextOverflow.Ellipsis,
    textAlign = TextAlign.Center,
    modifier =
        Modifier.width(90.dp)
            .placeholderShimmer(chipPlaceholderState)
            .placeholder(chipPlaceholderState)
)

// Simulate content loading
LaunchedEffect(Unit) {
    delay(3000)
    labelText = "A label"
}
if (!chipPlaceholderState.isShowContent) {
    LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}
Parameters
placeholderState: PlaceholderState

determines whether the placeholder is visible and controls animation effects for the placeholder.

shape: Shape = MaterialTheme.shapes.small

the shape to apply to the placeholder

color: Color = MaterialTheme.colors.onSurface .copy(alpha = 0.1f) .compositeOver(MaterialTheme.colors.surface)

the color of the placeholder.

@ExperimentalWearMaterialApi
@Composable
fun Modifier.placeholderShimmer(
    placeholderState: PlaceholderState,
    shape: Shape = MaterialTheme.shapes.small,
    color: Color = MaterialTheme.colors.onSurface
): Modifier

Modifier to draw a placeholder shimmer over a component. The placeholder shimmer is a 45 degree gradient from Top|Left of the screen to Bottom|Right. The shimmer is coordinated via the animation frame clock which orchestrates the shimmer so that every component will shimmer as the gradient progresses across the screen.

Example of a Chip with icon and a label that put placeholders over individual content slots and then draws a placeholder shimmer over the result:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.PlaceholderDefaults
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.placeholder
import androidx.wear.compose.material.placeholderShimmer
import androidx.wear.compose.material.rememberPlaceholderState

var labelText by remember { mutableStateOf("") }
var iconResource: Int? by remember { mutableStateOf(null) }
val chipPlaceholderState = rememberPlaceholderState {
    labelText.isNotEmpty() && iconResource != null
}

Chip(
    onClick = { /* Do something */ },
    enabled = true,
    label = {
        Text(
            text = labelText,
            maxLines = 2,
            overflow = TextOverflow.Ellipsis,
            modifier = Modifier.fillMaxWidth().placeholder(chipPlaceholderState)
        )
    },
    icon = {
        Box(modifier = Modifier.size(ChipDefaults.IconSize).placeholder(chipPlaceholderState)) {
            if (iconResource != null) {
                Icon(
                    painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
                    contentDescription = "airplane",
                    modifier =
                        Modifier.wrapContentSize(align = Alignment.Center)
                            .size(ChipDefaults.IconSize)
                            .fillMaxSize(),
                )
            }
        }
    },
    colors =
        PlaceholderDefaults.placeholderChipColors(
            originalChipColors = ChipDefaults.primaryChipColors(),
            placeholderState = chipPlaceholderState
        ),
    modifier = Modifier.fillMaxWidth().placeholderShimmer(chipPlaceholderState)
)
// Simulate content loading completing in stages
LaunchedEffect(Unit) {
    delay(2000)
    iconResource = R.drawable.ic_airplanemode_active_24px
    delay(1000)
    labelText = "A label"
}
if (!chipPlaceholderState.isShowContent) {
    LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}

Example of a Chip with icon and a primary and secondary labels that draws another Chip over the top of it when waiting for placeholder data to load and then draws a placeholder shimmer over the top:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Chip
import androidx.wear.compose.material.ChipDefaults
import androidx.wear.compose.material.Icon
import androidx.wear.compose.material.PlaceholderDefaults
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.placeholder
import androidx.wear.compose.material.placeholderShimmer
import androidx.wear.compose.material.rememberPlaceholderState

var labelText by remember { mutableStateOf("") }
var secondaryLabelText by remember { mutableStateOf("") }
var iconResource: Int? by remember { mutableStateOf(null) }

val chipPlaceholderState = rememberPlaceholderState {
    labelText.isNotEmpty() && secondaryLabelText.isNotEmpty() && iconResource != null
}
Box {
    if (chipPlaceholderState.isShowContent || chipPlaceholderState.isWipeOff) {
        Chip(
            onClick = { /* Do something */ },
            enabled = true,
            label = {
                Text(
                    text = labelText,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.fillMaxWidth()
                )
            },
            secondaryLabel = {
                Text(
                    text = secondaryLabelText,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                    modifier = Modifier.fillMaxWidth()
                )
            },
            icon = {
                if (iconResource != null) {
                    Icon(
                        painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
                        contentDescription = "airplane",
                        modifier =
                            Modifier.wrapContentSize(align = Alignment.Center)
                                .size(ChipDefaults.IconSize)
                    )
                }
            },
            colors = ChipDefaults.gradientBackgroundChipColors(),
            modifier = Modifier.fillMaxWidth()
        )
    }
    if (!chipPlaceholderState.isShowContent) {
        Chip(
            onClick = { /* Do something */ },
            enabled = true,
            label = {
                Box(
                    modifier =
                        Modifier.fillMaxWidth()
                            .height(16.dp)
                            .padding(top = 1.dp, bottom = 1.dp)
                            .placeholder(placeholderState = chipPlaceholderState)
                )
            },
            secondaryLabel = {
                Box(
                    modifier =
                        Modifier.fillMaxWidth()
                            .height(16.dp)
                            .padding(top = 1.dp, bottom = 1.dp)
                            .placeholder(placeholderState = chipPlaceholderState)
                )
            },
            icon = {
                Box(
                    modifier =
                        Modifier.size(ChipDefaults.IconSize).placeholder(chipPlaceholderState)
                )
                // Simulate the icon becoming ready after a period of time
                LaunchedEffect(Unit) {
                    delay(2000)
                    iconResource = R.drawable.ic_airplanemode_active_24px
                }
            },
            colors =
                PlaceholderDefaults.placeholderChipColors(
                    placeholderState = chipPlaceholderState
                ),
            modifier = Modifier.fillMaxWidth().placeholderShimmer(chipPlaceholderState)
        )
    }
}
// Simulate data being loaded after a delay
LaunchedEffect(Unit) {
    delay(2500)
    secondaryLabelText = "A secondary label"
    delay(500)
    labelText = "A label"
}
if (!chipPlaceholderState.isShowContent) {
    LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}

NOTE: The order of modifiers is important. If you are adding both Modifier.placeholder and Modifier.placeholderShimmer to the same composable then the shimmer must be before in the modifier chain. Example of Text composable with both placeholderShimmer and placeholder modifiers.

import androidx.compose.foundation.layout.width
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.Text
import androidx.wear.compose.material.placeholder
import androidx.wear.compose.material.placeholderShimmer
import androidx.wear.compose.material.rememberPlaceholderState

var labelText by remember { mutableStateOf("") }
val chipPlaceholderState = rememberPlaceholderState { labelText.isNotEmpty() }

Text(
    text = labelText,
    overflow = TextOverflow.Ellipsis,
    textAlign = TextAlign.Center,
    modifier =
        Modifier.width(90.dp)
            .placeholderShimmer(chipPlaceholderState)
            .placeholder(chipPlaceholderState)
)

// Simulate content loading
LaunchedEffect(Unit) {
    delay(3000)
    labelText = "A label"
}
if (!chipPlaceholderState.isShowContent) {
    LaunchedEffect(chipPlaceholderState) { chipPlaceholderState.startPlaceholderAnimation() }
}
Parameters
placeholderState: PlaceholderState

the current placeholder state that determine whether the placeholder shimmer should be shown.

shape: Shape = MaterialTheme.shapes.small

the shape of the component.

color: Color = MaterialTheme.colors.onSurface

the color to use in the shimmer.

fun Modifier.scrollAway(scrollState: ScrollState, offset: Dp = 0.dp): Modifier

Scroll an item vertically in/out of view based on a ScrollState. Typically used to scroll a TimeText item out of view as the user starts to scroll a vertically scrollable Column of items upwards and bring additional items into view.

Parameters
scrollState: ScrollState

The ScrollState to used as the basis for the scroll-away.

offset: Dp = 0.dp

Adjustment to the starting point for scrolling away. Positive values result in the scroll away starting later.

fun Modifier.scrollAway(
    scrollState: LazyListState,
    itemIndex: Int = 0,
    offset: Dp = 0.dp
): Modifier

Scroll an item vertically in/out of view based on a LazyListState. Typically used to scroll a TimeText item out of view as the user starts to scroll a LazyColumn of items upwards and bring additional items into view.

Parameters
scrollState: LazyListState

The LazyListState to used as the basis for the scroll-away.

itemIndex: Int = 0

The item for which the scroll offset will trigger scrolling away.

offset: Dp = 0.dp

Adjustment to the starting point for scrolling away. Positive values result in the scroll away starting later.

fun Modifier.scrollAway(
    scrollState: ScalingLazyListState,
    itemIndex: Int = 1,
    offset: Dp = 0.dp
): Modifier

Scroll an item vertically in/out of view based on a ScalingLazyListState. Typically used to scroll a TimeText item out of view as the user starts to scroll a ScalingLazyColumn of items upwards and bring additional items into view.

Parameters
scrollState: ScalingLazyListState

The ScalingLazyListState to used as the basis for the scroll-away.

itemIndex: Int = 1

The item for which the scroll offset will trigger scrolling away.

offset: Dp = 0.dp

Adjustment to the starting point for scrolling away. Positive values result in the scroll away starting later, negative values start scrolling away earlier.

fun Modifier.scrollAway(
    scrollState: ScalingLazyListState,
    itemIndex: Int = 1,
    offset: Dp = 0.dp
): Modifier

Scroll an item vertically in/out of view based on a ScalingLazyListState. Typically used to scroll a TimeText item out of view as the user starts to scroll a ScalingLazyColumn of items upwards and bring additional items into view.

Parameters
scrollState: ScalingLazyListState

The ScalingLazyListState to used as the basis for the scroll-away.

itemIndex: Int = 1

The item for which the scroll offset will trigger scrolling away.

offset: Dp = 0.dp

Adjustment to the starting point for scrolling away. Positive values result in the scroll away starting later, negative values start scrolling away earlier.

@ExperimentalWearMaterialApi
fun <T : Any?> Modifier.swipeable(
    state: SwipeableState<T>,
    anchors: Map<Float, T>,
    orientation: Orientation,
    enabled: Boolean = true,
    reverseDirection: Boolean = false,
    interactionSource: MutableInteractionSource? = null,
    thresholds: (from, to) -> ThresholdConfig = { _, _ -> FractionalThreshold(0.5f) },
    resistance: ResistanceConfig? = resistanceConfig(anchors.keys),
    velocityThreshold: Dp = VelocityThreshold
): Modifier

Enable swipe gestures between a set of predefined states.

To use this, you must provide a map of anchors (in pixels) to states (of type T). Note that this map cannot be empty and cannot have two anchors mapped to the same state.

When a swipe is detected, the offset of the SwipeableState will be updated with the swipe delta. You should use this offset to move your content accordingly (see Modifier.offsetPx). When the swipe ends, the offset will be animated to one of the anchors and when that anchor is reached, the value of the SwipeableState will also be updated to the state corresponding to the new anchor. The target anchor is calculated based on the provided positional thresholds.

Swiping is constrained between the minimum and maximum anchors. If the user attempts to swipe past these bounds, a resistance effect will be applied by default. The amount of resistance at each edge is specified by the resistance config. To disable all resistance, set it to null.

For an example of a swipeable with three states, see:

Parameters
<T : Any?>

The type of the state.

state: SwipeableState<T>

The state of the swipeable.

anchors: Map<Float, T>

Pairs of anchors and states, used to map anchors to states and vice versa.

orientation: Orientation

The orientation in which the swipeable can be swiped.

enabled: Boolean = true

Whether this swipeable is enabled and should react to the user's input.

reverseDirection: Boolean = false

Whether to reverse the direction of the swipe, so a top to bottom swipe will behave like bottom to top, and a left to right swipe will behave like right to left.

interactionSource: MutableInteractionSource? = null

Optional MutableInteractionSource that will passed on to the internal Modifier.draggable.

thresholds: (from, to) -> ThresholdConfig = { _, _ -> FractionalThreshold(0.5f) }

Specifies where the thresholds between the states are. The thresholds will be used to determine which state to animate to when swiping stops. This is represented as a lambda that takes two states and returns the threshold between them in the form of a ThresholdConfig. Note that the order of the states corresponds to the swipe direction.

resistance: ResistanceConfig? = resistanceConfig(anchors.keys)

Controls how much resistance will be applied when swiping past the bounds.

velocityThreshold: Dp = VelocityThreshold

The threshold (in dp per second) that the end velocity has to exceed in order to animate to the next state, even if the positional thresholds have not been reached.

Top-level properties

LocalContentAlpha

val LocalContentAlphaProvidableCompositionLocal<Float>

CompositionLocal containing the preferred content alpha for a given position in the hierarchy. This alpha is used for text and iconography (Text and Icon) to emphasize / de-emphasize different parts of a component. See the Material guide on Text Legibility for more information on alpha levels used by text and iconography.

See ContentAlpha for the default levels used by most Material components.

MaterialTheme sets this to ContentAlpha.high by default, as this is the default alpha for body text.

LocalContentColor

val LocalContentColorProvidableCompositionLocal<Color>

CompositionLocal containing the preferred content color for a given position in the hierarchy. This typically represents the on color for a color in Colors. For example, if the background color is Colors.surface, this color is typically set to Colors.onSurface.

This color should be used for any typography / iconography, to ensure that the color of these adjusts when the background color changes. For example, on a dark background, text should be light, and on a light background, text should be dark.

Defaults to Color.White if no color has been explicitly set.

LocalTextStyle

val LocalTextStyleProvidableCompositionLocal<TextStyle>

CompositionLocal containing the preferred TextStyle that will be used by Text components by default. To set the value for this CompositionLocal, see ProvideTextStyle which will merge any missing TextStyle properties with the existing TextStyle set in this CompositionLocal.

See also
ProvideTextStyle