Modifier

Known direct subclasses
CombinedModifier

A node in a Modifier chain.

Modifier.Companion

The companion object Modifier is the empty, default, or starter Modifier that contains no elements.

Modifier.Element

A single element contained within a Modifier chain.

Known indirect subclasses
DrawCacheModifier

DrawModifier implementation that supports building a cache of objects to be referenced across draw calls

DrawModifier

A Modifier.Element that draws into the space of the layout.

FocusEventModifier

This interface is deprecated. Use FocusEventModifierNode instead

FocusOrderModifier

This interface is deprecated. Use Modifier.focusProperties() instead

FocusRequesterModifier

This interface is deprecated. Use FocusRequesterModifierNode instead

InspectableModifier.End

This class is deprecated. This API will create more invalidations of your modifier than necessary, so it's use is discouraged.

InspectableModifier

This class is deprecated. This API will create more invalidations of your modifier than necessary, so it's use is discouraged.

LayoutModifier

A Modifier.Element that changes how its wrapped content is measured and laid out.

ModifierLocalConsumer

A Modifier that can be used to consume ModifierLocals that were provided by other modifiers to the left of this modifier, or above this modifier in the layout tree.

ModifierLocalProvider

A Modifier that can be used to provide ModifierLocals that can be read by other modifiers to the right of this modifier, or modifiers that are children of the layout node that this modifier is attached to.

ModifierNodeElement

A Modifier.Element which manages an instance of a particular Modifier.Node implementation.

OnGloballyPositionedModifier

A modifier whose onGloballyPositioned is called with the final LayoutCoordinates of the Layout when the global position of the content may have changed.

OnPlacedModifier

A modifier whose onPlaced is called after the parent LayoutModifier and parent layout has been placed and before child LayoutModifier is placed.

OnRemeasuredModifier

A modifier whose onRemeasured is called when the layout content is remeasured.

ParentDataModifier

A Modifier that provides data to the parent Layout.

PointerInputModifier

A Modifier.Element that can interact with pointer input.

RemeasurementModifier

A Modifier.Element that provides a Remeasurement object associated with the layout node the modifier is applied to.

SemanticsModifier

A Modifier.Element that adds semantics key/value for use in testing, accessibility, and similar use cases.


An ordered, immutable collection of modifier elements that decorate or add behavior to Compose UI elements. For example, backgrounds, padding and click event listeners decorate or add behavior to rows, text or buttons.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

Text(
    "Hello, World!",
    Modifier.padding(16.dp) // Outer padding; outside background
        .background(color = Color.Green) // Solid element background color
        .padding(16.dp), // Inner padding; inside background, around text
)

Modifier implementations should offer a fluent factory extension function on Modifier for creating combined modifiers by starting from existing modifiers:

import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

class FancyModifier(val level: Float) : Modifier.Element

fun Modifier.fancy(level: Float) = this.then(FancyModifier(level))

Row(Modifier.fancy(1f).padding(10.dp)) {
    // content
}

Modifier elements may be combined using then. Order is significant; modifier elements that appear first will be applied first.

Composables that accept a Modifier as a parameter to be applied to the whole component represented by the composable function should name the parameter modifier and assign the parameter a default value of Modifier. It should appear as the first optional parameter in the parameter list; after all required parameters (except for trailing lambda parameters) but before any other parameters with default values. Any default modifiers desired by a composable function should come after the modifier parameter's value in the composable function's implementation, keeping Modifier as the default parameter value. For example:

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun PaddedColumn(modifier: Modifier = Modifier) {
    Column(modifier.padding(10.dp)) {
        // ...
    }
}

The pattern above allows default modifiers to still be applied as part of the chain if a caller also supplies unrelated modifiers.

Composables that accept modifiers to be applied to a specific subcomponent foo should name the parameter fooModifier and follow the same guidelines above for default values and behavior. Subcomponent modifiers should be grouped together and follow the parent composable's modifier. For example:

import androidx.compose.foundation.layout.Row
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier

@Composable
fun ButtonBar(
    onOk: () -> Unit,
    onCancel: () -> Unit,
    modifier: Modifier = Modifier,
    buttonModifier: Modifier = Modifier,
) {
    Row(modifier) {
        Button(onCancel, buttonModifier) { Text("Cancel") }
        Button(onOk, buttonModifier) { Text("Ok") }
    }
}

Summary

Nested types

The companion object Modifier is the empty, default, or starter Modifier that contains no elements.

A single element contained within a Modifier chain.

The longer-lived object that is created for each Modifier.Element applied to a androidx.compose.ui.layout.Layout.

Public companion functions

open Boolean
all(predicate: (Modifier.Element) -> Boolean)

Returns true if predicate returns true for all Elements in this Modifier or if this Modifier contains no Elements.

Cmn
open Boolean
any(predicate: (Modifier.Element) -> Boolean)

Returns true if predicate returns true for any Element in this Modifier.

Cmn
open R
<R : Any?> foldIn(initial: R, operation: (Modifier.Element, R) -> R)

Accumulates a value starting with initial and applying operation to the current value and each element from outside in.

Cmn
open R
<R : Any?> foldOut(initial: R, operation: (Modifier.Element, R) -> R)

Accumulates a value starting with initial and applying operation to the current value and each element from inside out.

Cmn
open infix Modifier
then(other: Modifier)

Concatenates this modifier with another.

Cmn
open String
Cmn

Public functions

Boolean
all(predicate: (Modifier.Element) -> Boolean)

Returns true if predicate returns true for all Elements in this Modifier or if this Modifier contains no Elements.

Cmn
Boolean
any(predicate: (Modifier.Element) -> Boolean)

Returns true if predicate returns true for any Element in this Modifier.

Cmn
R
<R : Any?> foldIn(initial: R, operation: (Modifier.Element, R) -> R)

Accumulates a value starting with initial and applying operation to the current value and each element from outside in.

Cmn
R
<R : Any?> foldOut(initial: R, operation: (Modifier.Element, R) -> R)

Accumulates a value starting with initial and applying operation to the current value and each element from inside out.

Cmn
open infix Modifier
then(other: Modifier)

Concatenates this modifier with another.

Cmn

Extension functions

Modifier
Modifier.paddingFrom(alignmentLine: AlignmentLine, before: Dp, after: Dp)

A Modifier that can add padding to position the content according to specified distances from its bounds to an alignment line.

Cmn
Modifier
Modifier.paddingFrom(
    alignmentLine: AlignmentLine,
    before: TextUnit,
    after: TextUnit
)

A Modifier that can add padding to position the content according to specified distances from its bounds to an alignment line.

Cmn
Modifier
Modifier.paddingFromBaseline(top: Dp, bottom: Dp)

A Modifier that positions the content in a layout such that the distance from the top of the layout to the baseline of the first line of text in the content is top, and the distance from the baseline of the last line of text in the content to the bottom of the layout is bottom.

Cmn
Modifier

A Modifier that positions the content in a layout such that the distance from the top of the layout to the baseline of the first line of text in the content is top, and the distance from the baseline of the last line of text in the content to the bottom of the layout is bottom.

Cmn
Modifier

Draw content with modified alpha that may be less than 1.

Cmn
Modifier
<T : Any?> Modifier.anchoredDraggable(
    state: AnchoredDraggableState<T>,
    orientation: Orientation,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    overscrollEffect: OverscrollEffect?,
    flingBehavior: FlingBehavior?
)

Enable drag gestures between a set of predefined values.

Cmn
Modifier
<T : Any?> Modifier.anchoredDraggable(
    state: AnchoredDraggableState<T>,
    orientation: Orientation,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    overscrollEffect: OverscrollEffect?,
    startDragImmediately: Boolean,
    flingBehavior: FlingBehavior?
)

This function is deprecated. startDragImmediately has been removed without replacement.

Cmn
Modifier
<T : Any?> Modifier.anchoredDraggable(
    state: AnchoredDraggableState<T>,
    reverseDirection: Boolean,
    orientation: Orientation,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    overscrollEffect: OverscrollEffect?,
    flingBehavior: FlingBehavior?
)

Enable drag gestures between a set of predefined values.

Cmn
Modifier
<T : Any?> Modifier.anchoredDraggable(
    state: AnchoredDraggableState<T>,
    reverseDirection: Boolean,
    orientation: Orientation,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    overscrollEffect: OverscrollEffect?,
    startDragImmediately: Boolean,
    flingBehavior: FlingBehavior?
)

This function is deprecated. startDragImmediately has been removed without replacement.

Cmn
Modifier

This function is deprecated. Replaced by overload with a callback for obtain a transfer data,start detection is performed by Compose itself

android
Modifier
Modifier.animateBounds(
    lookaheadScope: LookaheadScope,
    modifier: Modifier,
    boundsTransform: BoundsTransform,
    animateMotionFrameOfReference: Boolean
)

Modifier to animate layout changes (position and/or size) that occur within a LookaheadScope.

Cmn
Modifier
Modifier.animateContentSize(
    animationSpec: FiniteAnimationSpec<IntSize>,
    finishedListener: ((initialValue: IntSize, targetValue: IntSize) -> Unit)?
)

This modifier animates its own size when its child modifier (or the child composable if it is already at the tail of the chain) changes size.

Cmn
Modifier
Modifier.animateContentSize(
    animationSpec: FiniteAnimationSpec<IntSize>,
    alignment: Alignment,
    finishedListener: ((initialValue: IntSize, targetValue: IntSize) -> Unit)?
)

This modifier animates its own size when its child modifier (or the child composable if it is already at the tail of the chain) changes size.

Cmn
Modifier
Modifier.aspectRatio(
    ratio: @FloatRange(from = 0.0, fromInclusive = false) Float,
    matchHeightConstraintsFirst: Boolean
)

Attempts to size the content to match a specified aspect ratio by trying to match one of the incoming constraints in the following order: Constraints.maxWidth, Constraints.maxHeight, Constraints.minWidth, Constraints.minHeight if matchHeightConstraintsFirst is false (which is the default), or Constraints.maxHeight, Constraints.maxWidth, Constraints.minHeight, Constraints.minWidth if matchHeightConstraintsFirst is true.

Cmn
Modifier

Set autofill hint with contentType.

Cmn
Modifier
Modifier.background(color: Color, shape: Shape)

Draws shape with a solid color behind the content.

Cmn
Modifier
Modifier.background(
    brush: Brush,
    shape: Shape,
    alpha: @FloatRange(from = 0.0, to = 1.0) Float
)

Draws shape with brush behind the content.

Cmn
Modifier
Modifier.basicMarquee(
    iterations: Int,
    animationMode: MarqueeAnimationMode,
    repeatDelayMillis: Int,
    initialDelayMillis: Int,
    spacing: MarqueeSpacing,
    velocity: Dp
)

Applies an animated marquee effect to the modified content if it's too wide to fit in the available space.

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

Handles swipe to dismiss from the edge of the viewport.

android
Modifier
Modifier.blur(radius: Dp, edgeTreatment: BlurredEdgeTreatment)

Draw content blurred with the specified radii.

Cmn
Modifier
Modifier.blur(
    radiusX: Dp,
    radiusY: Dp,
    edgeTreatment: BlurredEdgeTreatment
)

Draw content blurred with the specified radii.

Cmn
Modifier
Modifier.border(border: BorderStroke, shape: Shape)

Modify element to add border with appearance specified with a border and a shape and clip it.

Cmn
Modifier
Modifier.border(width: Dp, brush: Brush, shape: Shape)

Modify element to add border with appearance specified with a width, a brush and a shape and clip it.

Cmn
Modifier
Modifier.border(width: Dp, color: Color, shape: Shape)

Modify element to add border with appearance specified with a width, a color and a shape and clip it.

Cmn
Modifier
Modifier.bringIntoViewRequester(
    bringIntoViewRequester: BringIntoViewRequester
)

Modifier that can be used to send bringIntoView requests.

Cmn
Modifier

This function is deprecated. Use BringIntoViewModifierNode instead

Cmn
Modifier
Modifier.clickable(
    enabled: Boolean,
    onClickLabel: String?,
    role: Role?,
    interactionSource: MutableInteractionSource?,
    onClick: () -> Unit
)

Configure component to receive clicks via input or accessibility "click" event.

Cmn
Modifier
Modifier.clickable(
    interactionSource: MutableInteractionSource?,
    indication: Indication?,
    enabled: Boolean,
    onClickLabel: String?,
    role: Role?,
    onClick: () -> Unit
)

Configure component to receive clicks via input or accessibility "click" event.

Cmn
Modifier
Modifier.combinedClickable(
    enabled: Boolean,
    onClickLabel: String?,
    role: Role?,
    onLongClickLabel: String?,
    onLongClick: (() -> Unit)?,
    onDoubleClick: (() -> Unit)?,
    hapticFeedbackEnabled: Boolean,
    interactionSource: MutableInteractionSource?,
    onClick: () -> Unit
)

Configure component to receive clicks, double clicks and long clicks via input or accessibility "click" event.

Cmn
Modifier
Modifier.combinedClickable(
    interactionSource: MutableInteractionSource?,
    indication: Indication?,
    enabled: Boolean,
    onClickLabel: String?,
    role: Role?,
    onLongClickLabel: String?,
    onLongClick: (() -> Unit)?,
    onDoubleClick: (() -> Unit)?,
    hapticFeedbackEnabled: Boolean,
    onClick: () -> Unit
)

Configure component to receive clicks, double clicks and long clicks via input or accessibility "click" event.

Cmn
Modifier

Clip the content to shape.

Cmn
Modifier

Clip the content to the bounds of a layer defined at this modifier.

Cmn
Modifier

Clips bounds of scrollable container on main axis while leaving space for background effects (like shadows) on cross axis.

Cmn
Modifier
Modifier.composed(
    inspectorInfo: InspectorInfo.() -> Unit,
    factory: @Composable Modifier.() -> Modifier
)

Declare a just-in-time composition of a Modifier that will be composed for each element it modifies.

Cmn
Modifier
Modifier.composed(
    fullyQualifiedName: String,
    key1: Any?,
    inspectorInfo: InspectorInfo.() -> Unit,
    factory: @Composable Modifier.() -> Modifier
)

Declare a just-in-time composition of a Modifier that will be composed for each element it modifies.

Cmn
Modifier
Modifier.composed(
    fullyQualifiedName: String,
    vararg keys: Any?,
    inspectorInfo: InspectorInfo.() -> Unit,
    factory: @Composable Modifier.() -> Modifier
)

Declare a just-in-time composition of a Modifier that will be composed for each element it modifies.

Cmn
Modifier
Modifier.composed(
    fullyQualifiedName: String,
    key1: Any?,
    key2: Any?,
    inspectorInfo: InspectorInfo.() -> Unit,
    factory: @Composable Modifier.() -> Modifier
)

Declare a just-in-time composition of a Modifier that will be composed for each element it modifies.

Cmn
Modifier
Modifier.composed(
    fullyQualifiedName: String,
    key1: Any?,
    key2: Any?,
    key3: Any?,
    inspectorInfo: InspectorInfo.() -> Unit,
    factory: @Composable Modifier.() -> Modifier
)

Declare a just-in-time composition of a Modifier that will be composed for each element it modifies.

Cmn
Modifier
Modifier.layoutId(layoutId: String, tag: String?)

Alternative to androidx.compose.ui.layout.layoutId that enables the use of tag.

android
Modifier

Provides contentColor for text and iconography to consume.

android
Modifier
Modifier.depthEffect(depthEffect: DepthEffect?, shape: Shape)

Renders shadows for the provided depthEffect.

android
Modifier

A Modifier that allows an element it is applied to be treated like a source for drag and drop operations.

Cmn
Modifier
@ExperimentalFoundationApi
Modifier.dragAndDropSource(
    drawDragDecoration: DrawScope.() -> Unit,
    block: suspend DragAndDropSourceScope.() -> Unit
)

This function is deprecated. Replaced by overload with a callback for obtain a transfer data,start detection is performed by Compose itself

android
Modifier
Modifier.dragAndDropSource(
    drawDragDecoration: DrawScope.() -> Unit,
    transferData: (Offset) -> DragAndDropTransferData?
)

A Modifier that allows an element it is applied to be treated like a source for drag and drop operations.

Cmn
Modifier
Modifier.dragAndDropTarget(
    shouldStartDragAndDrop: (startEvent: DragAndDropEvent) -> Boolean,
    target: DragAndDropTarget
)

A modifier that allows for receiving from a drag and drop gesture.

Cmn
Modifier
Modifier.draggable2D(
    state: Draggable2DState,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    startDragImmediately: Boolean,
    onDragStarted: (startedPosition: Offset) -> Unit,
    onDragStopped: (velocity: Velocity) -> Unit,
    reverseDirection: Boolean
)

Configure touch dragging for the UI element in both orientations.

Cmn
Modifier
Modifier.draggable(
    state: DraggableState,
    orientation: Orientation,
    enabled: Boolean,
    interactionSource: MutableInteractionSource?,
    startDragImmediately: Boolean,
    onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit,
    onDragStopped: suspend CoroutineScope.(velocity: Float) -> Unit,
    reverseDirection: Boolean
)

Configure touch dragging for the UI element in a single Orientation.

Cmn
Modifier

Draw into a Canvas behind the modified content.

Cmn
Modifier

Draw into a DrawScope with content that is persisted across draw calls as long as the size of the drawing area is the same or any state objects that are read have not changed.

Cmn
Modifier

Creates a DrawModifier that allows the developer to draw before or after the layout's contents.

Cmn
Modifier

This function is deprecated. Use systemGestureExclusion

android
Modifier

This function is deprecated. Use systemGestureExclusion

android
Modifier
@ExperimentalMaterial3ExpressiveApi
Modifier.animateFloatingActionButton(
    visible: Boolean,
    alignment: Alignment,
    targetScale: Float,
    scaleAnimationSpec: AnimationSpec<Float>?,
    alphaAnimationSpec: AnimationSpec<Float>?
)

Apply this modifier to a FloatingActionButton to show or hide it with an animation, typically based on the app's main content scrolling.

Cmn
Modifier
Modifier.onFocusChanged(onFocusChanged: (FocusState) -> Unit)

Add this modifier to a component to observe focus state events.

Cmn
Modifier
Modifier.onFocusEvent(onFocusEvent: (FocusState) -> Unit)

Add this modifier to a component to observe focus state events.

Cmn
Modifier

This function is deprecated. Replaced by focusTarget

Cmn
Modifier

Add this modifier to a component to make it focusable.

Cmn
Modifier
Modifier.focusOrder(focusOrderReceiver: FocusOrder.() -> Unit)

This function is deprecated. Use focusProperties() instead

Cmn
Modifier

This function is deprecated. Use focusRequester() instead

Cmn
Modifier
Modifier.focusOrder(
    focusRequester: FocusRequester,
    focusOrderReceiver: FocusOrder.() -> Unit
)

This function is deprecated. Use focusProperties() and focusRequester() instead

Cmn
Modifier

This modifier allows you to specify properties that are accessible to focusTargets further down the modifier chain or on child layout nodes.

Cmn
Modifier

Add this modifier to a component to request changes to focus.

Cmn
Modifier

This modifier can be used to save and restore focus to a focus group.

Cmn
Modifier

This function is deprecated. Use focusRestorer(FocusRequester) instead

Cmn
Modifier

Creates a focus group or marks this component as a focus group.

Cmn
Modifier
Modifier.focusable(
    enabled: Boolean,
    interactionSource: MutableInteractionSource?
)

Configure component to be focusable via focus system or accessibility "focus" event.

Cmn
Modifier

Calls onPositioned whenever the bounds of the currently-focused area changes.

Cmn
Modifier

Set a requested frame rate on Composable

Cmn
Modifier
Modifier.preferredFrameRate(
    frameRate: @FloatRange(from = 0.0, to = 360.0) Float
)

Set a requested frame rate on Composable

Cmn
Modifier

A Modifier.Node that makes content draw into a draw layer.

Cmn
Modifier
Modifier.graphicsLayer(
    scaleX: Float,
    scaleY: Float,
    alpha: Float,
    translationX: Float,
    translationY: Float,
    shadowElevation: Float,
    rotationX: Float,
    rotationY: Float,
    rotationZ: Float,
    cameraDistance: Float,
    transformOrigin: TransformOrigin,
    shape: Shape,
    clip: Boolean,
    renderEffect: RenderEffect?,
    ambientShadowColor: Color,
    spotShadowColor: Color,
    compositingStrategy: CompositingStrategy,
    blendMode: BlendMode,
    colorFilter: ColorFilter?
)

A Modifier.Element that makes content draw into a draw layer.

Cmn
Modifier

A Modifier.Element that adds a draw layer such that tooling can identify an element in the drawn image.

Cmn
Modifier

Configures an element to act as a handwriting detector which detects stylus handwriting and delegates handling of the recognised text to another element.

android
Modifier

Configures an element to act as a stylus handwriting handler which can handle text input from a handwriting session which was triggered by stylus handwriting on a handwriting detector.

android
Modifier

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

android
Modifier

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

android
Modifier
Modifier.hoverable(
    interactionSource: MutableInteractionSource,
    enabled: Boolean
)

Configure component to be hoverable via pointer enter/exit events.

Cmn
Modifier
Modifier.indication(
    interactionSource: InteractionSource,
    indication: Indication?
)

Draws visual effects for this component when interactions occur.

Cmn
Modifier
Modifier.onIndirectPointerGesture(
    enabled: Boolean,
    onSwipeForward: (() -> Unit)?,
    onSwipeBackward: (() -> Unit)?,
    onClick: (() -> Unit)?
)

A Modifier that detects high-level click and horizontal swipe gestures from an IndirectPointerEvent source.

android
inline Modifier
Modifier.inspectable(
    noinline inspectorInfo: InspectorInfo.() -> Unit,
    factory: Modifier.() -> Modifier
)

This function is deprecated. This API will create more invalidations of your modifier than necessary, so it's use is discouraged.

Cmn
Modifier

Reserves at least 48.dp in size to disambiguate touch interactions if the element would measure smaller.

Cmn
Modifier

Reserves at least 48.dp in size to disambiguate touch interactions if the element would measure smaller.

Cmn
Modifier

Reserves at least 48.dp in size to disambiguate touch interactions if the element would measure smaller.

android
Modifier
Modifier.height(intrinsicSize: IntrinsicSize)

Declare the preferred height of the content to be the same as the min or max intrinsic height of the content.

Cmn
Modifier

Declare the height of the content to be exactly the same as the min or max intrinsic height of the content.

Cmn
Modifier

Declare the width of the content to be exactly the same as the min or max intrinsic width of the content.

Cmn
Modifier
Modifier.width(intrinsicSize: IntrinsicSize)

Declare the preferred width of the content to be the same as the min or max intrinsic width of the content.

Cmn
Modifier

A modifier that keeps the device screen on as long as it is part of the composition on supported platforms.

Cmn
Modifier
Modifier.onKeyEvent(onKeyEvent: (KeyEvent) -> Boolean)

Adding this modifier to the modifier parameter of a component will allow it to intercept hardware key events when it (or one of its children) is focused.

Cmn
Modifier
Modifier.onPreviewKeyEvent(onPreviewKeyEvent: (KeyEvent) -> Boolean)

Adding this modifier to the modifier parameter of a component will allow it to intercept hardware key events when it (or one of its children) is focused.

Cmn
Modifier

This will map the RelativeLayoutBounds of the modifier into the provided LayoutBoundsHolder.

Cmn
Modifier
Modifier.layoutId(layoutId: Any)

Tag the element with layoutId to identify the element within its parent.

Cmn
Modifier

Creates a LayoutModifier that allows changing how the wrapped element is measured and laid out.

Cmn
Modifier
Modifier.approachLayout(
    isMeasurementApproachInProgress: (lookaheadSize: IntSize) -> Boolean,
    isPlacementApproachInProgress: Placeable.PlacementScope.(lookaheadCoordinates: LayoutCoordinates) -> Boolean,
    approachMeasure: ApproachMeasureScope.(measurable: Measurable, constraints: Constraints) -> MeasureResult
)

Creates an approach layout intended to help gradually approach the destination layout calculated in the lookahead pass.

Cmn
Modifier
Modifier.magnifier(
    sourceCenter: Density.() -> Offset,
    magnifierCenter: (Density.() -> Offset)?,
    onSizeChanged: ((DpSize) -> Unit)?,
    zoom: Float,
    size: DpSize,
    cornerRadius: Dp,
    elevation: Dp,
    clip: Boolean
)

Shows a Magnifier widget that shows an enlarged version of the content at sourceCenter relative to the current layout node.

android
Modifier

A Modifier that can be used to consume ModifierLocals that were provided by other modifiers to the left of this modifier, or above this modifier in the layout tree.

Cmn
Modifier
<T : Any?> Modifier.modifierLocalProvider(
    key: ProvidableModifierLocal<T>,
    value: () -> T
)

A Modifier that can be used to provide ModifierLocals that can be read by other modifiers to the right of this modifier, or modifiers that are children of the layout node that this modifier is attached to.

Cmn
Modifier
Modifier.nestedScroll(
    connection: NestedScrollConnection,
    dispatcher: NestedScrollDispatcher?
)

Modify element to make it participate in the nested scrolling hierarchy.

Cmn
Modifier

Offset the content by offset px.

Cmn
Modifier

Offset the content by (x dp, y dp).

Cmn
Modifier

Offset the content by offset px.

Cmn
Modifier
Modifier.offset(x: Dp, y: Dp)

Offset the content by (x dp, y dp).

Cmn
Modifier
Modifier.onFirstVisible(
    minDurationMs: @IntRange(from = 0) Long,
    minFractionVisible: @FloatRange(from = 0.0, to = 1.0) Float,
    viewportBounds: LayoutBoundsHolder?,
    callback: () -> Unit
)

This function is deprecated. This modifier is deprecated as its behavior is misleading and doesn't always follow the contract claimed by the name.

Cmn
Modifier
Modifier.onGloballyPositioned(
    onGloballyPositioned: (LayoutCoordinates) -> Unit
)

Invoke onGloballyPositioned with the LayoutCoordinates of the element when the global position of the content may have changed.

Cmn
Modifier
Modifier.onLayoutRectChanged(
    throttleMillis: Long,
    debounceMillis: Long,
    callback: (RelativeLayoutBounds) -> Unit
)

Invokes callback with the position of this layout node relative to the coordinate system of the root of the composition, as well as in screen coordinates and window coordinates.

Cmn
Modifier

Invoke onPlaced after the parent LayoutModifier and parent layout has been placed and before child LayoutModifier is placed.

Cmn
Modifier
Modifier.onSizeChanged(onSizeChanged: (IntSize) -> Unit)

Invoked with the size of the modified Compose UI element when the element is first measured or when the size of the element changes.

Cmn
Modifier
Modifier.onVisibilityChanged(
    minDurationMs: @IntRange(from = 0) Long,
    minFractionVisible: @FloatRange(from = 0.0, to = 1.0) Float,
    viewportBounds: LayoutBoundsHolder?,
    callback: (Boolean) -> Unit
)

Registers a callback to monitor whether or not the node is inside of the viewport of the window or not.

Cmn
Modifier
@Composable
Modifier.oneHandedGesture(
    action: GestureAction,
    key: String?,
    priority: GesturePriority,
    enabledInAmbient: Boolean,
    interactionSource: MutableInteractionSource?,
    onShowIndicator: () -> Unit,
    onGesture: suspend () -> Unit
)

Registers a gesture handler.

android
Modifier
Modifier.overscroll(overscrollEffect: OverscrollEffect?)

Renders overscroll from the provided overscrollEffect.

Cmn
Modifier
Modifier.absolutePadding(left: Dp, top: Dp, right: Dp, bottom: Dp)

Apply additional space along each edge of the content in Dp: left, top, right and bottom.

Cmn
Modifier

Apply all dp of additional space along each edge of the content, left, top, right and bottom.

Cmn
Modifier
Modifier.padding(paddingValues: PaddingValues)

Apply PaddingValues to the component as additional space along each edge of the content's left, top, right and bottom.

Cmn
Modifier
Modifier.padding(horizontal: Dp, vertical: Dp)

Apply horizontal dp space along the left and right edges of the content, and vertical dp space along the top and bottom edges.

Cmn
Modifier
Modifier.padding(start: Dp, top: Dp, end: Dp, bottom: Dp)

Apply additional space along each edge of the content in Dp: start, top, end and bottom.

Cmn
Modifier
Modifier.paint(
    painter: Painter,
    sizeToIntrinsics: Boolean,
    alignment: Alignment,
    contentScale: ContentScale,
    alpha: Float,
    colorFilter: ColorFilter?
)

Paint the content using painter.

Cmn
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.

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

Modifier.placeholder draws a skeleton shape over a component, for situations when no provisional content (such as cached data) is available.

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

Modifier to draw a placeholder shimmer over a component.

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

Modifier.placeholderShimmer draws a periodic shimmer over content, indicating to the user that contents are loading or potentially out of date.

android
Modifier
Modifier.pointerHoverIcon(
    icon: PointerIcon,
    overrideDescendants: Boolean
)

Modifier that lets a developer define a pointer icon to display when the cursor is hovered over the element.

Cmn
Modifier
Modifier.stylusHoverIcon(
    icon: PointerIcon,
    overrideDescendants: Boolean,
    touchBoundsExpansion: DpTouchBoundsExpansion?
)

Modifier that lets a developer define a pointer icon to display when a stylus is hovered over the element.

Cmn
Modifier
Modifier.motionEventSpy(watcher: (motionEvent: MotionEvent) -> Unit)

Calls watcher with each MotionEvent that the layout area or any child pointerInput receives.

android
Modifier
Modifier.pointerInteropFilter(
    requestDisallowInterceptTouchEvent: RequestDisallowInterceptTouchEvent?,
    onTouchEvent: (MotionEvent) -> Boolean
)

A special PointerInputModifier that provides access to the underlying MotionEvents originally dispatched to Compose.

android
Modifier

Mark the layout rectangle as preferring to stay clear of floating windows.

android
Modifier

Mark a rectangle within the local layout coordinates preferring to stay clear of floating windows.

android
Modifier

Contains the semantics required for an indeterminate progress indicator, that represents the fact of the in-progress operation.

Cmn
Modifier
Modifier.progressSemantics(
    value: Float,
    valueRange: ClosedFloatingPointRange<Float>,
    steps: @IntRange(from = 0) Int
)

Contains the semantics required for a determinate progress indicator or the progress part of a slider, that represents progress within valueRange.

Cmn
Modifier

A modifier for translating the position and scaling the size of a pull-to-refresh indicator based on the given PullRefreshState.

Cmn
Modifier

A nested scroll modifier that provides scroll events to state.

Cmn
Modifier
@ExperimentalMaterialApi
Modifier.pullRefresh(
    onPull: (pullDelta: Float) -> Float,
    onRelease: suspend (flingVelocity: Float) -> Float,
    enabled: Boolean
)

A nested scroll modifier that provides onPull and onRelease callbacks to aid building custom pull refresh components.

Cmn
Modifier
Modifier.pullToRefresh(
    isRefreshing: Boolean,
    state: PullToRefreshState,
    enabled: Boolean,
    threshold: Dp,
    onRefresh: () -> Unit
)

A Modifier that adds nested scroll to a container to support a pull-to-refresh gesture.

Cmn
Modifier
Modifier.rangeSemantics(
    value: Float,
    enabled: Boolean,
    onValueChange: (Float) -> Unit,
    valueRange: ClosedFloatingPointRange<Float>,
    steps: Int
)

Modifier to add semantics signifying progress of the Stepper/Slider.

android
Modifier

Configures the current node and any children nodes as a Content Receiver.

Cmn
Modifier
Modifier.onPreRotaryScrollEvent(
    onPreRotaryScrollEvent: (RotaryScrollEvent) -> Boolean
)

Adding this modifier to the modifier parameter of a component will allow it to intercept RotaryScrollEvents if it (or one of its children) is focused.

Cmn
Modifier
Modifier.onRotaryScrollEvent(
    onRotaryScrollEvent: (RotaryScrollEvent) -> Boolean
)

Adding this modifier to the modifier parameter of a component will allow it to intercept RotaryScrollEvents if it (or one of its children) is focused.

Cmn
Modifier
Modifier.rotaryScrollable(
    behavior: RotaryScrollableBehavior,
    focusRequester: FocusRequester,
    reverseDirection: Boolean,
    overscrollEffect: OverscrollEffect?
)

A modifier which connects rotary events with scrollable containers such as Column, LazyList and others.

android
Modifier
Modifier.rotate(degrees: Float)

Sets the degrees the view is rotated around the center of the composable.

Cmn
Modifier

Fits the contents within rulers.

Cmn
Modifier

If one of the Rulers in rulers has a value within the bounds of the Layout, this sizes the content to that Ruler and the edge.

Cmn
Modifier

Scale the contents of both the horizontal and vertical axis uniformly by the same scale factor.

Cmn
Modifier
Modifier.scale(scaleX: Float, scaleY: Float)

Scale the contents of the composable by the following scale factors along the horizontal and vertical axis respectively.

Cmn
Modifier
Modifier.scrollAway(
    scrollInfoProvider: ScrollInfoProvider,
    screenStage: () -> ScreenStage
)

Scroll an item vertically in/out of view based on scroll state provided by a scrolling list.

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

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

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

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

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

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

android
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

android
Modifier
Modifier.horizontalScroll(
    state: ScrollState,
    enabled: Boolean,
    flingBehavior: FlingBehavior?,
    reverseScrolling: Boolean
)

Modify element to allow to scroll horizontally when width of the content is bigger than max constraints allow.

Cmn
Modifier
Modifier.horizontalScroll(
    state: ScrollState,
    overscrollEffect: OverscrollEffect?,
    enabled: Boolean,
    flingBehavior: FlingBehavior?,
    reverseScrolling: Boolean
)

Modify element to allow to scroll horizontally when width of the content is bigger than max constraints allow.

Cmn
Modifier
Modifier.verticalScroll(
    state: ScrollState,
    enabled: Boolean,
    flingBehavior: FlingBehavior?,
    reverseScrolling: Boolean
)

Modify element to allow to scroll vertically when height of the content is bigger than max constraints allow.

Cmn
Modifier
Modifier.verticalScroll(
    state: ScrollState,
    overscrollEffect: OverscrollEffect?,
    enabled: Boolean,
    flingBehavior: FlingBehavior?,
    reverseScrolling: Boolean
)

Modify element to allow to scroll vertically when height of the content is bigger than max constraints allow.

Cmn
Modifier
Modifier.scrollable2D(
    state: Scrollable2DState,
    enabled: Boolean,
    overscrollEffect: OverscrollEffect?,
    flingBehavior: FlingBehavior?,
    interactionSource: MutableInteractionSource?
)

Configure touch scrolling and flinging for the UI element in both XY orientations.

Cmn
Modifier
Modifier.scrollableArea(
    state: ScrollableState,
    orientation: Orientation,
    enabled: Boolean,
    reverseScrolling: Boolean,
    flingBehavior: FlingBehavior?,
    interactionSource: MutableInteractionSource?,
    bringIntoViewSpec: BringIntoViewSpec?
)

Configure a component to act as a scrollable area.

Cmn
Modifier
Modifier.scrollableArea(
    state: ScrollableState,
    orientation: Orientation,
    overscrollEffect: OverscrollEffect?,
    enabled: Boolean,
    reverseScrolling: Boolean,
    flingBehavior: FlingBehavior?,
    interactionSource: MutableInteractionSource?,
    bringIntoViewSpec: BringIntoViewSpec?
)

Configure a component to act as a scrollable area.

Cmn
Modifier
Modifier.scrollable(
    state: ScrollableState,
    orientation: Orientation,
    enabled: Boolean,
    reverseDirection: Boolean,
    flingBehavior: FlingBehavior?,
    interactionSource: MutableInteractionSource?
)

Configure touch scrolling and flinging for the UI element in a single Orientation.

Cmn
Modifier
Modifier.scrollable(
    state: ScrollableState,
    orientation: Orientation,
    overscrollEffect: OverscrollEffect?,
    enabled: Boolean,
    reverseDirection: Boolean,
    flingBehavior: FlingBehavior?,
    interactionSource: MutableInteractionSource?,
    bringIntoViewSpec: BringIntoViewSpec?
)

Configure touch scrolling and flinging for the UI element in a single Orientation.

Cmn
Modifier

Use this modifier to group a list of selectable items like Tabs or RadioButtons together for accessibility purpose.

Cmn
Modifier
Modifier.selectable(
    selected: Boolean,
    enabled: Boolean,
    role: Role?,
    interactionSource: MutableInteractionSource?,
    onClick: () -> Unit
)

Configure component to be selectable, usually as a part of a mutually exclusive group, where only one item can be selected at any point in time.

Cmn
Modifier
Modifier.selectable(
    selected: Boolean,
    interactionSource: MutableInteractionSource?,
    indication: Indication?,
    enabled: Boolean,
    role: Role?,
    onClick: () -> Unit
)

Configure component to be selectable, usually as a part of a mutually exclusive group, where only one item can be selected at any point in time.

Cmn
Modifier

Clears the semantics of all the descendant nodes and sets new semantics.

Cmn
Modifier
Modifier.semantics(mergeDescendants: Boolean, properties: SemanticsPropertyReceiver.() -> Unit)

Add semantics key/value pairs to the layout node, for use in testing, accessibility, etc.

Cmn
Modifier
Modifier.sensitiveContent(isContentSensitive: Boolean)

This modifier hints that the composable renders sensitive content (i.e. username, password, credit card etc) on the screen, and the content should be protected during screen share in supported environments.

Cmn
Modifier
Modifier.dropShadow(shape: Shape, block: DropShadowScope.() -> Unit)

Draws a drop shadow behind the rest of the content with the geometry specified by the given shape and the shadow properties defined the DropShadowScope.

Cmn
Modifier
Modifier.dropShadow(shape: Shape, shadow: Shadow)

Draws a drop shadow behind the rest of the content with the geometry specified by the given shape and the shadow properties defined by the Shadow.

Cmn
Modifier

Draws an inner shadow behind the rest of the content with the geometry specified by the given shape and the shadow properties defined the InnerShadowScope.

Cmn
Modifier
Modifier.innerShadow(shape: Shape, shadow: Shadow)

Draws an inner shadow on top of the rest of the content with the geometry specified by the given shape and the shadow properties defined by the Shadow.

Cmn
Modifier
Modifier.shadow(
    elevation: Dp,
    shape: Shape,
    clip: Boolean,
    ambientColor: Color,
    spotColor: Color
)

Creates a graphicsLayer that draws a shadow.

Cmn
Modifier
Modifier.defaultMinSize(minWidth: Dp, minHeight: Dp)

Constrain the size of the wrapped layout only when it would be otherwise unconstrained: the minWidth and minHeight constraints are only applied when the incoming corresponding constraint is 0.

Cmn
Modifier
Modifier.fillMaxHeight(fraction: @FloatRange(from = 0.0, to = 1.0) Float)

Have the content fill (possibly only partially) the Constraints.maxHeight of the incoming measurement constraints, by setting the minimum height and the maximum height to be equal to the maximum height multiplied by fraction.

Cmn
Modifier
Modifier.fillMaxSize(fraction: @FloatRange(from = 0.0, to = 1.0) Float)

Have the content fill (possibly only partially) the Constraints.maxWidth and Constraints.maxHeight of the incoming measurement constraints, by setting the minimum width and the maximum width to be equal to the maximum width multiplied by fraction, as well as the minimum height and the maximum height to be equal to the maximum height multiplied by fraction.

Cmn
Modifier
Modifier.fillMaxWidth(fraction: @FloatRange(from = 0.0, to = 1.0) Float)

Have the content fill (possibly only partially) the Constraints.maxWidth of the incoming measurement constraints, by setting the minimum width and the maximum width to be equal to the maximum width multiplied by fraction.

Cmn
Modifier
Modifier.height(height: Dp)

Declare the preferred height of the content to be exactly heightdp.

Cmn
Modifier
Modifier.heightIn(min: Dp, max: Dp)

Constrain the height of the content to be between mindp and maxdp as permitted by the incoming measurement Constraints.

Cmn
Modifier

Declare the height of the content to be exactly heightdp.

Cmn
Modifier

Constrain the height of the content to be between mindp and maxdp.

Cmn
Modifier

Declare the size of the content to be exactly sizedp width and height.

Cmn
Modifier

Declare the size of the content to be exactly size.

Cmn
Modifier
Modifier.requiredSize(width: Dp, height: Dp)

Declare the size of the content to be exactly widthdp and heightdp.

Cmn
Modifier
Modifier.requiredSizeIn(
    minWidth: Dp,
    minHeight: Dp,
    maxWidth: Dp,
    maxHeight: Dp
)

Constrain the width of the content to be between minWidthdp and maxWidthdp, and the height of the content to be between minHeightdp and maxHeightdp.

Cmn
Modifier

Declare the width of the content to be exactly widthdp.

Cmn
Modifier
Modifier.requiredWidthIn(min: Dp, max: Dp)

Constrain the width of the content to be between mindp and maxdp.

Cmn
Modifier
Modifier.size(size: Dp)

Declare the preferred size of the content to be exactly sizedp square.

Cmn
Modifier

Declare the preferred size of the content to be exactly size.

Cmn
Modifier
Modifier.size(width: Dp, height: Dp)

Declare the preferred size of the content to be exactly widthdp by heightdp.

Cmn
Modifier
Modifier.sizeIn(minWidth: Dp, minHeight: Dp, maxWidth: Dp, maxHeight: Dp)

Constrain the width of the content to be between minWidthdp and maxWidthdp and the height of the content to be between minHeightdp and maxHeightdp as permitted by the incoming measurement Constraints.

Cmn
Modifier
Modifier.width(width: Dp)

Declare the preferred width of the content to be exactly widthdp.

Cmn
Modifier
Modifier.widthIn(min: Dp, max: Dp)

Constrain the width of the content to be between mindp and maxdp as permitted by the incoming measurement Constraints.

Cmn
Modifier
Modifier.wrapContentHeight(
    align: Alignment.Vertical,
    unbounded: Boolean
)

Allow the content to measure at its desired height without regard for the incoming measurement minimum height constraint, and, if unbounded is true, also without regard for the incoming measurement maximum height constraint.

Cmn
Modifier
Modifier.wrapContentSize(align: Alignment, unbounded: Boolean)

Allow the content to measure at its desired size without regard for the incoming measurement minimum width or minimum height constraints, and, if unbounded is true, also without regard for the incoming maximum constraints.

Cmn
Modifier
Modifier.wrapContentWidth(
    align: Alignment.Horizontal,
    unbounded: Boolean
)

Allow the content to measure at its desired width without regard for the incoming measurement minimum width constraint, and, if unbounded is true, also without regard for the incoming measurement maximum width constraint.

Cmn
Modifier
Modifier.onInterceptKeyBeforeSoftKeyboard(
    onInterceptKeyBeforeSoftKeyboard: (KeyEvent) -> Boolean
)

Adding this modifier to the modifier parameter of a component will allow it to intercept hardware key events before they are sent to the software keyboard.

Cmn
Modifier
Modifier.onPreInterceptKeyBeforeSoftKeyboard(
    onPreInterceptKeyBeforeSoftKeyboard: (KeyEvent) -> Boolean
)

Adding this modifier to the modifier parameter of a component will allow it to intercept hardware key events before they are sent to the software keyboard.

Cmn
Modifier

This function is deprecated. The styleable() modifier must provide one or more 'style' parameter values.

Cmn
Modifier

Modifier that creates a region that is styled by the given Style object for the component this Modifier is attached to.

Cmn
Modifier

Modifier that creates a region that is styled by the given Style object for the component this Modifier is attached to.

Cmn
Modifier
@Composable
Modifier.surface(
    focusable: Boolean,
    shape: Shape,
    color: Color,
    contentColor: Color,
    depthEffect: SurfaceDepthEffect?,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?
)

A surface is a fundamental building block in Glimmer.

android
Modifier
@Composable
Modifier.surface(
    enabled: Boolean,
    shape: Shape,
    color: Color,
    contentColor: Color,
    depthEffect: SurfaceDepthEffect?,
    border: BorderStroke?,
    interactionSource: MutableInteractionSource?,
    onClick: () -> Unit
)

A surface is a fundamental building block in Glimmer.

android
Modifier

This function is deprecated. Modifier.pointerInput must provide one or more 'key' parameters that define the identity of the modifier and determine when its previous input processing coroutine should be cancelled and a new effect launched for the new key.

Cmn
Modifier

Create a modifier for processing pointer input within the region of the modified element.

Cmn
Modifier

Create a modifier for processing pointer input within the region of the modified element.

Cmn
Modifier
Modifier.pointerInput(
    key1: Any?,
    key2: Any?,
    block: PointerInputEventHandler
)

Create a modifier for processing pointer input within the region of the modified element.

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

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

android
Modifier
@ExperimentalMaterialApi
<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
)

This function is deprecated. Material's Swipeable has been replaced by Foundation's AnchoredDraggable APIs.

Cmn
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.

android
Modifier

Excludes the layout rectangle from the system gesture.

android
Modifier

Excludes a rectangle within the local layout coordinates from the system gesture.

android
Modifier

Applies a tag to allow modified element to be found in tests.

Cmn
Modifier

Adds a builder to be run when the text context menu is shown within this hierarchy.

Cmn
Modifier

Adds a filter to be run when the text context menu is shown within this hierarchy.

Cmn
Modifier
Modifier.toggleable(
    value: Boolean,
    enabled: Boolean,
    role: Role?,
    interactionSource: MutableInteractionSource?,
    onValueChange: (Boolean) -> Unit
)

Configure component to make it toggleable via input and accessibility events

Cmn
Modifier
Modifier.toggleable(
    value: Boolean,
    interactionSource: MutableInteractionSource?,
    indication: Indication?,
    enabled: Boolean,
    role: Role?,
    onValueChange: (Boolean) -> Unit
)

Configure component to make it toggleable via input and accessibility events.

Cmn
Modifier
Modifier.triStateToggleable(
    state: ToggleableState,
    enabled: Boolean,
    role: Role?,
    interactionSource: MutableInteractionSource?,
    onClick: () -> Unit
)

Configure component to make it toggleable via input and accessibility events with three states: On, Off and Indeterminate.

Cmn
Modifier
Modifier.triStateToggleable(
    state: ToggleableState,
    interactionSource: MutableInteractionSource?,
    indication: Indication?,
    enabled: Boolean,
    role: Role?,
    onClick: () -> Unit
)

Configure component to make it toggleable via input and accessibility events with three states: On, Off and Indeterminate.

Cmn
Modifier

Modifier to set both the size and recommended touch target for IconButton and TextButton.

android
Modifier
Modifier.transformable(
    state: TransformableState,
    lockRotationOnZoomPan: Boolean,
    enabled: Boolean
)

Enable transformation gestures of the modified UI element.

Cmn
Modifier
Modifier.transformable(
    state: TransformableState,
    canPan: (Offset) -> Boolean,
    lockRotationOnZoomPan: Boolean,
    enabled: Boolean
)

Enable transformation gestures of the modified UI element.

Cmn
Modifier

Convenience modifier to calculate transformed height using TransformationSpec.

android
Modifier

A Modifier that controls the visibility of the Layout it is applied to.

Cmn
Modifier

Controls the soft keyboard as a nested scrolling on Android R and later.

android
Modifier

Adds padding to accommodate the caption bar insets.

Cmn
android
Modifier

Consume insets that haven't been consumed yet by other insets Modifiers similar to windowInsetsPadding without adding any padding.

Cmn
Modifier

Consume paddingValues as insets as if the padding was added irrespective of insets.

Cmn
Modifier

Adds padding to accommodate the display cutout.

Cmn
android
Modifier

Adds padding to accommodate the ime insets.

Cmn
android
Modifier

Adds padding to accommodate the mandatory system gestures insets.

Cmn
android
Modifier

Adds padding to accommodate the navigation bars insets.

Cmn
android
Modifier
Modifier.onConsumedWindowInsetsChanged(
    block: (consumedWindowInsets: WindowInsets) -> Unit
)

Calls block with the WindowInsets that have been consumed, either by consumeWindowInsets or one of the padding Modifiers, such as imePadding.

Cmn
Modifier

This recalculates the WindowInsets based on the size and position.

Cmn
Modifier

Adds padding to accommodate the safe content insets.

Cmn
android
Modifier

Adds padding to accommodate the safe drawing insets.

Cmn
android
Modifier

Adds padding to accommodate the safe gestures insets.

Cmn
android
Modifier

Adds padding to accommodate the status bars insets.

Cmn
android
Modifier

Adds padding to accommodate the system bars insets.

Cmn
android
Modifier

Adds padding to accommodate the system gestures insets.

Cmn
android
Modifier

Adds padding to accommodate the waterfall insets.

Cmn
android
Modifier

Adds padding so that the content doesn't enter insets space.

Cmn
Modifier

Sets the height to that of insets at the bottom of the screen.

Cmn
Modifier

Sets the width to that of insets at the end of the screen, using either left or right, depending on the LayoutDirection.

Cmn
Modifier

Sets the width to that of insets at the start of the screen, using either left or right, depending on the LayoutDirection.

Cmn
Modifier

Sets the height to that of insets at the top of the screen.

Cmn
Modifier

Creates a modifier that controls the drawing order for the children of the same layout parent.

Cmn
Modifier
@UnstableApi
@Composable
Modifier.resizeWithContentScale(
    contentScale: ContentScale,
    sourceSizeDp: Size?,
    density: Density
)

Attempts to size the original content rectangle to be inscribed into a destination by applying a specified ContentScale type.

android

Public companion functions

all

open fun all(predicate: (Modifier.Element) -> Boolean): Boolean

Returns true if predicate returns true for all Elements in this Modifier or if this Modifier contains no Elements.

any

open fun any(predicate: (Modifier.Element) -> Boolean): Boolean

Returns true if predicate returns true for any Element in this Modifier.

foldIn

open fun <R : Any?> foldIn(initial: R, operation: (Modifier.Element, R) -> R): R

Accumulates a value starting with initial and applying operation to the current value and each element from outside in.

Elements wrap one another in a chain from left to right; an Element that appears to the left of another in a + expression or in operation's parameter order affects all of the elements that appear after it. foldIn may be used to accumulate a value starting from the parent or head of the modifier chain to the final wrapped child.

foldOut

open fun <R : Any?> foldOut(initial: R, operation: (Modifier.Element, R) -> R): R

Accumulates a value starting with initial and applying operation to the current value and each element from inside out.

Elements wrap one another in a chain from left to right; an Element that appears to the left of another in a + expression or in operation's parameter order affects all of the elements that appear after it. foldOut may be used to accumulate a value starting from the child or tail of the modifier chain up to the parent or head of the chain.

then

open infix fun then(other: Modifier): Modifier

Concatenates this modifier with another.

Returns a Modifier representing this modifier followed by other in sequence.

toString

open fun toString(): String

Public functions

all

fun all(predicate: (Modifier.Element) -> Boolean): Boolean

Returns true if predicate returns true for all Elements in this Modifier or if this Modifier contains no Elements.

any

fun any(predicate: (Modifier.Element) -> Boolean): Boolean

Returns true if predicate returns true for any Element in this Modifier.

foldIn

fun <R : Any?> foldIn(initial: R, operation: (Modifier.Element, R) -> R): R

Accumulates a value starting with initial and applying operation to the current value and each element from outside in.

Elements wrap one another in a chain from left to right; an Element that appears to the left of another in a + expression or in operation's parameter order affects all of the elements that appear after it. foldIn may be used to accumulate a value starting from the parent or head of the modifier chain to the final wrapped child.

foldOut

fun <R : Any?> foldOut(initial: R, operation: (Modifier.Element, R) -> R): R

Accumulates a value starting with initial and applying operation to the current value and each element from inside out.

Elements wrap one another in a chain from left to right; an Element that appears to the left of another in a + expression or in operation's parameter order affects all of the elements that appear after it. foldOut may be used to accumulate a value starting from the child or tail of the modifier chain up to the parent or head of the chain.

then

open infix fun then(other: Modifier): Modifier

Concatenates this modifier with another.

Returns a Modifier representing this modifier followed by other in sequence.

Extension functions

Modifier.paddingFrom

fun Modifier.paddingFrom(
    alignmentLine: AlignmentLine,
    before: Dp = Dp.Unspecified,
    after: Dp = Dp.Unspecified
): Modifier

A Modifier that can add padding to position the content according to specified distances from its bounds to an alignment line. Whether the positioning is vertical or horizontal is defined by the orientation of the given alignmentLine (if the line is horizontal, before and after will refer to distances from top and bottom, otherwise they will refer to distances from start and end). The opposite axis sizing and positioning will remain unaffected. The modified layout will try to include the required padding, subject to the incoming max layout constraints, such that the distance from its bounds to the alignmentLine of the content will be before and after, respectively. When the max constraints do not allow this, satisfying the before requirement will have priority over after. When the modified layout is min constrained in the affected layout direction and the padded layout is smaller than the constraint, the modified layout will satisfy the min constraint and the content will be positioned to satisfy the before requirement if specified, or the after requirement otherwise.

Example usage:

import androidx.compose.foundation.layout.paddingFrom
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.FirstBaseline
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

// We want to have 30.sp distance from the top of the layout box to the baseline of the
// first line of text.
val distanceToBaseline = 30.sp
// We convert the 30.sp value to dps, which is required for the paddingFrom API.
val distanceToBaselineDp = with(LocalDensity.current) { distanceToBaseline.toDp() }
// The result will be a layout with 30.sp distance from the top of the layout box to the
// baseline of the first line of text.
Text(
    text = "This is an example.",
    modifier = Modifier.paddingFrom(FirstBaseline, before = distanceToBaselineDp),
)
Parameters
alignmentLine: AlignmentLine

the alignment line relative to which the padding is defined

before: Dp = Dp.Unspecified

the distance between the container's top edge and the horizontal alignment line, or the container's start edge and the vertical alignment line

after: Dp = Dp.Unspecified

the distance between the container's bottom edge and the horizontal alignment line, or the container's end edge and the vertical alignment line

Modifier.paddingFrom

fun Modifier.paddingFrom(
    alignmentLine: AlignmentLine,
    before: TextUnit = TextUnit.Unspecified,
    after: TextUnit = TextUnit.Unspecified
): Modifier

A Modifier that can add padding to position the content according to specified distances from its bounds to an alignment line. Whether the positioning is vertical or horizontal is defined by the orientation of the given alignmentLine (if the line is horizontal, before and after will refer to distances from top and bottom, otherwise they will refer to distances from start and end). The opposite axis sizing and positioning will remain unaffected. The modified layout will try to include the required padding, subject to the incoming max layout constraints, such that the distance from its bounds to the alignmentLine of the content will be before and after, respectively. When the max constraints do not allow this, satisfying the before requirement will have priority over after. When the modified layout is min constrained in the affected layout direction and the padded layout is smaller than the constraint, the modified layout will satisfy the min constraint and the content will be positioned to satisfy the before requirement if specified, or the after requirement otherwise.

Example usage:

import androidx.compose.foundation.layout.paddingFrom
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.FirstBaseline
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

// We want to have 30.sp distance from the top of the layout box to the baseline of the
// first line of text.
val distanceToBaseline = 30.sp
// We convert the 30.sp value to dps, which is required for the paddingFrom API.
val distanceToBaselineDp = with(LocalDensity.current) { distanceToBaseline.toDp() }
// The result will be a layout with 30.sp distance from the top of the layout box to the
// baseline of the first line of text.
Text(
    text = "This is an example.",
    modifier = Modifier.paddingFrom(FirstBaseline, before = distanceToBaselineDp),
)
Parameters
alignmentLine: AlignmentLine

the alignment line relative to which the padding is defined

before: TextUnit = TextUnit.Unspecified

the distance between the container's top edge and the horizontal alignment line, or the container's start edge and the vertical alignment line

after: TextUnit = TextUnit.Unspecified

the distance between the container's bottom edge and the horizontal alignment line, or the container's end edge and the vertical alignment line

Modifier.paddingFromBaseline

fun Modifier.paddingFromBaseline(
    top: Dp = Dp.Unspecified,
    bottom: Dp = Dp.Unspecified
): Modifier

A Modifier that positions the content in a layout such that the distance from the top of the layout to the baseline of the first line of text in the content is top, and the distance from the baseline of the last line of text in the content to the bottom of the layout is bottom.

When the modified layout is min height constrained and the padded layout is smaller than the constraint, the modified layout will satisfy the min constraint and the content will be positioned to satisfy the top requirement if specified, or the bottom requirement otherwise.

Example usage:

import androidx.compose.foundation.layout.paddingFrom
import androidx.compose.foundation.layout.paddingFromBaseline
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.FirstBaseline
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

// We want to have 30.dp distance from the top of the layout box to the baseline of the
// first line of text, and a 40.dp distance from the bottom of the layout box to the baseline
// of the last line of text. Note it is good practice to specify these distances in sp for font
// scaling, which can be done with the other overload.
val distanceToFirstBaseline = 30.dp
val distanceFromLastBaseline = 40.dp
Text(
    text = "This line has the first baseline.\nThis line has the last baseline.",
    modifier = Modifier.paddingFromBaseline(distanceToFirstBaseline, distanceFromLastBaseline),
)
See also
paddingFrom

Modifier.paddingFromBaseline

fun Modifier.paddingFromBaseline(
    top: TextUnit = TextUnit.Unspecified,
    bottom: TextUnit = TextUnit.Unspecified
): Modifier

A Modifier that positions the content in a layout such that the distance from the top of the layout to the baseline of the first line of text in the content is top, and the distance from the baseline of the last line of text in the content to the bottom of the layout is bottom.

When the modified layout is min height constrained and the padded layout is smaller than the constraint, the modified layout will satisfy the min constraint and the content will be positioned to satisfy the top requirement if specified, or the bottom requirement otherwise.

Example usage:

import androidx.compose.foundation.layout.paddingFrom
import androidx.compose.foundation.layout.paddingFromBaseline
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.FirstBaseline
import androidx.compose.ui.unit.sp

// We want to have 30.sp distance from the top of the layout box to the baseline of the
// first line of text, and a 40.sp distance from the bottom of the layout box to the baseline
// of the last line of text.
val distanceToFirstBaseline = 30.sp
val distanceFromLastBaseline = 40.sp
Text(
    text = "This line has the first baseline.\nThis line has the last baseline.",
    modifier = Modifier.paddingFromBaseline(distanceToFirstBaseline, distanceFromLastBaseline),
)
See also
paddingFrom

Modifier.alpha

fun Modifier.alpha(alpha: Float): Modifier

Draw content with modified alpha that may be less than 1.

Usage of this API renders this composable into a separate graphics layer. Note when an alpha less than 1.0f is provided, contents are implicitly clipped to their bounds. This is because an intermediate compositing layer is created to render contents into first before being drawn into the destination with the desired alpha. This layer is sized to the bounds of the composable this modifier is configured on, and contents outside of these bounds are omitted.

Performance Note: For animating alpha, it is highly recommended to use Modifier.graphicsLayer instead (e.g., Modifier.graphicsLayer { alpha = ... }). Changing the alpha parameter on Modifier.alpha causes the composable to be recomposed, which is less efficient than updating the alpha property within graphicsLayer, as graphicsLayer can optimize this change without requiring recomposition.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

Box(Modifier.size(100.dp).alpha(alpha = 0.5f).background(Color.Red))
Parameters
alpha: Float

the fraction of children's alpha value and must be between 0 and 1, inclusive.

See also
graphicsLayer

Example usage:

Modifier.anchoredDraggable

fun <T : Any?> Modifier.anchoredDraggable(
    state: AnchoredDraggableState<T>,
    orientation: Orientation,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    overscrollEffect: OverscrollEffect? = null,
    flingBehavior: FlingBehavior? = null
): Modifier

Enable drag gestures between a set of predefined values.

When a drag is detected, the offset of the AnchoredDraggableState will be updated with the drag delta. If the orientation is set to Orientation.Horizontal and LocalLayoutDirection's value is LayoutDirection.Rtl, the drag deltas will be reversed. You should use this offset to move your content accordingly (see Modifier.offset). When the drag ends, the offset will be animated to one of the anchors and when that anchor is reached, the value of the AnchoredDraggableState will also be updated to the value corresponding to the new anchor.

Dragging is constrained between the minimum and maximum anchors.

Parameters
state: AnchoredDraggableState<T>

The associated AnchoredDraggableState.

orientation: Orientation

The orientation in which the anchoredDraggable can be dragged.

enabled: Boolean = true

Whether this anchoredDraggable is enabled and should react to the user's input.

interactionSource: MutableInteractionSource? = null

Optional MutableInteractionSource that will passed on to the internal Modifier.draggable.

overscrollEffect: OverscrollEffect? = null

optional effect to dispatch any excess delta or velocity to. The excess delta or velocity are a result of dragging/flinging and reaching the bounds. If you provide an overscrollEffect, make sure to apply androidx.compose.foundation.overscroll to render the effect as well.

flingBehavior: FlingBehavior? = null

Optionally configure how the anchored draggable performs the fling. By default (if passing in null), this will snap to the closest anchor considering the velocity thresholds and positional thresholds. See AnchoredDraggableDefaults.flingBehavior.

Modifier.anchoredDraggable

fun <T : Any?> Modifier.anchoredDraggable(
    state: AnchoredDraggableState<T>,
    orientation: Orientation,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    overscrollEffect: OverscrollEffect? = null,
    startDragImmediately: Boolean = state.isAnimationRunning,
    flingBehavior: FlingBehavior? = null
): Modifier

Enable drag gestures between a set of predefined values.

When a drag is detected, the offset of the AnchoredDraggableState will be updated with the drag delta. If the orientation is set to Orientation.Horizontal and LocalLayoutDirection's value is LayoutDirection.Rtl, the drag deltas will be reversed. You should use this offset to move your content accordingly (see Modifier.offset). When the drag ends, the offset will be animated to one of the anchors and when that anchor is reached, the value of the AnchoredDraggableState will also be updated to the value corresponding to the new anchor.

Dragging is constrained between the minimum and maximum anchors.

Parameters
state: AnchoredDraggableState<T>

The associated AnchoredDraggableState.

orientation: Orientation

The orientation in which the anchoredDraggable can be dragged.

enabled: Boolean = true

Whether this anchoredDraggable is enabled and should react to the user's input.

interactionSource: MutableInteractionSource? = null

Optional MutableInteractionSource that will passed on to the internal Modifier.draggable.

overscrollEffect: OverscrollEffect? = null

optional effect to dispatch any excess delta or velocity to. The excess delta or velocity are a result of dragging/flinging and reaching the bounds. If you provide an overscrollEffect, make sure to apply androidx.compose.foundation.overscroll to render the effect as well.

startDragImmediately: Boolean = state.isAnimationRunning

when set to false, draggable will start dragging only when the gesture crosses the touchSlop. This is useful to prevent users from "catching" an animating widget when pressing on it. See draggable to learn more about startDragImmediately.

flingBehavior: FlingBehavior? = null

Optionally configure how the anchored draggable performs the fling. By default (if passing in null), this will snap to the closest anchor considering the velocity thresholds and positional thresholds. See AnchoredDraggableDefaults.flingBehavior.

Modifier.anchoredDraggable

fun <T : Any?> Modifier.anchoredDraggable(
    state: AnchoredDraggableState<T>,
    reverseDirection: Boolean,
    orientation: Orientation,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    overscrollEffect: OverscrollEffect? = null,
    flingBehavior: FlingBehavior? = null
): Modifier

Enable drag gestures between a set of predefined values.

When a drag is detected, the offset of the AnchoredDraggableState will be updated with the drag delta. You should use this offset to move your content accordingly (see Modifier.offset). When the drag ends, the offset will be animated to one of the anchors and when that anchor is reached, the value of the AnchoredDraggableState will also be updated to the value corresponding to the new anchor.

Dragging is constrained between the minimum and maximum anchors.

Parameters
state: AnchoredDraggableState<T>

The associated AnchoredDraggableState.

reverseDirection: Boolean

Whether to reverse the direction of the drag, so a top to bottom drag will behave like bottom to top, and a left to right drag will behave like right to left. If not specified, this will be determined based on orientation and LocalLayoutDirection through the other anchoredDraggable overload.

orientation: Orientation

The orientation in which the anchoredDraggable can be dragged.

enabled: Boolean = true

Whether this anchoredDraggable is enabled and should react to the user's input.

interactionSource: MutableInteractionSource? = null

Optional MutableInteractionSource that will passed on to the internal Modifier.draggable.

overscrollEffect: OverscrollEffect? = null

optional effect to dispatch any excess delta or velocity to. The excess delta or velocity are a result of dragging/flinging and reaching the bounds. If you provide an overscrollEffect, make sure to apply androidx.compose.foundation.overscroll to render the effect as well.

flingBehavior: FlingBehavior? = null

Optionally configure how the anchored draggable performs the fling. By default (if passing in null), this will snap to the closest anchor considering the velocity thresholds and positional thresholds. See AnchoredDraggableDefaults.flingBehavior.

Modifier.anchoredDraggable

fun <T : Any?> Modifier.anchoredDraggable(
    state: AnchoredDraggableState<T>,
    reverseDirection: Boolean,
    orientation: Orientation,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    overscrollEffect: OverscrollEffect? = null,
    startDragImmediately: Boolean = state.isAnimationRunning,
    flingBehavior: FlingBehavior? = null
): Modifier

Enable drag gestures between a set of predefined values.

When a drag is detected, the offset of the AnchoredDraggableState will be updated with the drag delta. You should use this offset to move your content accordingly (see Modifier.offset). When the drag ends, the offset will be animated to one of the anchors and when that anchor is reached, the value of the AnchoredDraggableState will also be updated to the value corresponding to the new anchor.

Dragging is constrained between the minimum and maximum anchors.

Parameters
state: AnchoredDraggableState<T>

The associated AnchoredDraggableState.

reverseDirection: Boolean

Whether to reverse the direction of the drag, so a top to bottom drag will behave like bottom to top, and a left to right drag will behave like right to left. If not specified, this will be determined based on orientation and LocalLayoutDirection through the other anchoredDraggable overload.

orientation: Orientation

The orientation in which the anchoredDraggable can be dragged.

enabled: Boolean = true

Whether this anchoredDraggable is enabled and should react to the user's input.

interactionSource: MutableInteractionSource? = null

Optional MutableInteractionSource that will passed on to the internal Modifier.draggable.

overscrollEffect: OverscrollEffect? = null

optional effect to dispatch any excess delta or velocity to. The excess delta or velocity are a result of dragging/flinging and reaching the bounds. If you provide an overscrollEffect, make sure to apply androidx.compose.foundation.overscroll to render the effect as well.

startDragImmediately: Boolean = state.isAnimationRunning

when set to false, draggable will start dragging only when the gesture crosses the touchSlop. This is useful to prevent users from "catching" an animating widget when pressing on it. See draggable to learn more about startDragImmediately.

flingBehavior: FlingBehavior? = null

Optionally configure how the anchored draggable performs the fling. By default (if passing in null), this will snap to the closest anchor considering the velocity thresholds and positional thresholds. See AnchoredDraggableDefaults.flingBehavior.

Modifier.dragAndDropSource

@ExperimentalFoundationApi
fun Modifier.dragAndDropSource(block: suspend DragAndDropSourceScope.() -> Unit): Modifier

A Modifier that allows an element it is applied to to be treated like a source for drag and drop operations. It displays the element dragged as a drag shadow.

Learn how to use Modifier.dragAndDropSource:

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.border
import androidx.compose.foundation.draganddrop.dragAndDropSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draganddrop.DragAndDropTransferData
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

val label = remember { "Drag me" }
Box(
    modifier =
        modifier
            .dragAndDropSource { _ ->
                DragAndDropTransferData(
                    clipData = ClipData.newPlainText(label, label),
                    flags = View.DRAG_FLAG_GLOBAL,
                )
            }
            .border(
                border =
                    BorderStroke(
                        width = 4.dp,
                        brush = Brush.linearGradient(listOf(Color.Magenta, Color.Magenta)),
                    ),
                shape = RoundedCornerShape(16.dp),
            )
            .padding(24.dp)
) {
    Text(modifier = Modifier.align(Alignment.Center), text = label)
}
Parameters
block: suspend DragAndDropSourceScope.() -> Unit

A lambda with a DragAndDropSourceScope as a receiver which provides a PointerInputScope to detect the drag gesture, after which a drag and drop gesture can be started with DragAndDropSourceScope.startTransfer.

Modifier.animateBounds

fun Modifier.animateBounds(
    lookaheadScope: LookaheadScope,
    modifier: Modifier = Modifier,
    boundsTransform: BoundsTransform = DefaultBoundsTransform,
    animateMotionFrameOfReference: Boolean = false
): Modifier

Modifier to animate layout changes (position and/or size) that occur within a LookaheadScope.

So, the given lookaheadScope defines the coordinate space considered to trigger an animation. For example, if lookaheadScope was defined at the root of the app hierarchy, then any layout changes visible within the screen will trigger an animation, if it, in contrast was defined within a scrolling parent, then, as long the LookaheadScope scrolls with is content, no animation will be triggered, as there will be no changes within its coordinate space.

The animation is driven with a FiniteAnimationSpec produced by the given BoundsTransform function, which you may use to customize the animations based on the initial and target bounds.

Do note that certain Layout Modifiers when chained with animateBounds, may only cause an immediate observable change to either the child or the parent Layout which can result in undesired behavior. For those cases you can instead provide it to the modifier parameter. This allows animateBounds to envelop the size and constraints change and propagate them gradually to both its parent and child Layout.

You may see the difference when supplying a Layout Modifier in modifier on the following example:

import androidx.compose.animation.BoundsTransform
import androidx.compose.animation.animateBounds
import androidx.compose.animation.core.VisibilityThreshold
import androidx.compose.animation.core.spring
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
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.shape.RoundedCornerShape
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.LookaheadScope
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round

// Example showing the difference between providing a Layout Modifier as a parameter of
// `animateBounds` and chaining the Layout Modifier.

// We use `padding` in this example, as it provides an immediate change in layout to its child,
// but not the parent, which sees the same resulting layout. The difference can be seen in the
// Text (content under padding) and an accompanying Cyan Box (a sibling, under the same Row
// parent).
LookaheadScope {
    val boundsTransform = remember {
        BoundsTransform { _, _ ->
            spring(stiffness = 50f, visibilityThreshold = Rect.VisibilityThreshold)
        }
    }

    var toggleAnimation by remember { mutableStateOf(true) }

    Column(Modifier.clickable { toggleAnimation = !toggleAnimation }) {
        Text(
            "See the difference in animation when the Layout Modifier is a parameter of animateBounds. Padding, in this example."
        )
        Spacer(Modifier.height(12.dp))
        Text("Layout Modifier as a parameter.")
        Row(Modifier.fillMaxWidth()) {
            Box(
                Modifier.animateBounds(
                        lookaheadScope = this@LookaheadScope,
                        modifier =
                            // By providing this Modifier as a parameter of `animateBounds`,
                            // both content and parent see a gradual/animated change in Layout.
                            Modifier.padding(
                                horizontal = if (toggleAnimation) 10.dp else 50.dp
                            ),
                        boundsTransform = boundsTransform,
                    )
                    .background(Color.Red, RoundedCornerShape(12.dp))
                    .height(50.dp)
            ) {
                Text("Layout Content", Modifier.align(Alignment.Center))
            }
            Box(Modifier.size(50.dp).background(Color.Cyan, RoundedCornerShape(12.dp)))
        }
        Spacer(Modifier.height(12.dp))
        Text("Layout Modifier after AnimateBounds.")
        Row(Modifier.fillMaxWidth()) {
            Box(
                Modifier.animateBounds(
                        lookaheadScope = this@LookaheadScope,
                        boundsTransform = boundsTransform,
                    )
                    // The content is able to animate the change in padding, but since the
                    // parent Layout sees no difference, the change in position is immediate.
                    .padding(horizontal = if (toggleAnimation) 10.dp else 50.dp)
                    .background(Color.Red, RoundedCornerShape(12.dp))
                    .height(50.dp)
            ) {
                Text("Layout Content", Modifier.align(Alignment.Center))
            }
            Box(Modifier.size(50.dp).background(Color.Cyan, RoundedCornerShape(12.dp)))
        }
        Spacer(Modifier.height(12.dp))
        Text("Layout Modifier before AnimateBounds.")
        Row(Modifier.fillMaxWidth()) {
            Box(
                Modifier
                    // The parent is able to see the change in position and the animated size,
                    // so it can smoothly place both its children, but the content of the Box
                    // cannot see the gradual changes so it remains constant.
                    .padding(horizontal = if (toggleAnimation) 10.dp else 50.dp)
                    .animateBounds(
                        lookaheadScope = this@LookaheadScope,
                        boundsTransform = boundsTransform,
                    )
                    .background(Color.Red, RoundedCornerShape(12.dp))
                    .height(50.dp)
            ) {
                Text("Layout Content", Modifier.align(Alignment.Center))
            }
            Box(Modifier.size(50.dp).background(Color.Cyan, RoundedCornerShape(12.dp)))
        }
    }
}

By default, changes in position under LayoutCoordinates.introducesMotionFrameOfReference are excluded from the animation and are instead immediately applied, as they are expected to be frequent/continuous (to handle Layouts under Scroll). You may change this behavior by passing animateMotionFrameOfReference as true. Keep in mind, doing that under a scroll may result in the Layout "chasing" the scroll offset, as it will constantly animate to the latest position.

A basic use-case is animating a layout based on content changes, such as the String changing on a Text:

import androidx.compose.animation.animateBounds
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.LookaheadScope
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round

// Example where the change in content triggers the layout change on the item with animateBounds
val textShort = remember { "Foo ".repeat(10) }
val textLong = remember { "Bar ".repeat(50) }

var toggle by remember { mutableStateOf(true) }

LookaheadScope {
    Box(
        modifier = Modifier.fillMaxSize().clickable { toggle = !toggle },
        contentAlignment = Alignment.Center,
    ) {
        Text(
            text = if (toggle) textShort else textLong,
            modifier =
                Modifier.fillMaxWidth(0.7f)
                    .background(Color.LightGray)
                    .animateBounds(this@LookaheadScope)
                    .padding(10.dp),
        )
    }
}

It also provides an easy way to animate layout changes of a complex Composable Layout:

import androidx.compose.animation.animateBounds
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Text
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.LookaheadScope
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round
import androidx.compose.ui.util.fastForEach

var itemRowCount by remember { mutableIntStateOf(1) }
val colors = remember { listOf(Color.Cyan, Color.Magenta, Color.Yellow, Color.Green) }

// A case showing `animateBounds` being used to animate layout changes driven by a parent Layout
LookaheadScope {
    Column(Modifier.clickable { itemRowCount = if (itemRowCount != 2) 2 else 1 }) {
        Text("Click to toggle animation.")
        FlowRow(
            modifier =
                Modifier.fillMaxWidth()
                    // Note that the wrap content size changes for FlowRow as the content
                    // adjusts
                    // to one or two lines, we can simply use `animateContentSize()` to make
                    // sure
                    // all items are visible during their animation.
                    .animateContentSize(),
            // Try changing the arrangement as well!
            horizontalArrangement = Arrangement.spacedBy(8.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp),
            // We use the maxItems parameter to change the layout of the FlowRow at different
            // states
            maxItemsInEachRow = itemRowCount,
        ) {
            colors.fastForEach {
                Box(
                    Modifier.animateBounds(this@LookaheadScope)
                        // Note the modifier order, we declare the background after
                        // `animateBounds` to make sure it animates with the rest of the content
                        .background(it, RoundedCornerShape(12.dp))
                        .weight(weight = 1f, fill = true)
                        .height(100.dp)
                )
            }
        }
    }
}

Since BoundsTransform is called when initiating an animation, you may also use it to calculate a keyframe based animation:

import androidx.compose.animation.BoundsTransform
import androidx.compose.animation.animateBounds
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.keyframesWithSpline
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
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.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.LookaheadScope
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round

var toggle by remember { mutableStateOf(true) }

// Example using BoundsTransform to calculate an animation using keyframes with splines.
LookaheadScope {
    Box(Modifier.fillMaxSize().clickable { toggle = !toggle }) {
        Text(
            text = "Hello, World!",
            textAlign = TextAlign.Center,
            modifier =
                Modifier.align(if (toggle) Alignment.TopStart else Alignment.TopEnd)
                    .animateBounds(
                        lookaheadScope = this@LookaheadScope,
                        boundsTransform = { initialBounds, targetBounds ->
                            // We'll use a keyframe to emphasize the animation in position and
                            // size.
                            keyframesWithSpline {
                                durationMillis = 1200

                                // Emphasize with an increase in size
                                val size = targetBounds.size.times(2f)

                                // Emphasize the path with a slight curve at the halfway point
                                val position =
                                    targetBounds.topLeft
                                        .plus(initialBounds.topLeft)
                                        .times(0.5f)
                                        .plus(
                                            Offset(
                                                // Consider the increase in size (from the
                                                // center,
                                                // to keep the Layout aligned at the keyframe)
                                                x = -(size.width - targetBounds.width) * 0.5f,
                                                // Emphasize the path with a vertical offset
                                                y = size.height * 0.5f,
                                            )
                                        )

                                // Only need to define the intermediate keyframe, initial and
                                // target are implicit.
                                Rect(position, size).atFraction(0.5f).using(LinearEasing)
                            }
                        },
                    )
                    .background(Color.LightGray, RoundedCornerShape(50))
                    .padding(10.dp)
                    // Text is laid out with the animated fixed Constraints, relax constraints
                    // back to wrap content to be able to center Align vertically.
                    .wrapContentSize(Alignment.Center),
        )
    }
}

It may also be used together with movableContent as long as the given LookaheadScope is in a common place within the Layout hierarchy of the slots presenting the movableContent:

import androidx.compose.animation.animateBounds
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.VisibilityThreshold
import androidx.compose.animation.core.spring
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.movableContentWithReceiverOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.LookaheadScope
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.round

// Example showing how to animate a Layout that can be presented on different Layout Composables
// as the state changes using `movableContent`.
var position by remember { mutableIntStateOf(-1) }

val movableContent = remember {
    // To animate a Layout that can be presented in different Composables, we can use
    // `animateBounds` with `movableContent`.
    movableContentWithReceiverOf<LookaheadScope> {
        Box(
            Modifier.animateBounds(
                    lookaheadScope = this@movableContentWithReceiverOf,
                    boundsTransform = { _, _ ->
                        spring(
                            dampingRatio = Spring.DampingRatioLowBouncy,
                            stiffness = Spring.StiffnessVeryLow,
                            visibilityThreshold = Rect.VisibilityThreshold,
                        )
                    },
                )
                // Our movableContent can always fill its container in this example.
                .fillMaxSize()
                .background(Color.Cyan, RoundedCornerShape(8.dp))
        )
    }
}

LookaheadScope {
    Box(Modifier.fillMaxSize()) {
        // Initial container of our Layout, at the center of the screen.
        Box(
            Modifier.size(200.dp)
                .border(3.dp, Color.Red, RoundedCornerShape(8.dp))
                .align(Alignment.Center)
                .clickable { position = -1 }
        ) {
            if (position < 0) {
                movableContent()
            }
        }

        repeat(4) { index ->
            // Four additional Boxes where our content may be move to.
            Box(
                Modifier.size(100.dp)
                    .border(2.dp, Color.Blue, RoundedCornerShape(8.dp))
                    .align { size, space, _ ->
                        val horizontal = if (index % 2 == 0) 0.15f else 0.85f
                        val vertical = if (index < 2) 0.15f else 0.85f

                        Offset(
                                x = (space.width - size.width) * horizontal,
                                y = (space.height - size.height) * vertical,
                            )
                            .round()
                    }
                    .clickable { position = index }
            ) {
                if (position == index) {
                    // The call to movable content will trigger `Modifier.animateBounds()` to
                    // animate the content's position and size from its previous state.
                    movableContent()
                }
            }
        }
    }
}
Parameters
lookaheadScope: LookaheadScope

The scope from which this animateBounds will calculate its animations from. This implies that as long as you're expecting an animation the reference of the given LookaheadScope shouldn't change, otherwise you may get unexpected behavior.

modifier: Modifier = Modifier

Optional intermediate Modifier, may be used in cases where otherwise immediate layout changes are perceived as gradual by both the parent and child Layout.

boundsTransform: BoundsTransform = DefaultBoundsTransform

Produce a customized FiniteAnimationSpec based on the initial and target bounds, called when an animation is triggered.

animateMotionFrameOfReference: Boolean = false

When true, changes under LayoutCoordinates.introducesMotionFrameOfReference (for continuous positional changes, such as Scroll Offset) are included when calculating an animation. false by default, where the changes are instead applied directly into the layout without triggering an animation.

Modifier.animateContentSize

fun Modifier.animateContentSize(
    animationSpec: FiniteAnimationSpec<IntSize> = spring( stiffness = Spring.StiffnessMediumLow, visibilityThreshold = IntSize.VisibilityThreshold, ),
    finishedListener: ((initialValue: IntSize, targetValue: IntSize) -> Unit)? = null
): Modifier

This modifier animates its own size when its child modifier (or the child composable if it is already at the tail of the chain) changes size. This allows the parent modifier to observe a smooth size change, resulting in an overall continuous visual change.

A FiniteAnimationSpec can be optionally specified for the size change animation. By default, spring will be used.

An optional finishedListener can be supplied to get notified when the size change animation is finished. Since the content size change can be dynamic in many cases, both initial value and target value (i.e. final size) will be passed to the finishedListener. Note: if the animation is interrupted, the initial value will be the size at the point of interruption. This is intended to help determine the direction of the size change (i.e. expand or collapse in x and y dimensions).

import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

val shortText = "Hi"
val longText = "Very long text\nthat spans across\nmultiple lines"
var short by remember { mutableStateOf(true) }
Box(
    modifier =
        Modifier.background(Color.Blue, RoundedCornerShape(15.dp))
            .clickable { short = !short }
            .padding(20.dp)
            .wrapContentSize()
            .animateContentSize()
) {
    Text(
        if (short) {
            shortText
        } else {
            longText
        },
        style = LocalTextStyle.current.copy(color = Color.White),
    )
}
Parameters
animationSpec: FiniteAnimationSpec<IntSize> = spring( stiffness = Spring.StiffnessMediumLow, visibilityThreshold = IntSize.VisibilityThreshold, )

a finite animation that will be used to animate size change, spring by default

finishedListener: ((initialValue: IntSize, targetValue: IntSize) -> Unit)? = null

an optional listener to be called when the content change animation is completed.

Modifier.animateContentSize

fun Modifier.animateContentSize(
    animationSpec: FiniteAnimationSpec<IntSize> = spring( stiffness = Spring.StiffnessMediumLow, visibilityThreshold = IntSize.VisibilityThreshold, ),
    alignment: Alignment = Alignment.TopStart,
    finishedListener: ((initialValue: IntSize, targetValue: IntSize) -> Unit)? = null
): Modifier

This modifier animates its own size when its child modifier (or the child composable if it is already at the tail of the chain) changes size. This allows the parent modifier to observe a smooth size change, resulting in an overall continuous visual change.

A FiniteAnimationSpec can be optionally specified for the size change animation. By default, spring will be used.

An optional finishedListener can be supplied to get notified when the size change animation is finished. Since the content size change can be dynamic in many cases, both initial value and target value (i.e. final size) will be passed to the finishedListener. Note: if the animation is interrupted, the initial value will be the size at the point of interruption. This is intended to help determine the direction of the size change (i.e. expand or collapse in x and y dimensions).

import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

val shortText = "Hi"
val longText = "Very long text\nthat spans across\nmultiple lines"
var short by remember { mutableStateOf(true) }
Box(
    modifier =
        Modifier.background(Color.Blue, RoundedCornerShape(15.dp))
            .clickable { short = !short }
            .padding(20.dp)
            .wrapContentSize()
            .animateContentSize()
) {
    Text(
        if (short) {
            shortText
        } else {
            longText
        },
        style = LocalTextStyle.current.copy(color = Color.White),
    )
}
Parameters
animationSpec: FiniteAnimationSpec<IntSize> = spring( stiffness = Spring.StiffnessMediumLow, visibilityThreshold = IntSize.VisibilityThreshold, )

a finite animation that will be used to animate size change, spring by default

alignment: Alignment = Alignment.TopStart

sets the alignment of the content during the animation. Alignment.TopStart by default.

finishedListener: ((initialValue: IntSize, targetValue: IntSize) -> Unit)? = null

an optional listener to be called when the content change animation is completed.

Modifier.aspectRatio

fun Modifier.aspectRatio(
    ratio: @FloatRange(from = 0.0, fromInclusive = false) Float,
    matchHeightConstraintsFirst: Boolean = false
): Modifier

Attempts to size the content to match a specified aspect ratio by trying to match one of the incoming constraints in the following order: Constraints.maxWidth, Constraints.maxHeight, Constraints.minWidth, Constraints.minHeight if matchHeightConstraintsFirst is false (which is the default), or Constraints.maxHeight, Constraints.maxWidth, Constraints.minHeight, Constraints.minWidth if matchHeightConstraintsFirst is true. The size in the other dimension is determined by the aspect ratio. The combinations will be tried in this order until one non-empty is found to satisfy the constraints. If no valid size is obtained this way, it means that there is no non-empty size satisfying both the constraints and the aspect ratio, so the constraints will not be respected and the content will be sized such that the Constraints.maxWidth or Constraints.maxHeight is matched (depending on matchHeightConstraintsFirst).

Example usage:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.width
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

Box(Modifier.width(100.dp).aspectRatio(2f).background(Color.Green))
Parameters
ratio: @FloatRange(from = 0.0, fromInclusive = false) Float

the desired width/height positive ratio

matchHeightConstraintsFirst: Boolean = false

if true, height constraints will be matched before width constraints and used to calculate the resulting size according to ratio

Modifier.contentType

fun Modifier.contentType(contentType: ContentType): Modifier

Set autofill hint with contentType.

This applies the contentType to the modifier's semantics, in turn enabling autofill and marking the hint to be associated with this composable. This allows autofill frameworks to provide relevant suggestions to users.

Using contentType is equivalent to simply setting the contentType semantic property, i.e. Modifier.contentType(ContentType.NewUsername) is equivalent to setting Modifier.semantics { contentType = ContentType.NewUsername }.

import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.ui.Modifier
import androidx.compose.ui.autofill.ContentType
import androidx.compose.ui.autofill.contentType
import androidx.compose.ui.semantics.contentType

TextField(
    state = rememberTextFieldState(),
    label = { Text("Enter your new username here.") },
    // Set the content type hint with the modifier extension.
    modifier = Modifier.contentType(ContentType.NewUsername),
)
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.ui.Modifier
import androidx.compose.ui.autofill.ContentType
import androidx.compose.ui.autofill.contentType
import androidx.compose.ui.semantics.contentType
import androidx.compose.ui.semantics.semantics

TextField(
    state = rememberTextFieldState(),
    label = { Text("Enter your new password here.") },
    // Set the content type hint with semantics.
    modifier = Modifier.semantics { contentType = ContentType.NewPassword },
)
Parameters
contentType: ContentType

The ContentType to apply to the component's semantics.

Returns
Modifier

The Modifier with the specified ContentType semantics set.

Modifier.background

fun Modifier.background(color: Color, shape: Shape = RectangleShape): Modifier

Draws shape with a solid color behind the content.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

Text("Text with background", Modifier.background(color = Color.Magenta).padding(10.dp))
Parameters
color: Color

color to paint background with

shape: Shape = RectangleShape

desired shape of the background

Modifier.background

fun Modifier.background(
    brush: Brush,
    shape: Shape = RectangleShape,
    alpha: @FloatRange(from = 0.0, to = 1.0) Float = 1.0f
): Modifier

Draws shape with brush behind the content.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

val gradientBrush =
    Brush.horizontalGradient(
        colors = listOf(Color.Red, Color.Blue, Color.Green),
        startX = 0.0f,
        endX = 500.0f,
    )
Text(
    "Text with gradient back",
    Modifier.background(brush = gradientBrush, shape = CutCornerShape(8.dp)).padding(10.dp),
)
Parameters
brush: Brush

brush to paint background with

shape: Shape = RectangleShape

desired shape of the background

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

Opacity to be applied to the brush, with 0 being completely transparent and 1 being completely opaque. The value must be between 0 and 1.

Modifier.basicMarquee

fun Modifier.basicMarquee(
    iterations: Int = Iterations,
    animationMode: MarqueeAnimationMode = Immediately,
    repeatDelayMillis: Int = RepeatDelayMillis,
    initialDelayMillis: Int = if (animationMode == Immediately) repeatDelayMillis else 0,
    spacing: MarqueeSpacing = Spacing,
    velocity: Dp = Velocity
): Modifier

Applies an animated marquee effect to the modified content if it's too wide to fit in the available space. This modifier has no effect if the content fits in the max constraints. The content will be measured with unbounded width.

When the animation is running, it will restart from the initial state any time:

  • any of the parameters to this modifier change, or

  • the content or container size change.

The animation only affects the drawing of the content, not its position. The offset returned by the LayoutCoordinates of anything inside the marquee is undefined relative to anything outside the marquee, and may not match its drawn position on screen. This modifier also does not currently support content that accepts position-based input such as pointer events.

To only animate when the composable is focused, specify animationMode and make the composable focusable. This modifier does not add any visual effects aside from scrolling, but you can add your own by placing modifiers before this one.

import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.width
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

// Marquee only animates when the content doesn't fit in the max width.
Column(Modifier.width(30.dp)) { Text("hello world", Modifier.basicMarquee()) }
import androidx.compose.foundation.MarqueeSpacing
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp

val edgeWidth = 32.dp
fun ContentDrawScope.drawFadedEdge(leftEdge: Boolean) {
    val edgeWidthPx = edgeWidth.toPx()
    drawRect(
        topLeft = Offset(if (leftEdge) 0f else size.width - edgeWidthPx, 0f),
        size = Size(edgeWidthPx, size.height),
        brush =
            Brush.horizontalGradient(
                colors = listOf(Color.Transparent, Color.Black),
                startX = if (leftEdge) 0f else size.width,
                endX = if (leftEdge) edgeWidthPx else size.width - edgeWidthPx,
            ),
        blendMode = BlendMode.DstIn,
    )
}

Text(
    "the quick brown fox jumped over the lazy dogs",
    Modifier.widthIn(max = edgeWidth * 4)
        // Rendering to an offscreen buffer is required to get the faded edges' alpha to be
        // applied only to the text, and not whatever is drawn below this composable (e.g. the
        // window).
        .graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen }
        .drawWithContent {
            drawContent()
            drawFadedEdge(leftEdge = true)
            drawFadedEdge(leftEdge = false)
        }
        .basicMarquee(
            // Animate forever.
            iterations = Int.MAX_VALUE,
            spacing = MarqueeSpacing(0.dp),
        )
        .padding(start = edgeWidth),
)
import androidx.compose.foundation.MarqueeAnimationMode
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.width
import androidx.compose.material.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.unit.dp

val focusRequester = remember { FocusRequester() }

// Marquee only animates when the content doesn't fit in the max width.
Column(Modifier.width(30.dp)) {
    Text(
        "hello world",
        Modifier.clickable { focusRequester.requestFocus() }
            .basicMarquee(animationMode = MarqueeAnimationMode.WhileFocused)
            .focusRequester(focusRequester)
            .focusable(),
    )
}
Parameters
iterations: Int = Iterations

The number of times to repeat the animation. Int.MAX_VALUE will repeat forever, and 0 will disable animation.

animationMode: MarqueeAnimationMode = Immediately

Whether the marquee should start animating Immediately or only WhileFocused. In WhileFocused mode, the modified node or the content must be made focusable. Note that the initialDelayMillis is part of the animation, so this parameter determines when that initial delay starts counting down, not when the content starts to actually scroll.

repeatDelayMillis: Int = RepeatDelayMillis

The duration to wait before starting each subsequent iteration, in millis.

initialDelayMillis: Int = if (animationMode == Immediately) repeatDelayMillis else 0

The duration to wait before starting the first iteration of the animation, in millis. By default, there will be no initial delay if animationMode is WhileFocused, otherwise the initial delay will be repeatDelayMillis.

spacing: MarqueeSpacing = Spacing

A MarqueeSpacing that specifies how much space to leave at the end of the content before showing the beginning again.

velocity: Dp = Velocity

The speed of the animation in dps / second. A positive velocity means that the marquee will animate in the direction of the current LayoutDirection.

Modifier.edgeSwipeToDismiss

fun Modifier.edgeSwipeToDismiss(
    swipeToDismissBoxState: SwipeToDismissBoxState,
    edgeWidth: Dp = SwipeToDismissBoxDefaults.EdgeWidth
): Modifier

Handles swipe to dismiss from the edge of the viewport.

Used when the content of the BasicSwipeToDismissBox is handling all the gestures of the viewport, which prevents BasicSwipeToDismissBox from handling the swipe-to-dismiss gesture. Examples of this scenario are horizontal paging, such as 2-d scrolling a Map or swiping horizontally between pages.

Use of Modifier.edgeSwipeToDismiss defines a zone on the left side of the viewport of width edgeWidth in which the swipe-right gesture is intercepted. Other touch events are 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 BasicSwipeToDismissBox which is using the same SwipeToDismissBoxState instance. As such, Modifier.edgeSwipeToDismiss is also compatible with SwipeDismissableNavHost up to and including API 35. However, for API 36 onwards, SwipeDismissableNavHost uses platform predictive back events for navigation, and is not compatible with Modifier.edgeSwipeToDismiss.

Requires that the element to which this modifier is applied notifies the nested scroll system about the scrolling events that are happening on the element. For example, using a NestedScrollDispatcher.

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.BasicSwipeToDismissBox
import androidx.wear.compose.foundation.edgeSwipeToDismiss
import androidx.wear.compose.foundation.rememberSwipeToDismissBoxState
import androidx.wear.compose.material.MaterialTheme
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.
BasicSwipeToDismissBox(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

State of BasicSwipeToDismissBox. Used to trigger swipe gestures on SwipeToDismissBox.

edgeWidth: Dp = SwipeToDismissBoxDefaults.EdgeWidth

Width of the edge zone in which the swipe will be recognised.

Modifier.blur

fun Modifier.blur(
    radius: Dp,
    edgeTreatment: BlurredEdgeTreatment = BlurredEdgeTreatment.Rectangle
): Modifier

Draw content blurred with the specified radii. Note this effect is only supported on Android 12 and above. Attempts to use this Modifier on older Android versions will be ignored.

Usage of this API renders the corresponding composable into a separate graphics layer. Because the blurred content renders a larger area by the blur radius, this layer is explicitly clipped to the content bounds. It is recommended introduce additional space around the drawn content by the specified blur radius to remain within the content bounds.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.BlurredEdgeTreatment
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

Box(
    Modifier.size(300.dp)
        // Blur content allowing the result to extend beyond the bounds of the original content
        .blur(30.dp, edgeTreatment = BlurredEdgeTreatment.Unbounded)
        .background(Color.Red, CircleShape)
)
import androidx.compose.foundation.Image
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.BlurredEdgeTreatment
import androidx.compose.ui.draw.blur
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp

Image(
    painter = painterResource(R.drawable.circus),
    contentDescription = "sample blurred image",
    // Blur content within the original bounds, clipping the result to a rounded rectangle
    modifier = Modifier.blur(30.dp, BlurredEdgeTreatment(RoundedCornerShape(5.dp))),
)
Parameters
radius: Dp

Radius of the blur along both the x and y axis

edgeTreatment: BlurredEdgeTreatment = BlurredEdgeTreatment.Rectangle

Strategy used to render pixels outside of bounds of the original input

See also
graphicsLayer

Example usage:

Modifier.blur

fun Modifier.blur(
    radiusX: Dp,
    radiusY: Dp,
    edgeTreatment: BlurredEdgeTreatment = BlurredEdgeTreatment.Rectangle
): Modifier

Draw content blurred with the specified radii. Note this effect is only supported on Android 12 and above. Attempts to use this Modifier on older Android versions will be ignored.

Usage of this API renders the corresponding composable into a separate graphics layer. Because the blurred content renders a larger area by the blur radius, this layer is explicitly clipped to the content bounds. It is recommended introduce additional space around the drawn content by the specified blur radius to remain within the content bounds.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.BlurredEdgeTreatment
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

Box(
    Modifier.size(300.dp)
        // Blur content allowing the result to extend beyond the bounds of the original content
        .blur(30.dp, edgeTreatment = BlurredEdgeTreatment.Unbounded)
        .background(Color.Red, CircleShape)
)
import androidx.compose.foundation.Image
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.BlurredEdgeTreatment
import androidx.compose.ui.draw.blur
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp

Image(
    painter = painterResource(R.drawable.circus),
    contentDescription = "sample blurred image",
    // Blur content within the original bounds, clipping the result to a rounded rectangle
    modifier = Modifier.blur(30.dp, BlurredEdgeTreatment(RoundedCornerShape(5.dp))),
)
Parameters
radiusX: Dp

Radius of the blur along the x axis

radiusY: Dp

Radius of the blur along the y axis

edgeTreatment: BlurredEdgeTreatment = BlurredEdgeTreatment.Rectangle

Strategy used to render pixels outside of bounds of the original input

See also
graphicsLayer

Example usage:

Modifier.border

fun Modifier.border(border: BorderStroke, shape: Shape = RectangleShape): Modifier

Modify element to add border with appearance specified with a border and a shape and clip it.

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

Text("Text with  square border", modifier = Modifier.border(4.dp, Color.Magenta).padding(10.dp))
Parameters
border: BorderStroke

BorderStroke class that specifies border appearance, such as size and color

shape: Shape = RectangleShape

shape of the border

Modifier.border

fun Modifier.border(width: Dp, brush: Brush, shape: Shape): Modifier

Modify element to add border with appearance specified with a width, a brush and a shape and clip it.

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.TileMode
import androidx.compose.ui.unit.dp

val gradientBrush =
    Brush.horizontalGradient(
        colors = listOf(Color.Red, Color.Blue, Color.Green),
        startX = 0.0f,
        endX = 500.0f,
        tileMode = TileMode.Repeated,
    )
Text(
    "Text with gradient border",
    modifier =
        Modifier.border(width = 2.dp, brush = gradientBrush, shape = CircleShape).padding(10.dp),
)
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.TileMode
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

val widthRange = (1..10)
var width by remember { mutableStateOf((widthRange.random()).dp) }

val shapes = remember { listOf(CutCornerShape(8.dp), CircleShape, RoundedCornerShape(20)) }
var selectedShape by remember { mutableStateOf(shapes.random()) }

val colors =
    listOf(
        Color.Black,
        Color.DarkGray,
        Color.Gray,
        Color.LightGray,
        Color.White,
        Color.Red,
        Color.Blue,
        Color.Green,
        Color.Yellow,
        Color.Cyan,
        Color.Magenta,
    )
var gradientBrush by remember {
    mutableStateOf(
        Brush.horizontalGradient(
            colors = listOf(colors.random(), colors.random(), colors.random()),
            startX = 0.0f,
            endX = 500.0f,
            tileMode = TileMode.Repeated,
        )
    )
}

Column(Modifier.padding(2.dp)) {
    Text(text = "Update border with buttons")
    Row {
        Button(
            modifier = Modifier.width(60.dp),
            onClick = { width = (widthRange.random()).dp },
        ) {
            Text(fontSize = 8.sp, text = "width")
        }
        Button(
            modifier = Modifier.width(60.dp),
            onClick = {
                gradientBrush =
                    Brush.horizontalGradient(
                        colors = listOf(colors.random(), colors.random(), colors.random()),
                        startX = 0.0f,
                        endX = 500.0f,
                        tileMode = TileMode.Repeated,
                    )
            },
        ) {
            Text(fontSize = 8.sp, text = "brush")
        }
        Button(
            modifier = Modifier.width(60.dp),
            onClick = { selectedShape = shapes.random() },
        ) {
            Text(fontSize = 8.sp, text = "shape")
        }
    }
    Text(
        "Dynamic border",
        modifier =
            Modifier.border(width = width, brush = gradientBrush, shape = selectedShape)
                .padding(10.dp),
    )
}
Parameters
width: Dp

width of the border. Use Dp.Hairline for a hairline border.

brush: Brush

brush to paint the border with

shape: Shape

shape of the border

Modifier.border

fun Modifier.border(width: Dp, color: Color, shape: Shape = RectangleShape): Modifier

Modify element to add border with appearance specified with a width, a color and a shape and clip it.

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

Text(
    "Text with gradient border",
    modifier =
        Modifier.border(border = BorderStroke(2.dp, Color.Blue), shape = CutCornerShape(8.dp))
            .padding(10.dp),
)
Parameters
width: Dp

width of the border. Use Dp.Hairline for a hairline border.

color: Color

color to paint the border with

shape: Shape = RectangleShape

shape of the border

Modifier.bringIntoViewRequester

fun Modifier.bringIntoViewRequester(
    bringIntoViewRequester: BringIntoViewRequester
): Modifier

Modifier that can be used to send bringIntoView requests.

The following example uses a bringIntoViewRequester to bring an item into the parent bounds. The example demonstrates how a composable can ask its parents to scroll so that the component using this modifier is brought into the bounds of all its parents.

import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.relocation.BringIntoViewRequester
import androidx.compose.foundation.relocation.bringIntoViewRequester
import androidx.compose.foundation.rememberScrollState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.focusTarget
import androidx.compose.ui.focus.onFocusChanged

Row(Modifier.horizontalScroll(rememberScrollState())) {
    repeat(100) {
        val bringIntoViewRequester = remember { BringIntoViewRequester() }
        val coroutineScope = rememberCoroutineScope()
        Box(
            Modifier
                // This associates the RelocationRequester with a Composable that wants to be
                // brought into view.
                .bringIntoViewRequester(bringIntoViewRequester)
                .onFocusChanged {
                    if (it.isFocused) {
                        coroutineScope.launch {
                            // This sends a request to all parents that asks them to scroll so
                            // that this item is brought into view.
                            bringIntoViewRequester.bringIntoView()
                        }
                    }
                }
                .focusTarget()
        )
    }
}
Parameters
bringIntoViewRequester: BringIntoViewRequester

An instance of BringIntoViewRequester. This hoisted object can be used to send bringIntoView requests to parents of the current composable.

Modifier.bringIntoViewResponder

fun Modifier.bringIntoViewResponder(responder: BringIntoViewResponder): Modifier

A parent that can respond to BringIntoViewRequester requests from its children, and adjust itself so that the item is visible on screen. See BringIntoViewResponder for more details about how this mechanism works.

import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.relocation.BringIntoViewRequester
import androidx.compose.foundation.relocation.bringIntoViewRequester
import androidx.compose.foundation.rememberScrollState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.focusTarget
import androidx.compose.ui.focus.onFocusChanged

Row(Modifier.horizontalScroll(rememberScrollState())) {
    repeat(100) {
        val bringIntoViewRequester = remember { BringIntoViewRequester() }
        val coroutineScope = rememberCoroutineScope()
        Box(
            Modifier
                // This associates the RelocationRequester with a Composable that wants to be
                // brought into view.
                .bringIntoViewRequester(bringIntoViewRequester)
                .onFocusChanged {
                    if (it.isFocused) {
                        coroutineScope.launch {
                            // This sends a request to all parents that asks them to scroll so
                            // that this item is brought into view.
                            bringIntoViewRequester.bringIntoView()
                        }
                    }
                }
                .focusTarget()
        )
    }
}

Modifier.clickable

fun Modifier.clickable(
    enabled: Boolean = true,
    onClickLabel: String? = null,
    role: Role? = null,
    interactionSource: MutableInteractionSource? = null,
    onClick: () -> Unit
): Modifier

Configure component to receive clicks via input or accessibility "click" event.

Add this modifier to the element to make it clickable within its bounds and show a default indication when it's pressed.

This overload will use the Indication from LocalIndication. Use the other overload to explicitly provide an Indication instance. Note that this overload only supports IndicationNodeFactory instances provided through LocalIndication - it is strongly recommended to migrate to IndicationNodeFactory, but you can use the other overload if you still need to support Indication instances that are not IndicationNodeFactory.

If interactionSource is null, an internal MutableInteractionSource will be lazily created only when needed. This reduces the performance cost of clickable during composition, as creating the indication can be delayed until there is an incoming androidx.compose.foundation.interaction.Interaction. If you are only passing a remembered MutableInteractionSource and you are never using it outside of clickable, it is recommended to instead provide null to enable lazy creation. If you need the Indication to be created eagerly, provide a remembered MutableInteractionSource.

If you need to support double click or long click alongside the single click, consider using combinedClickable.

Note Any removal operations on Android Views from clickable should wrap onClick in a post { } block to guarantee the event dispatch completes before executing the removal. (You do not need to do this when removing a composable because Compose guarantees it completes via the snapshot state system.)

import androidx.compose.foundation.clickable
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

val count = remember { mutableStateOf(0) }
// content that you want to make clickable
Text(text = count.value.toString(), modifier = Modifier.clickable { count.value += 1 })
Parameters
enabled: Boolean = true

Controls the enabled state. When false, onClick, and this modifier will appear disabled for accessibility services

onClickLabel: String? = null

semantic / accessibility label for the onClick action

role: Role? = null

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

interactionSource: MutableInteractionSource? = null

MutableInteractionSource that will be used to dispatch PressInteraction.Press when this clickable is pressed. If null, an internal MutableInteractionSource will be created if needed.

onClick: () -> Unit

will be called when user clicks on the element

Modifier.clickable

fun Modifier.clickable(
    interactionSource: MutableInteractionSource?,
    indication: Indication?,
    enabled: Boolean = true,
    onClickLabel: String? = null,
    role: Role? = null,
    onClick: () -> Unit
): Modifier

Configure component to receive clicks via input or accessibility "click" event.

Add this modifier to the element to make it clickable within its bounds and show an indication as specified in indication parameter.

If interactionSource is null, and indication is an IndicationNodeFactory, an internal MutableInteractionSource will be lazily created along with the indication only when needed. This reduces the performance cost of clickable during composition, as creating the indication can be delayed until there is an incoming androidx.compose.foundation.interaction.Interaction. If you are only passing a remembered MutableInteractionSource and you are never using it outside of clickable, it is recommended to instead provide null to enable lazy creation. If you need indication to be created eagerly, provide a remembered MutableInteractionSource.

If indication is not an IndicationNodeFactory, and instead implements the deprecated Indication.rememberUpdatedInstance method, you should explicitly pass a remembered MutableInteractionSource as a parameter for interactionSource instead of null, as this cannot be lazily created inside clickable.

If you need to support double click or long click alongside the single click, consider using combinedClickable.

Note Any removal operations on Android Views from clickable should wrap onClick in a post { } block to guarantee the event dispatch completes before executing the removal. (You do not need to do this when removing a composable because Compose guarantees it completes via the snapshot state system.)

import androidx.compose.foundation.clickable
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

val count = remember { mutableStateOf(0) }
// content that you want to make clickable
Text(text = count.value.toString(), modifier = Modifier.clickable { count.value += 1 })
Parameters
interactionSource: MutableInteractionSource?

MutableInteractionSource that will be used to dispatch PressInteraction.Press when this clickable is pressed. If null, an internal MutableInteractionSource will be created if needed.

indication: Indication?

indication to be shown when modified element is pressed. By default, indication from LocalIndication will be used. Pass null to show no indication, or current value from LocalIndication to show theme default

enabled: Boolean = true

Controls the enabled state. When false, onClick, and this modifier will appear disabled for accessibility services

onClickLabel: String? = null

semantic / accessibility label for the onClick action

role: Role? = null

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

onClick: () -> Unit

will be called when user clicks on the element

Modifier.combinedClickable

fun Modifier.combinedClickable(
    enabled: Boolean = true,
    onClickLabel: String? = null,
    role: Role? = null,
    onLongClickLabel: String? = null,
    onLongClick: (() -> Unit)? = null,
    onDoubleClick: (() -> Unit)? = null,
    hapticFeedbackEnabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    onClick: () -> Unit
): Modifier

Configure component to receive clicks, double clicks and long clicks via input or accessibility "click" event.

Add this modifier to the element to make it clickable within its bounds.

If you need only click handling, and no double or long clicks, consider using clickable

This overload will use the Indication from LocalIndication. Use the other overload to explicitly provide an Indication instance. Note that this overload only supports IndicationNodeFactory instances provided through LocalIndication - it is strongly recommended to migrate to IndicationNodeFactory, but you can use the other overload if you still need to support Indication instances that are not IndicationNodeFactory.

If interactionSource is null, an internal MutableInteractionSource will be lazily created only when needed. This reduces the performance cost of combinedClickable during composition, as creating the indication can be delayed until there is an incoming androidx.compose.foundation.interaction.Interaction. If you are only passing a remembered MutableInteractionSource and you are never using it outside of combinedClickable, it is recommended to instead provide null to enable lazy creation. If you need the Indication to be created eagerly, provide a remembered MutableInteractionSource.

Note, if the modifier instance gets re-used between a key down and key up events, the ongoing input will be aborted.

Note Any removal operations on Android Views from clickable should wrap onClick in a post { } block to guarantee the event dispatch completes before executing the removal. (You do not need to do this when removing a composable because Compose guarantees it completes via the snapshot state system.)

import androidx.compose.foundation.clickable
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

val count = remember { mutableStateOf(0) }
// content that you want to make clickable
Text(text = count.value.toString(), modifier = Modifier.clickable { count.value += 1 })
Parameters
enabled: Boolean = true

Controls the enabled state. When false, onClick, onLongClick or onDoubleClick won't be invoked

onClickLabel: String? = null

semantic / accessibility label for the onClick action

role: Role? = null

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

onLongClickLabel: String? = null

semantic / accessibility label for the onLongClick action

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

will be called when user long presses on the element

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

will be called when user double clicks on the element

hapticFeedbackEnabled: Boolean = true

whether to use the default HapticFeedback behavior

interactionSource: MutableInteractionSource? = null

MutableInteractionSource that will be used to dispatch PressInteraction.Press when this clickable is pressed. If null, an internal MutableInteractionSource will be created if needed.

onClick: () -> Unit

will be called when user clicks on the element

Modifier.combinedClickable

fun Modifier.combinedClickable(
    interactionSource: MutableInteractionSource?,
    indication: Indication?,
    enabled: Boolean = true,
    onClickLabel: String? = null,
    role: Role? = null,
    onLongClickLabel: String? = null,
    onLongClick: (() -> Unit)? = null,
    onDoubleClick: (() -> Unit)? = null,
    hapticFeedbackEnabled: Boolean = true,
    onClick: () -> Unit
): Modifier

Configure component to receive clicks, double clicks and long clicks via input or accessibility "click" event.

Add this modifier to the element to make it clickable within its bounds.

If you need only click handling, and no double or long clicks, consider using clickable.

Add this modifier to the element to make it clickable within its bounds.

If interactionSource is null, and indication is an IndicationNodeFactory, an internal MutableInteractionSource will be lazily created along with the indication only when needed. This reduces the performance cost of clickable during composition, as creating the indication can be delayed until there is an incoming androidx.compose.foundation.interaction.Interaction. If you are only passing a remembered MutableInteractionSource and you are never using it outside of clickable, it is recommended to instead provide null to enable lazy creation. If you need indication to be created eagerly, provide a remembered MutableInteractionSource.

If indication is not an IndicationNodeFactory, and instead implements the deprecated Indication.rememberUpdatedInstance method, you should explicitly pass a remembered MutableInteractionSource as a parameter for interactionSource instead of null, as this cannot be lazily created inside clickable.

Note, if the modifier instance gets re-used between a key down and key up events, the ongoing input will be aborted.

Note Any removal operations on Android Views from clickable should wrap onClick in a post { } block to guarantee the event dispatch completes before executing the removal. (You do not need to do this when removing a composable because Compose guarantees it completes via the snapshot state system.)

import androidx.compose.foundation.clickable
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier

val count = remember { mutableStateOf(0) }
// content that you want to make clickable
Text(text = count.value.toString(), modifier = Modifier.clickable { count.value += 1 })
Parameters
interactionSource: MutableInteractionSource?

MutableInteractionSource that will be used to emit PressInteraction.Press when this clickable is pressed. If null, an internal MutableInteractionSource will be created if needed.

indication: Indication?

indication to be shown when modified element is pressed. By default, indication from LocalIndication will be used. Pass null to show no indication, or current value from LocalIndication to show theme default

enabled: Boolean = true

Controls the enabled state. When false, onClick, onLongClick or onDoubleClick won't be invoked

onClickLabel: String? = null

semantic / accessibility label for the onClick action

role: Role? = null

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

onLongClickLabel: String? = null

semantic / accessibility label for the onLongClick action

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

will be called when user long presses on the element

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

will be called when user double clicks on the element

hapticFeedbackEnabled: Boolean = true

whether to use the default HapticFeedback behavior

onClick: () -> Unit

will be called when user clicks on the element

Modifier.clip

fun Modifier.clip(shape: Shape): Modifier

Clip the content to shape.

Parameters
shape: Shape

the content will be clipped to this Shape.

Modifier.clipToBounds

fun Modifier.clipToBounds(): Modifier

Clip the content to the bounds of a layer defined at this modifier.

Modifier.clipScrollableContainer

fun Modifier.clipScrollableContainer(orientation: Orientation): Modifier

Clips bounds of scrollable container on main axis while leaving space for background effects (like shadows) on cross axis.

Parameters
orientation: Orientation

orientation of the scrolling

Modifier.composed

fun Modifier.composed(
    inspectorInfo: InspectorInfo.() -> Unit = NoInspectorInfo,
    factory: @Composable Modifier.() -> Modifier
): Modifier

Declare a just-in-time composition of a Modifier that will be composed for each element it modifies. composed may be used to implement stateful modifiers that have instance-specific state for each modified element, allowing the same Modifier instance to be safely reused for multiple elements while maintaining element-specific state.

If inspectorInfo is specified this modifier will be visible to tools during development. Specify the name and arguments of the original modifier.

Example usage:

import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.debugInspectorInfo

// let's create your own custom stateful modifier
fun Modifier.myColorModifier(color: Color) =
    composed(
        // pass inspector information for debug
        inspectorInfo =
            debugInspectorInfo {
                // name should match the name of the modifier
                name = "myColorModifier"
                // specify a single argument as the value when the argument name is irrelevant
                value = color
            },
        // pass your modifier implementation that resolved per modified element
        factory = {
            // add your modifier implementation here
            Modifier
        },
    )
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.unit.Dp

// let's create your own custom stateful modifier with multiple arguments
fun Modifier.myModifier(width: Dp, height: Dp, color: Color) =
    composed(
        // pass inspector information for debug
        inspectorInfo =
            debugInspectorInfo {
                // name should match the name of the modifier
                name = "myModifier"
                // add name and value of each argument
                properties["width"] = width
                properties["height"] = height
                properties["color"] = color
            },
        // pass your modifier implementation that resolved per modified element
        factory = {
            // add your modifier implementation here
            Modifier
        },
    )

materialize must be called to create instance-specific modifiers if you are directly applying a Modifier to an element tree node.

Modifier.composed

fun Modifier.composed(
    fullyQualifiedName: String,
    key1: Any?,
    inspectorInfo: InspectorInfo.() -> Unit = NoInspectorInfo,
    factory: @Composable Modifier.() -> Modifier
): Modifier

Declare a just-in-time composition of a Modifier that will be composed for each element it modifies. composed may be used to implement stateful modifiers that have instance-specific state for each modified element, allowing the same Modifier instance to be safely reused for multiple elements while maintaining element-specific state.

When keys are provided, composed produces a Modifier that will compare equals to another modifier constructed with the same keys in order to take advantage of caching and skipping optimizations. fullyQualifiedName should be the fully-qualified import name for your modifier factory function, e.g. com.example.myapp.ui.fancyPadding.

If inspectorInfo is specified this modifier will be visible to tools during development. Specify the name and arguments of the original modifier.

Example usage:

import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.debugInspectorInfo

// let's create your own custom stateful modifier
fun Modifier.myColorModifier(color: Color) =
    composed(
        // pass inspector information for debug
        inspectorInfo =
            debugInspectorInfo {
                // name should match the name of the modifier
                name = "myColorModifier"
                // specify a single argument as the value when the argument name is irrelevant
                value = color
            },
        // pass your modifier implementation that resolved per modified element
        factory = {
            // add your modifier implementation here
            Modifier
        },
    )
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.unit.Dp

// let's create your own custom stateful modifier with multiple arguments
fun Modifier.myModifier(width: Dp, height: Dp, color: Color) =
    composed(
        // pass inspector information for debug
        inspectorInfo =
            debugInspectorInfo {
                // name should match the name of the modifier
                name = "myModifier"
                // add name and value of each argument
                properties["width"] = width
                properties["height"] = height
                properties["color"] = color
            },
        // pass your modifier implementation that resolved per modified element
        factory = {
            // add your modifier implementation here
            Modifier
        },
    )

materialize must be called to create instance-specific modifiers if you are directly applying a Modifier to an element tree node.

Modifier.composed

fun Modifier.composed(
    fullyQualifiedName: String,
    vararg keys: Any?,
    inspectorInfo: InspectorInfo.() -> Unit = NoInspectorInfo,
    factory: @Composable Modifier.() -> Modifier
): Modifier

Declare a just-in-time composition of a Modifier that will be composed for each element it modifies. composed may be used to implement stateful modifiers that have instance-specific state for each modified element, allowing the same Modifier instance to be safely reused for multiple elements while maintaining element-specific state.

When keys are provided, composed produces a Modifier that will compare equals to another modifier constructed with the same keys in order to take advantage of caching and skipping optimizations. fullyQualifiedName should be the fully-qualified import name for your modifier factory function, e.g. com.example.myapp.ui.fancyPadding.

If inspectorInfo is specified this modifier will be visible to tools during development. Specify the name and arguments of the original modifier.

Example usage:

import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.debugInspectorInfo

// let's create your own custom stateful modifier
fun Modifier.myColorModifier(color: Color) =
    composed(
        // pass inspector information for debug
        inspectorInfo =
            debugInspectorInfo {
                // name should match the name of the modifier
                name = "myColorModifier"
                // specify a single argument as the value when the argument name is irrelevant
                value = color
            },
        // pass your modifier implementation that resolved per modified element
        factory = {
            // add your modifier implementation here
            Modifier
        },
    )
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.unit.Dp

// let's create your own custom stateful modifier with multiple arguments
fun Modifier.myModifier(width: Dp, height: Dp, color: Color) =
    composed(
        // pass inspector information for debug
        inspectorInfo =
            debugInspectorInfo {
                // name should match the name of the modifier
                name = "myModifier"
                // add name and value of each argument
                properties["width"] = width
                properties["height"] = height
                properties["color"] = color
            },
        // pass your modifier implementation that resolved per modified element
        factory = {
            // add your modifier implementation here
            Modifier
        },
    )

materialize must be called to create instance-specific modifiers if you are directly applying a Modifier to an element tree node.

Modifier.composed

fun Modifier.composed(
    fullyQualifiedName: String,
    key1: Any?,
    key2: Any?,
    inspectorInfo: InspectorInfo.() -> Unit = NoInspectorInfo,
    factory: @Composable Modifier.() -> Modifier
): Modifier

Declare a just-in-time composition of a Modifier that will be composed for each element it modifies. composed may be used to implement stateful modifiers that have instance-specific state for each modified element, allowing the same Modifier instance to be safely reused for multiple elements while maintaining element-specific state.

When keys are provided, composed produces a Modifier that will compare equals to another modifier constructed with the same keys in order to take advantage of caching and skipping optimizations. fullyQualifiedName should be the fully-qualified import name for your modifier factory function, e.g. com.example.myapp.ui.fancyPadding.

If inspectorInfo is specified this modifier will be visible to tools during development. Specify the name and arguments of the original modifier.

Example usage:

import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.debugInspectorInfo

// let's create your own custom stateful modifier
fun Modifier.myColorModifier(color: Color) =
    composed(
        // pass inspector information for debug
        inspectorInfo =
            debugInspectorInfo {
                // name should match the name of the modifier
                name = "myColorModifier"
                // specify a single argument as the value when the argument name is irrelevant
                value = color
            },
        // pass your modifier implementation that resolved per modified element
        factory = {
            // add your modifier implementation here
            Modifier
        },
    )
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.unit.Dp

// let's create your own custom stateful modifier with multiple arguments
fun Modifier.myModifier(width: Dp, height: Dp, color: Color) =
    composed(
        // pass inspector information for debug
        inspectorInfo =
            debugInspectorInfo {
                // name should match the name of the modifier
                name = "myModifier"
                // add name and value of each argument
                properties["width"] = width
                properties["height"] = height
                properties["color"] = color
            },
        // pass your modifier implementation that resolved per modified element
        factory = {
            // add your modifier implementation here
            Modifier
        },
    )

materialize must be called to create instance-specific modifiers if you are directly applying a Modifier to an element tree node.

Modifier.composed

fun Modifier.composed(
    fullyQualifiedName: String,
    key1: Any?,
    key2: Any?,
    key3: Any?,
    inspectorInfo: InspectorInfo.() -> Unit = NoInspectorInfo,
    factory: @Composable Modifier.() -> Modifier
): Modifier

Declare a just-in-time composition of a Modifier that will be composed for each element it modifies. composed may be used to implement stateful modifiers that have instance-specific state for each modified element, allowing the same Modifier instance to be safely reused for multiple elements while maintaining element-specific state.

When keys are provided, composed produces a Modifier that will compare equals to another modifier constructed with the same keys in order to take advantage of caching and skipping optimizations. fullyQualifiedName should be the fully-qualified import name for your modifier factory function, e.g. com.example.myapp.ui.fancyPadding.

If inspectorInfo is specified this modifier will be visible to tools during development. Specify the name and arguments of the original modifier.

Example usage:

import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.debugInspectorInfo

// let's create your own custom stateful modifier
fun Modifier.myColorModifier(color: Color) =
    composed(
        // pass inspector information for debug
        inspectorInfo =
            debugInspectorInfo {
                // name should match the name of the modifier
                name = "myColorModifier"
                // specify a single argument as the value when the argument name is irrelevant
                value = color
            },
        // pass your modifier implementation that resolved per modified element
        factory = {
            // add your modifier implementation here
            Modifier
        },
    )
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.unit.Dp

// let's create your own custom stateful modifier with multiple arguments
fun Modifier.myModifier(width: Dp, height: Dp, color: Color) =
    composed(
        // pass inspector information for debug
        inspectorInfo =
            debugInspectorInfo {
                // name should match the name of the modifier
                name = "myModifier"
                // add name and value of each argument
                properties["width"] = width
                properties["height"] = height
                properties["color"] = color
            },
        // pass your modifier implementation that resolved per modified element
        factory = {
            // add your modifier implementation here
            Modifier
        },
    )

materialize must be called to create instance-specific modifiers if you are directly applying a Modifier to an element tree node.

fun Modifier.layoutId(layoutId: String, tag: String? = null): Modifier

Alternative to androidx.compose.ui.layout.layoutId that enables the use of tag.

Parameters
layoutId: String

The unique Id string assigned to the Composable

tag: String? = null

A string to represent a group of Composables that may be affected by a ConstraintLayout function. Eg: The Variables block in a JSON5 based ConstraintSet

Modifier.contentColorProvider

fun Modifier.contentColorProvider(contentColor: Color): Modifier

Provides contentColor for text and iconography to consume. Content color is provided automatically by surface - contentColorProvider can be used for cases where some text or icons inside a surface require a different color for emphasis.

Parameters
contentColor: Color

the content color to provide for descendants

Modifier.depthEffect

fun Modifier.depthEffect(depthEffect: DepthEffect?, shape: Shape): Modifier

Renders shadows for the provided depthEffect.

Parameters
depthEffect: DepthEffect?

Depth effect to render shadows for. If null, no shadows will be rendered.

shape: Shape

Shape of the shadows

Modifier.dragAndDropSource

fun Modifier.dragAndDropSource(
    transferData: (Offset) -> DragAndDropTransferData?
): Modifier

A Modifier that allows an element it is applied to be treated like a source for drag and drop operations. It displays the element dragged as a drag shadow.

Learn how to use Modifier.dragAndDropSource:

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.border
import androidx.compose.foundation.draganddrop.dragAndDropSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draganddrop.DragAndDropTransferData
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

val label = remember { "Drag me" }
Box(
    modifier =
        modifier
            .dragAndDropSource { _ ->
                DragAndDropTransferData(
                    clipData = ClipData.newPlainText(label, label),
                    flags = View.DRAG_FLAG_GLOBAL,
                )
            }
            .border(
                border =
                    BorderStroke(
                        width = 4.dp,
                        brush = Brush.linearGradient(listOf(Color.Magenta, Color.Magenta)),
                    ),
                shape = RoundedCornerShape(16.dp),
            )
            .padding(24.dp)
) {
    Text(modifier = Modifier.align(Alignment.Center), text = label)
}
Parameters
transferData: (Offset) -> DragAndDropTransferData?

A function that receives the current offset of the drag operation and returns the DragAndDropTransferData to be transferred. If null is returned, the drag and drop transfer won't be started.

Modifier.dragAndDropSource

@ExperimentalFoundationApi
fun Modifier.dragAndDropSource(
    drawDragDecoration: DrawScope.() -> Unit,
    block: suspend DragAndDropSourceScope.() -> Unit
): Modifier

A Modifier that allows an element it is applied to to be treated like a source for drag and drop operations.

Learn how to use Modifier.dragAndDropSource while providing a custom drag shadow:

import androidx.compose.foundation.background
import androidx.compose.foundation.draganddrop.dragAndDropSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

Box(
    modifier =
        Modifier.size(56.dp).background(color = color).dragAndDropSource(
            drawDragDecoration = { drawRect(color) }
        ) { _ ->
            color.toDragAndDropTransfer()
        }
)
Parameters
drawDragDecoration: DrawScope.() -> Unit

provides the visual representation of the item dragged during the drag and drop gesture.

block: suspend DragAndDropSourceScope.() -> Unit

A lambda with a DragAndDropSourceScope as a receiver which provides a PointerInputScope to detect the drag gesture, after which a drag and drop gesture can be started with DragAndDropSourceScope.startTransfer.

Modifier.dragAndDropSource

fun Modifier.dragAndDropSource(
    drawDragDecoration: DrawScope.() -> Unit,
    transferData: (Offset) -> DragAndDropTransferData?
): Modifier

A Modifier that allows an element it is applied to be treated like a source for drag and drop operations.

Learn how to use Modifier.dragAndDropSource while providing a custom drag shadow:

import androidx.compose.foundation.background
import androidx.compose.foundation.draganddrop.dragAndDropSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

Box(
    modifier =
        Modifier.size(56.dp).background(color = color).dragAndDropSource(
            drawDragDecoration = { drawRect(color) }
        ) { _ ->
            color.toDragAndDropTransfer()
        }
)
Parameters
drawDragDecoration: DrawScope.() -> Unit

provides the visual representation of the item dragged during the drag and drop gesture.

transferData: (Offset) -> DragAndDropTransferData?

A function that receives the current offset of the drag operation and returns the DragAndDropTransferData to be transferred. If null is returned, the drag and drop transfer won't be started.

Modifier.dragAndDropTarget

fun Modifier.dragAndDropTarget(
    shouldStartDragAndDrop: (startEvent: DragAndDropEvent) -> Boolean,
    target: DragAndDropTarget
): Modifier

A modifier that allows for receiving from a drag and drop gesture.

Learn how to use Modifier.dragAndDropTarget to receive drag and drop events from inside your app or from other apps:

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.draganddrop.dragAndDropTarget
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draganddrop.DragAndDropEvent
import androidx.compose.ui.draganddrop.DragAndDropTarget
import androidx.compose.ui.draganddrop.mimeTypes
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

val validMimeTypePrefixes = remember {
    setOf(ClipDescription.MIMETYPE_TEXT_INTENT, "image/", "text/", "video/", "audio/")
}
var backgroundColor by remember { mutableStateOf(Color.Transparent) }
val dragAndDropTarget = remember {
    object : DragAndDropTarget {
        override fun onStarted(event: DragAndDropEvent) {
            backgroundColor = Color.DarkGray.copy(alpha = 0.2f)
        }

        override fun onDrop(event: DragAndDropEvent): Boolean {
            onDragAndDropEventDropped(event)
            return true
        }

        override fun onEnded(event: DragAndDropEvent) {
            backgroundColor = Color.Transparent
        }
    }
}
Box(
    modifier =
        Modifier.fillMaxSize()
            .dragAndDropTarget(
                shouldStartDragAndDrop = accept@{ startEvent ->
                        val hasValidMimeType =
                            startEvent.mimeTypes().any { eventMimeType ->
                                validMimeTypePrefixes.any(eventMimeType::startsWith)
                            }
                        hasValidMimeType
                    },
                target = dragAndDropTarget,
            )
            .background(backgroundColor)
            .border(width = 4.dp, color = Color.Magenta, shape = RoundedCornerShape(16.dp))
) {
    when (eventSummary) {
        null -> Text(modifier = Modifier.align(Alignment.Center), text = "Drop anything here")
        else ->
            Text(
                modifier =
                    Modifier.padding(horizontal = 16.dp, vertical = 24.dp)
                        .verticalScroll(rememberScrollState()),
                text = eventSummary,
            )
    }
}
Parameters
shouldStartDragAndDrop: (startEvent: DragAndDropEvent) -> Boolean

Allows the Composable to decide if it wants to receive from a given drag and drop session by inspecting the DragAndDropEvent that started the session.

target: DragAndDropTarget

The DragAndDropTarget that will receive events for a given drag and drop session.

All drag and drop target modifiers in the hierarchy will be given an opportunity to participate in a given drag and drop session via shouldStartDragAndDrop.

Modifier.draggable2D

fun Modifier.draggable2D(
    state: Draggable2DState,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    startDragImmediately: Boolean = false,
    onDragStarted: (startedPosition: Offset) -> Unit = NoOpOnDragStart,
    onDragStopped: (velocity: Velocity) -> Unit = NoOpOnDragStop,
    reverseDirection: Boolean = false
): Modifier

Configure touch dragging for the UI element in both orientations. The drag distance reported to Draggable2DState, allowing users to react to the drag delta and update their state.

The common common usecase for this component is when you need to be able to drag something inside the component on the screen and represent this state via one float value

If you are implementing dragging in a single orientation, consider using draggable.

import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.draggable2D
import androidx.compose.foundation.gestures.rememberDraggable2DState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp

// Draw a box that has a a grey background
// with a red square that moves along 300.dp dragging in both directions
val max = 200.dp
val min = 0.dp
val (minPx, maxPx) = with(LocalDensity.current) { min.toPx() to max.toPx() }
// this is the offset we will update while dragging
var offsetPositionX by remember { mutableStateOf(0f) }
var offsetPositionY by remember { mutableStateOf(0f) }

Box(
    modifier =
        Modifier.width(max)
            .height(max)
            .draggable2D(
                state =
                    rememberDraggable2DState { delta ->
                        val newValueX = offsetPositionX + delta.x
                        val newValueY = offsetPositionY + delta.y
                        offsetPositionX = newValueX.coerceIn(minPx, maxPx)
                        offsetPositionY = newValueY.coerceIn(minPx, maxPx)
                    }
            )
            .background(Color.LightGray)
) {
    Box(
        Modifier.offset {
                IntOffset(offsetPositionX.roundToInt(), offsetPositionY.roundToInt())
            }
            .size(50.dp)
            .background(Color.Red)
    )
}
Parameters
state: Draggable2DState

Draggable2DState state of the draggable2D. Defines how drag events will be interpreted by the user land logic.

enabled: Boolean = true

whether or not drag is enabled

interactionSource: MutableInteractionSource? = null

MutableInteractionSource that will be used to emit DragInteraction.Start when this draggable is being dragged.

startDragImmediately: Boolean = false

when set to true, draggable2D will start dragging immediately and prevent other gesture detectors from reacting to "down" events (in order to block composed press-based gestures). This is intended to allow end users to "catch" an animating widget by pressing on it. It's useful to set it when value you're dragging is settling / animating.

onDragStarted: (startedPosition: Offset) -> Unit = NoOpOnDragStart

callback that will be invoked when drag is about to start at the starting position, allowing user to perform preparation for drag.

onDragStopped: (velocity: Velocity) -> Unit = NoOpOnDragStop

callback that will be invoked when drag is finished, allowing the user to react on velocity and process it.

reverseDirection: Boolean = false

reverse the direction of the dragging, so top to bottom dragging will behave like bottom to top and left to right will behave like right to left.

Modifier.draggable

fun Modifier.draggable(
    state: DraggableState,
    orientation: Orientation,
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null,
    startDragImmediately: Boolean = false,
    onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit = NoOpOnDragStarted,
    onDragStopped: suspend CoroutineScope.(velocity: Float) -> Unit = NoOpOnDragStopped,
    reverseDirection: Boolean = false
): Modifier

Configure touch dragging for the UI element in a single Orientation. The drag distance reported to DraggableState, allowing users to react on the drag delta and update their state.

The common usecase for this component is when you need to be able to drag something inside the component on the screen and represent this state via one float value

If you need to control the whole dragging flow, consider using pointerInput instead with the helper functions like detectDragGestures.

If you want to enable dragging in 2 dimensions, consider using draggable2D.

If you are implementing scroll/fling behavior, consider using scrollable.

import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp

// Draw a seekbar-like composable that has a black background
// with a red square that moves along the 300.dp drag distance
val max = 300.dp
val min = 0.dp
val (minPx, maxPx) = with(LocalDensity.current) { min.toPx() to max.toPx() }
// this is the  state we will update while dragging
val offsetPosition = remember { mutableStateOf(0f) }

// seekbar itself
Box(
    modifier =
        Modifier.width(max)
            .draggable(
                orientation = Orientation.Horizontal,
                state =
                    rememberDraggableState { delta ->
                        val newValue = offsetPosition.value + delta
                        offsetPosition.value = newValue.coerceIn(minPx, maxPx)
                    },
            )
            .background(Color.Black)
) {
    Box(
        Modifier.offset { IntOffset(offsetPosition.value.roundToInt(), 0) }
            .size(50.dp)
            .background(Color.Red)
    )
}
Parameters
state: DraggableState

DraggableState state of the draggable. Defines how drag events will be interpreted by the user land logic.

orientation: Orientation

orientation of the drag

enabled: Boolean = true

whether or not drag is enabled

interactionSource: MutableInteractionSource? = null

MutableInteractionSource that will be used to emit DragInteraction.Start when this draggable is being dragged.

startDragImmediately: Boolean = false

when set to true, draggable will start dragging immediately and prevent other gesture detectors from reacting to "down" events (in order to block composed press-based gestures). This is intended to allow end users to "catch" an animating widget by pressing on it. It's useful to set it when value you're dragging is settling / animating.

onDragStarted: suspend CoroutineScope.(startedPosition: Offset) -> Unit = NoOpOnDragStarted

callback that will be invoked when drag is about to start at the starting position, allowing user to suspend and perform preparation for drag, if desired. This suspend function is invoked with the draggable scope, allowing for async processing, if desired. Note that the scope used here is the one provided by the draggable node, for long running work that needs to outlast the modifier being in the composition you should use a scope that fits the lifecycle needed.

onDragStopped: suspend CoroutineScope.(velocity: Float) -> Unit = NoOpOnDragStopped

callback that will be invoked when drag is finished, allowing the user to react on velocity and process it. This suspend function is invoked with the draggable scope, allowing for async processing, if desired. Note that the scope used here is the one provided by the draggable node, for long running work that needs to outlast the modifier being in the composition you should use a scope that fits the lifecycle needed.

reverseDirection: Boolean = false

reverse the direction of the scroll, so top to bottom scroll will behave like bottom to top and left to right will behave like right to left.

Modifier.drawBehind

fun Modifier.drawBehind(onDraw: DrawScope.() -> Unit): Modifier

Draw into a Canvas behind the modified content.

Modifier.drawWithCache

fun Modifier.drawWithCache(onBuildDrawCache: CacheDrawScope.() -> DrawResult): Modifier

Draw into a DrawScope with content that is persisted across draw calls as long as the size of the drawing area is the same or any state objects that are read have not changed. In the event that the drawing area changes, or the underlying state values that are being read change, this method is invoked again to recreate objects to be used during drawing

For example, a androidx.compose.ui.graphics.LinearGradient that is to occupy the full bounds of the drawing area can be created once the size has been defined and referenced for subsequent draw calls without having to re-allocate.

import androidx.compose.foundation.layout.Box
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color

Box(
    Modifier.drawWithCache {
        val gradient =
            Brush.linearGradient(
                colors = listOf(Color.Red, Color.Blue),
                start = Offset.Zero,
                end = Offset(size.width, size.height),
            )
        onDrawBehind { drawRect(gradient) }
    }
)
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color

val colors1 = listOf(Color.Red, Color.Blue)
val colors2 = listOf(Color.Yellow, Color.Green)
var toggle by remember { mutableStateOf(true) }
Box(
    Modifier.clickable { toggle = !toggle }
        .drawWithCache {
            val gradient =
                Brush.linearGradient(
                    colors = if (toggle) colors1 else colors2,
                    start = Offset.Zero,
                    end = Offset(size.width, size.height),
                )
            onDrawBehind { drawRect(gradient) }
        }
)
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.vector.Path
import androidx.compose.ui.graphics.vector.PathData
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.unit.dp

val vectorPainter =
    rememberVectorPainter(24.dp, 24.dp, autoMirror = true) { viewportWidth, viewportHeight ->
        Path(
            pathData =
                PathData {
                    lineTo(viewportWidth, 0f)
                    lineTo(0f, viewportHeight)
                    close()
                },
            fill = SolidColor(Color.Black),
        )
    }
Image(
    painter = vectorPainter,
    contentDescription = null,
    modifier =
        Modifier.requiredSize(120.dp).drawWithCache {
            val gradient =
                Brush.linearGradient(
                    colors = listOf(Color.Red, Color.Blue),
                    start = Offset.Zero,
                    end = Offset(0f, size.height),
                )
            onDrawWithContent {
                drawContent()
                drawRect(gradient, blendMode = BlendMode.Plus)
            }
        },
)

Modifier.drawWithContent

fun Modifier.drawWithContent(onDraw: ContentDrawScope.() -> Unit): Modifier

Creates a DrawModifier that allows the developer to draw before or after the layout's contents. It also allows the modifier to adjust the layout's canvas.

Modifier.excludeFromSystemGesture

fun Modifier.excludeFromSystemGesture(): Modifier

Excludes the layout rectangle from the system gesture.

Modifier.excludeFromSystemGesture

fun Modifier.excludeFromSystemGesture(
    exclusion: (LayoutCoordinates) -> Rect
): Modifier

Excludes a rectangle within the local layout coordinates from the system gesture. After layout, exclusion is called to determine the Rect to exclude from the system gesture area.

The LayoutCoordinates of the Modifier's location in the layout is passed as passed as exclusion's parameter.

Modifier.animateFloatingActionButton

@ExperimentalMaterial3ExpressiveApi
fun Modifier.animateFloatingActionButton(
    visible: Boolean,
    alignment: Alignment,
    targetScale: Float = FloatingActionButtonDefaults.ShowHideTargetScale,
    scaleAnimationSpec: AnimationSpec<Float>? = null,
    alphaAnimationSpec: AnimationSpec<Float>? = null
): Modifier

Apply this modifier to a FloatingActionButton to show or hide it with an animation, typically based on the app's main content scrolling.

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MediumFloatingActionButton
import androidx.compose.material3.PlainTooltip
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TooltipAnchorPosition
import androidx.compose.material3.TooltipBox
import androidx.compose.material3.TooltipDefaults
import androidx.compose.material3.animateFloatingActionButton
import androidx.compose.material3.rememberTooltipState
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

val listState = rememberLazyListState()
// The FAB is initially shown. Upon scrolling past the first item we hide the FAB by using a
// remembered derived state to minimize unnecessary compositions.
val fabVisible by remember { derivedStateOf { listState.firstVisibleItemIndex == 0 } }

Scaffold(
    floatingActionButton = {
        // A FAB should have a tooltip associated with it.
        TooltipBox(
            positionProvider =
                TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
            tooltip = { PlainTooltip { Text("Localized description") } },
            state = rememberTooltipState(),
        ) {
            MediumFloatingActionButton(
                modifier =
                    Modifier.animateFloatingActionButton(
                        visible = fabVisible,
                        alignment = Alignment.BottomEnd,
                    ),
                onClick = { /* do something */ },
            ) {
                Icon(
                    Icons.Filled.Add,
                    contentDescription = "Localized description",
                    modifier = Modifier.size(FloatingActionButtonDefaults.MediumIconSize),
                )
            }
        }
    },
    floatingActionButtonPosition = FabPosition.End,
) {
    LazyColumn(state = listState, modifier = Modifier.fillMaxSize()) {
        for (index in 0 until 100) {
            item { Text(text = "List item - $index", modifier = Modifier.padding(24.dp)) }
        }
    }
}
Parameters
visible: Boolean

whether the FAB should be shown or hidden with an animation

alignment: Alignment

the direction towards which the FAB should be scaled to and from

targetScale: Float = FloatingActionButtonDefaults.ShowHideTargetScale

the initial scale value when showing the FAB and the final scale value when hiding the FAB

scaleAnimationSpec: AnimationSpec<Float>? = null

the AnimationSpec to use for the scale part of the animation, if null the Fast Spatial spring spec from the MotionScheme will be used

alphaAnimationSpec: AnimationSpec<Float>? = null

the AnimationSpec to use for the alpha part of the animation, if null the Fast Effects spring spec from the MotionScheme will be used

Modifier.onFocusChanged

fun Modifier.onFocusChanged(onFocusChanged: (FocusState) -> Unit): Modifier

Add this modifier to a component to observe focus state events. onFocusChanged is invoked when the focus state changes. The onFocusChanged modifier listens to the state of the first focusTarget following this modifier.

import androidx.compose.foundation.border
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color.Companion.Black
import androidx.compose.ui.graphics.Color.Companion.Green
import androidx.compose.ui.unit.dp

var color by remember { mutableStateOf(Black) }
Box(
    Modifier.border(2.dp, color)
        // The onFocusChanged should be added BEFORE the focusable that is being observed.
        .onFocusChanged { color = if (it.isFocused) Green else Black }
        .focusable()
)

Note: If you want to be notified every time the internal focus state is written to (even if it hasn't changed), use onFocusEvent instead.

Modifier.onFocusEvent

fun Modifier.onFocusEvent(onFocusEvent: (FocusState) -> Unit): Modifier

Add this modifier to a component to observe focus state events.

Modifier.focusModifier

fun Modifier.focusModifier(): Modifier

Add this modifier to a component to make it focusable.

Modifier.focusTarget

fun Modifier.focusTarget(): Modifier

Add this modifier to a component to make it focusable.

Focus state is stored within this modifier. The bounds of this modifier reflect the bounds of the focus box.

Note: This is a low level modifier. Before using this consider using Modifier.focusable(). It uses a focusTarget in its implementation. Modifier.focusable() adds semantics that are needed for accessibility.

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.focusTarget
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color.Companion.Black
import androidx.compose.ui.graphics.Color.Companion.Green
import androidx.compose.ui.unit.dp

var color by remember { mutableStateOf(Black) }
Box(
    Modifier.border(2.dp, color)
        // The onFocusChanged should be added BEFORE the focusTarget that is being observed.
        .onFocusChanged { color = if (it.isFocused) Green else Black }
        .focusTarget()
)

Modifier.focusOrder

fun Modifier.focusOrder(focusOrderReceiver: FocusOrder.() -> Unit): Modifier

Use this modifier to specify a custom focus traversal order.

import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusProperties
import androidx.compose.ui.focus.focusRequester

Column(Modifier.fillMaxSize(), Arrangement.SpaceEvenly) {
    val (item1, item2, item3, item4) = remember { FocusRequester.createRefs() }
    Row(Modifier.fillMaxWidth(), Arrangement.SpaceEvenly) {
        Box(
            Modifier.focusRequester(item1)
                .focusProperties {
                    next = item2
                    right = item2
                    down = item3
                    previous = item4
                }
                .focusable()
        )
        Box(
            Modifier.focusRequester(item2)
                .focusProperties {
                    next = item3
                    right = item1
                    down = item4
                    previous = item1
                }
                .focusable()
        )
    }
    Row(Modifier.fillMaxWidth(), Arrangement.SpaceEvenly) {
        Box(
            Modifier.focusRequester(item3).focusProperties {
                next = item4
                right = item4
                up = item1
                previous = item2
            }
        )
        Box(
            Modifier.focusRequester(item4).focusProperties {
                next = item1
                left = item3
                up = item2
                previous = item3
            }
        )
    }
}
Parameters
focusOrderReceiver: FocusOrder.() -> Unit

Specifies FocusRequesters that are used when the user wants to move the current focus to the next item, or wants to move focus left, right, up or down.

Modifier.focusOrder

fun Modifier.focusOrder(focusRequester: FocusRequester): Modifier

A modifier that lets you specify a FocusRequester for the current composable so that this focusRequester can be used by another composable to specify a custom focus order.

import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusProperties
import androidx.compose.ui.focus.focusRequester

Column(Modifier.fillMaxSize(), Arrangement.SpaceEvenly) {
    val (item1, item2, item3, item4) = remember { FocusRequester.createRefs() }
    Row(Modifier.fillMaxWidth(), Arrangement.SpaceEvenly) {
        Box(
            Modifier.focusRequester(item1)
                .focusProperties {
                    next = item2
                    right = item2
                    down = item3
                    previous = item4
                }
                .focusable()
        )
        Box(
            Modifier.focusRequester(item2)
                .focusProperties {
                    next = item3
                    right = item1
                    down = item4
                    previous = item1
                }
                .focusable()
        )
    }
    Row(Modifier.fillMaxWidth(), Arrangement.SpaceEvenly) {
        Box(
            Modifier.focusRequester(item3).focusProperties {
                next = item4
                right = item4
                up = item1
                previous = item2
            }
        )
        Box(
            Modifier.focusRequester(item4).focusProperties {
                next = item1
                left = item3
                up = item2
                previous = item3
            }
        )
    }
}

Modifier.focusOrder

fun Modifier.focusOrder(
    focusRequester: FocusRequester,
    focusOrderReceiver: FocusOrder.() -> Unit
): Modifier

A modifier that lets you specify a FocusRequester for the current composable along with focusOrder.

Modifier.focusProperties

fun Modifier.focusProperties(scope: FocusProperties.() -> Unit): Modifier

This modifier allows you to specify properties that are accessible to focusTargets further down the modifier chain or on child layout nodes.

import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.focusProperties
import androidx.compose.ui.focus.focusTarget
import androidx.compose.ui.input.InputMode.Companion.Touch
import androidx.compose.ui.platform.LocalInputModeManager

Column {
    // Always focusable.
    Box(modifier = Modifier.focusProperties { canFocus = true }.focusTarget())
    // Only focusable in non-touch mode.
    val inputModeManager = LocalInputModeManager.current
    Box(
        modifier =
            Modifier.focusProperties { canFocus = inputModeManager.inputMode != Touch }
                .focusTarget()
    )
}

Modifier.focusRequester

fun Modifier.focusRequester(focusRequester: FocusRequester): Modifier

Add this modifier to a component to request changes to focus.

import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color.Companion.Black
import androidx.compose.ui.graphics.Color.Companion.Green
import androidx.compose.ui.unit.dp

val focusRequester = remember { FocusRequester() }
var color by remember { mutableStateOf(Black) }
Box(
    Modifier.clickable { focusRequester.requestFocus() }
        .border(2.dp, color)
        // The focusRequester should be added BEFORE the focusable.
        .focusRequester(focusRequester)
        // The onFocusChanged should be added BEFORE the focusable that is being observed.
        .onFocusChanged { color = if (it.isFocused) Green else Black }
        .focusable()
)

Modifier.focusRestorer

fun Modifier.focusRestorer(fallback: FocusRequester = Default): Modifier

This modifier can be used to save and restore focus to a focus group. When focus leaves the focus group, it stores a reference to the item that was previously focused. Then when focus re-enters this focus group, it restores focus to the previously focused item.

import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.focusRestorer

LazyRow(Modifier.focusRestorer()) {
    item { Button(onClick = {}) { Text("1") } }
    item { Button(onClick = {}) { Text("2") } }
    item { Button(onClick = {}) { Text("3") } }
    item { Button(onClick = {}) { Text("4") } }
}
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.focusRestorer

val focusRequester = remember { FocusRequester() }
LazyRow(
    // If restoration fails, focus would fallback to the item associated with focusRequester.
    Modifier.focusRestorer(focusRequester)
) {
    item {
        Button(modifier = Modifier.focusRequester(focusRequester), onClick = {}) { Text("1") }
    }
    item { Button(onClick = {}) { Text("2") } }
    item { Button(onClick = {}) { Text("3") } }
    item { Button(onClick = {}) { Text("4") } }
}
Parameters
fallback: FocusRequester = Default

A FocusRequester that is used when focus restoration fails to restore the initially focused item. For example, this might happen if the item is not available to be focused. The default value of FocusRequester.Default chooses the default focusable item.

Modifier.focusRestorer

@ExperimentalComposeUiApi
fun Modifier.focusRestorer(onRestoreFailed: (() -> FocusRequester)?): Modifier

Deprecated focusRestorer API. Use the version accepting FocusRequester instead of the lambda. This method will be removed soon after submitting.

Modifier.focusGroup

fun Modifier.focusGroup(): Modifier

Creates a focus group or marks this component as a focus group. This means that when we move focus using the keyboard or programmatically using FocusManager.moveFocus(), the items within the focus group will be given a higher priority before focus moves to items outside the focus group.

In the sample below, each column is a focus group, so pressing the tab key will move focus to all the buttons in column 1 before visiting column 2.

import androidx.compose.foundation.focusGroup
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.ui.Modifier

Row {
    Column(Modifier.focusGroup()) {
        Button({}) { Text("Row1 Col1") }
        Button({}) { Text("Row2 Col1") }
        Button({}) { Text("Row3 Col1") }
    }
    Column(Modifier.focusGroup()) {
        Button({}) { Text("Row1 Col2") }
        Button({}) { Text("Row2 Col2") }
        Button({}) { Text("Row3 Col2") }
    }
}

Note: The focusable children of a focusable parent automatically form a focus group. This modifier is to be used when you want to create a focus group where the parent is not focusable. If you encounter a component that uses a focusGroup internally, you can make it focusable by using a focusable modifier. In the second sample here, the LazyRow is a focus group that is not itself focusable. But you can make it focusable by adding a focusable modifier.

import androidx.compose.foundation.border
import androidx.compose.foundation.focusable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color.Companion.Black
import androidx.compose.ui.graphics.Color.Companion.Red
import androidx.compose.ui.unit.dp

val interactionSource = remember { MutableInteractionSource() }
LazyRow(
    Modifier.focusable(interactionSource = interactionSource)
        .border(1.dp, if (interactionSource.collectIsFocusedAsState().value) Red else Black)
) {
    repeat(10) { item { Button({}) { Text("Button$it") } } }
}

Modifier.focusable

fun Modifier.focusable(
    enabled: Boolean = true,
    interactionSource: MutableInteractionSource? = null
): Modifier

Configure component to be focusable via focus system or accessibility "focus" event.

Add this modifier to the element to make it focusable within its bounds.

import androidx.compose.foundation.focusable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester

// initialize focus reference to be able to request focus programmatically
val focusRequester = remember { FocusRequester() }
// MutableInteractionSource to track changes of the component's interactions (like "focused")
val interactionSource = remember { MutableInteractionSource() }

// text below will change when we focus it via button click
val isFocused = interactionSource.collectIsFocusedAsState().value
val text =
    if (isFocused) {
        "Focused! tap anywhere to free the focus"
    } else {
        "Bring focus to me by tapping the button below!"
    }
Column {
    // this Text will change it's text parameter depending on the presence of a focus
    Text(
        text = text,
        modifier =
            Modifier
                // add focusRequester modifier before the focusable (or even in the parent)
                .focusRequester(focusRequester)
                .focusable(interactionSource = interactionSource),
    )
    Button(onClick = { focusRequester.requestFocus() }) {
        Text("Bring focus to the text above")
    }
}
Parameters
enabled: Boolean = true

Controls the enabled state. When false, element won't participate in the focus

interactionSource: MutableInteractionSource? = null

MutableInteractionSource that will be used to emit FocusInteraction.Focus when this element is being focused.

Modifier.onFocusedBoundsChanged

fun Modifier.onFocusedBoundsChanged(
    onPositioned: (LayoutCoordinates?) -> Unit
): Modifier

Calls onPositioned whenever the bounds of the currently-focused area changes. If a child of this node has focus, onPositioned will be called immediately with a non-null LayoutCoordinates that can be queried for the focused bounds, and again every time the focused child changes or is repositioned. When a child loses focus, onPositioned will be passed null.

When an event occurs, it is bubbled up from the focusable node, so the nearest parent gets the event first, and then its parent, etc.

Note that there may be some cases where the focused bounds change but the callback is not invoked, but the last LayoutCoordinates will always return the most up-to-date bounds.

Modifier.preferredFrameRate

fun Modifier.preferredFrameRate(frameRateCategory: FrameRateCategory): Modifier

Set a requested frame rate on Composable

You can set the preferred frame rate (frames per second) for a Composable using a frame rate category see: FrameRateCategory.

For increased frame rates, please consider using FrameRateCategory.High.

Keep in mind that the preferred frame rate affects the frame rate for the next frame, so use this method carefully. It's important to note that the preference is valid as long as the Composable is drawn.

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.size
import androidx.compose.material.Button
import androidx.compose.material.LocalContentColor
import androidx.compose.material.Text
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.FrameRateCategory
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.preferredFrameRate
import androidx.compose.ui.unit.dp

var targetAlpha by remember { mutableFloatStateOf(1f) }
val context = LocalContext.current
val activity: Activity? = findOwner(context)
DisposableEffect(activity) {
    activity?.window?.frameRateBoostOnTouchEnabled = false
    onDispose { activity?.window?.frameRateBoostOnTouchEnabled = true }
}

val alpha by
    animateFloatAsState(targetValue = targetAlpha, animationSpec = tween(durationMillis = 5000))

Column(modifier = Modifier.size(300.dp)) {
    Button(
        onClick = { targetAlpha = if (targetAlpha == 1f) 0.2f else 1f },
        modifier =
            Modifier.testTag("frameRateTag")
                .background(LocalContentColor.current.copy(alpha = alpha)),
    ) {
        Text(
            text = "Click Me for alpha change with frame rate category High",
            color = LocalContentColor.current.copy(alpha = alpha),
            modifier = Modifier.preferredFrameRate(FrameRateCategory.High),
        )
    }
}
Parameters
frameRateCategory: FrameRateCategory

The preferred frame rate category the content should be rendered at.

See also
graphicsLayer

Modifier.preferredFrameRate

fun Modifier.preferredFrameRate(
    frameRate: @FloatRange(from = 0.0, to = 360.0) Float
): Modifier

Set a requested frame rate on Composable

You can set the preferred frame rate (frames per second) for a Composable using a non-negative number. This API should only be used when a specific frame rate is needed for your Composable. For example, 24 or 30 for video play.

If multiple frame rates are requested, they will be aggregated to determine a feasible frame rate.

If you no longer want this modifier to influence the frame rate, clear the preference by setting it to 0.

Keep in mind that the preferred frame rate affects the frame rate for the next frame, so use this method carefully. It's important to note that the preference is valid as long as the Composable is drawn.

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.size
import androidx.compose.material.Button
import androidx.compose.material.LocalContentColor
import androidx.compose.material.Text
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.preferredFrameRate
import androidx.compose.ui.unit.dp

var targetAlpha by remember { mutableFloatStateOf(1f) }
val context = LocalContext.current
val activity: Activity? = findOwner(context)
DisposableEffect(activity) {
    activity?.window?.frameRateBoostOnTouchEnabled = false
    onDispose { activity?.window?.frameRateBoostOnTouchEnabled = true }
}

val alpha by
    animateFloatAsState(targetValue = targetAlpha, animationSpec = tween(durationMillis = 5000))

Column(modifier = Modifier.size(300.dp)) {
    Button(
        onClick = { targetAlpha = if (targetAlpha == 1f) 0.2f else 1f },
        modifier =
            Modifier.testTag("frameRateTag")
                .background(LocalContentColor.current.copy(alpha = alpha)),
    ) {
        Text(
            text = "Click Me for alpha change with 30 Hz frame rate",
            color = LocalContentColor.current.copy(alpha = alpha), // Adjust text alpha
            modifier = Modifier.preferredFrameRate(30f),
        )
    }
}
Parameters
frameRate: @FloatRange(from = 0.0, to = 360.0) Float

The preferred frame rate the content should be rendered at. Default value is 0.

See also
graphicsLayer

Modifier.graphicsLayer

fun Modifier.graphicsLayer(block: GraphicsLayerScope.() -> Unit): Modifier

A Modifier.Node that makes content draw into a draw layer. The draw layer can be invalidated separately from parents. A graphicsLayer should be used when the content updates independently from anything above it to minimize the invalidated content.

graphicsLayer can be used to apply effects to content, such as scaling, rotation, opacity, shadow, and clipping. Prefer this version when you have layer properties backed by a androidx.compose.runtime.State or an animated value as reading a state inside block will only cause the layer properties update without triggering recomposition and relayout.

NOTE: block can be invoked multiple times, which is why it's important for performance to minimize work done inside of it. block may also be invoked before effects.

import androidx.compose.animation.core.Animatable
import androidx.compose.material.Text
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer

val animatedAlpha = remember { Animatable(0f) }
Text(
    "Hello World",
    Modifier.graphicsLayer {
        alpha = animatedAlpha.value
        clip = true
    },
)
LaunchedEffect(animatedAlpha) { animatedAlpha.animateTo(1f) }
Parameters
block: GraphicsLayerScope.() -> Unit

block on GraphicsLayerScope where you define the layer properties.

Modifier.graphicsLayer

fun Modifier.graphicsLayer(
    scaleX: Float = 1.0f,
    scaleY: Float = 1.0f,
    alpha: Float = 1.0f,
    translationX: Float = 0.0f,
    translationY: Float = 0.0f,
    shadowElevation: Float = 0.0f,
    rotationX: Float = 0.0f,
    rotationY: Float = 0.0f,
    rotationZ: Float = 0.0f,
    cameraDistance: Float = DefaultCameraDistance,
    transformOrigin: TransformOrigin = TransformOrigin.Center,
    shape: Shape = RectangleShape,
    clip: Boolean = false,
    renderEffect: RenderEffect? = null,
    ambientShadowColor: Color = DefaultShadowColor,
    spotShadowColor: Color = DefaultShadowColor,
    compositingStrategy: CompositingStrategy = CompositingStrategy.Auto,
    blendMode: BlendMode = BlendMode.SrcOver,
    colorFilter: ColorFilter? = null
): Modifier

A Modifier.Element that makes content draw into a draw layer. The draw layer can be invalidated separately from parents. A graphicsLayer should be used when the content updates independently from anything above it to minimize the invalidated content.

graphicsLayer can also be used to apply effects to content, such as scaling (scaleX, scaleY), rotation (rotationX, rotationY, rotationZ), opacity (alpha), shadow (shadowElevation, shape), clipping (clip, shape), as well as altering the result of the layer with RenderEffect. Shadow color and ambient colors can be modified by configuring the spotShadowColor and ambientShadowColor respectively.

CompositingStrategy determines whether or not the contents of this layer are rendered into an offscreen buffer. This is useful in order to optimize alpha usages with CompositingStrategy.ModulateAlpha which will skip the overhead of an offscreen buffer but can generate different rendering results depending on whether or not the contents of the layer are overlapping. Similarly leveraging CompositingStrategy.Offscreen is useful in situations where creating an offscreen buffer is preferred usually in conjunction with BlendMode usage.

Note that if you provide a non-zero shadowElevation and if the passed shape is concave the shadow will not be drawn on Android versions less than 10.

Also note that alpha values less than 1.0f will have their contents implicitly clipped to their bounds unless CompositingStrategy.ModulateAlpha is specified. This is because an intermediate compositing layer is created to render contents into first before being drawn into the destination with the desired alpha. This layer is sized to the bounds of the composable this modifier is configured on, and contents outside of these bounds are omitted.

If the layer parameters are backed by a androidx.compose.runtime.State or an animated value prefer an overload with a lambda block on GraphicsLayerScope as reading a state inside the block will only cause the layer properties update without triggering recomposition and relayout.

import androidx.compose.material.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer

Text("Hello World", Modifier.graphicsLayer(alpha = 0.5f, clip = true))
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.drawscope.inset
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp

Canvas(
    modifier =
        Modifier.size(100.dp)
            .background(Color.Black)
            .graphicsLayer(
                alpha = 0.5f,
                compositingStrategy = CompositingStrategy.ModulateAlpha,
            )
) {
    // Configuring an alpha less than 1.0 and specifying
    // CompositingStrategy.ModulateAlpha ends up with the overlapping region
    // of the 2 draw rect calls to blend transparent blue and transparent red
    // against the black background instead of just transparent blue which is what would
    // occur with CompositingStrategy.Auto or CompositingStrategy.Offscreen
    inset(0f, 0f, size.width / 3, size.height / 3) { drawRect(color = Color.Red) }
    inset(size.width / 3, size.height / 3, 0f, 0f) { drawRect(color = Color.Blue) }
}
Parameters
scaleX: Float = 1.0f

see GraphicsLayerScope.scaleX

scaleY: Float = 1.0f

see GraphicsLayerScope.scaleY

alpha: Float = 1.0f

see GraphicsLayerScope.alpha

translationX: Float = 0.0f

see GraphicsLayerScope.translationX

translationY: Float = 0.0f

see GraphicsLayerScope.translationY

shadowElevation: Float = 0.0f

see GraphicsLayerScope.shadowElevation

rotationX: Float = 0.0f

see GraphicsLayerScope.rotationX

rotationY: Float = 0.0f

see GraphicsLayerScope.rotationY

rotationZ: Float = 0.0f

see GraphicsLayerScope.rotationZ

cameraDistance: Float = DefaultCameraDistance

see GraphicsLayerScope.cameraDistance

transformOrigin: TransformOrigin = TransformOrigin.Center

see GraphicsLayerScope.transformOrigin

shape: Shape = RectangleShape

see GraphicsLayerScope.shape

clip: Boolean = false

see GraphicsLayerScope.clip

renderEffect: RenderEffect? = null

see GraphicsLayerScope.renderEffect

ambientShadowColor: Color = DefaultShadowColor

see GraphicsLayerScope.ambientShadowColor

spotShadowColor: Color = DefaultShadowColor

see GraphicsLayerScope.spotShadowColor

compositingStrategy: CompositingStrategy = CompositingStrategy.Auto

see GraphicsLayerScope.compositingStrategy

blendMode: BlendMode = BlendMode.SrcOver

see GraphicsLayerScope.blendMode

colorFilter: ColorFilter? = null

see GraphicsLayerScope.colorFilter

Modifier.toolingGraphicsLayer

fun Modifier.toolingGraphicsLayer(): Modifier

A Modifier.Element that adds a draw layer such that tooling can identify an element in the drawn image.

Modifier.handwritingDetector

fun Modifier.handwritingDetector(callback: () -> Unit): Modifier

Configures an element to act as a handwriting detector which detects stylus handwriting and delegates handling of the recognised text to another element.

Stylus movement on the element will start a handwriting session, and trigger the callback. The callback implementation is expected to show and focus a text input field with a handwritingHandler modifier which can handle the recognized text from the handwriting session.

A common use case is a component which looks like a text input field but does not actually support text input itself, and clicking on this fake text input field causes a real text input field to be shown. To support handwriting initiation in this case, this modifier can be applied to the fake text input field to configure it as a detector, and a handwritingHandler modifier can be applied to the real text input field. The callback implementation is typically the same as the onClick implementation for the fake text field's clickable modifier, which shows and focuses the real text input field.

This function returns a no-op modifier on API levels below Android U (34) as stylus handwriting is not supported.

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.handwriting.handwritingDetector
import androidx.compose.foundation.text.handwriting.handwritingHandler
import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Card
import androidx.compose.material.ContentAlpha
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.platform.LocalWindowInfo
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog

var openDialog by remember { mutableStateOf(false) }
val focusRequester = remember { FocusRequester() }

Column(
    Modifier.imePadding().requiredWidth(300.dp).verticalScroll(rememberScrollState()),
    verticalArrangement = Arrangement.Center,
    horizontalAlignment = Alignment.CenterHorizontally,
) {
    Text(
        "This is not an actual text field, but it is a handwriting detector so you can use " +
            "a stylus to write here."
    )
    Spacer(Modifier.size(16.dp))
    Text(
        "Fake text field",
        Modifier.fillMaxWidth()
            .handwritingDetector { openDialog = !openDialog }
            .padding(4.dp)
            .border(
                1.dp,
                MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled),
                RoundedCornerShape(4.dp),
            )
            .padding(16.dp),
        color = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium),
    )
}

if (openDialog) {
    Dialog(onDismissRequest = { openDialog = false }) {
        Card(modifier = Modifier.width(300.dp), shape = RoundedCornerShape(16.dp)) {
            Column(
                modifier = Modifier.padding(24.dp),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally,
            ) {
                Text("This text field is a handwriting handler.")
                Spacer(Modifier.size(16.dp))
                val state = remember { TextFieldState() }
                BasicTextField(
                    state = state,
                    modifier =
                        Modifier.fillMaxWidth()
                            .focusRequester(focusRequester)
                            .handwritingHandler(),
                    decorator = { innerTextField ->
                        Box(
                            Modifier.padding(4.dp)
                                .border(
                                    1.dp,
                                    MaterialTheme.colors.onSurface,
                                    RoundedCornerShape(4.dp),
                                )
                                .padding(16.dp)
                        ) {
                            innerTextField()
                        }
                    },
                )
            }
        }

        val windowInfo = LocalWindowInfo.current
        LaunchedEffect(windowInfo) {
            snapshotFlow { windowInfo.isWindowFocused }
                .collect { isWindowFocused ->
                    if (isWindowFocused) {
                        focusRequester.requestFocus()
                    }
                }
        }
    }
}
Parameters
callback: () -> Unit

a callback which will be triggered when stylus handwriting is detected

Modifier.handwritingHandler

fun Modifier.handwritingHandler(): Modifier

Configures an element to act as a stylus handwriting handler which can handle text input from a handwriting session which was triggered by stylus handwriting on a handwriting detector.

When this element gains focus, if there is an ongoing stylus handwriting delegation which was triggered by stylus handwriting on a handwriting detector, this element will receive text input from the handwriting session via its input connection.

A common use case is a component which looks like a text input field but does not actually support text input itself, and clicking on this fake text input field causes a real text input field to be shown. To support handwriting initiation in this case, a handwritingDetector modifier can be applied to the fake text input field to configure it as a detector, and this modifier can be applied to the real text input field. The