Modifiers

Jetpack Compose modifiers reference — padding, size, click, scroll, gesture, clipping, and chaining

Modifiers are the way to decorate or configure a composable in Compose. They chain together and the order matters.

Modifier ordering

Order matters. Each modifier wraps the one after it.

// Padding is OUTSIDE the background
Modifier
    .padding(16.dp)     // 16dp padding around the entire thing
    .background(Color.Blue)  // blue background inside the padding
    .padding(8.dp)      // 8dp padding between background and text

// vs. background is OUTSIDE the padding
Modifier
    .background(Color.Blue)
    .padding(16.dp)      // padding inside the blue background

Padding

// All sides
Modifier.padding(16.dp)

// Different values
Modifier.padding(horizontal = 16.dp, vertical = 8.dp)

// Individual sides
Modifier.padding(start = 8.dp, top = 4.dp, end = 8.dp, bottom = 4.dp)

// Padding around specific content (inside scroll, etc.)
Modifier.padding(innerPadding)

Size

// Exact size
Modifier.size(48.dp)                // 48 x 48
Modifier.size(width = 200.dp, height = 100.dp)

// Fill parent
Modifier.fillMaxSize()              // fill max width and height
Modifier.fillMaxWidth()             // fill max width
Modifier.fillMaxHeight()            // fill max height

// Constrain size
Modifier.widthIn(min = 100.dp, max = 300.dp)
Modifier.heightIn(min = 50.dp)
Modifier.defaultMinSize(minWidth = 48.dp, minHeight = 48.dp)

// Weight in Row/Column (like LinearLayout weight)
Modifier.weight(1f)                 // take remaining space
Modifier.weight(2f)                 // take 2x remaining space

Click and interaction

// Clickable
Modifier.clickable { /* handle click */ }

// Clickable with indication (ripple)
Modifier.clickable(
    interactionSource = remember { MutableInteractionSource() },
    indication = ripple(),
) { /* handle click */ }

// Combined clickable (click, long click, double click)
Modifier.pointerInput(Unit) {
    detectTapGestures(
        onPress = { /* touch down */ },
        onTap = { offset -> /* single tap */ },
        onDoubleTap = { offset -> /* double tap */ },
        onLongPress = { offset -> /* long press */ },
    )
}

Scrolling

// Vertical scroll (for small content, not LazyColumn)
Modifier.verticalScroll(rememberScrollState())

// Horizontal scroll
Modifier.horizontalScroll(rememberScrollState())

// Scroll to position programmatically
val scrollState = rememberScrollState()
Modifier.verticalScroll(scrollState)

LaunchedEffect(Unit) {
    scrollState.animateScrollTo(100)
}

// Nested scrolling is automatic in Compose

Clipping and shape

// Clip to shape
Modifier.clip(CircleShape)                          // circular
Modifier.clip(RoundedCornerShape(12.dp))           // rounded corners
Modifier.clip(RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp))  // top only

// Border
Modifier.border(1.dp, Color.Gray, RoundedCornerShape(8.dp))

// Border + clip
Modifier
    .clip(RoundedCornerShape(12.dp))
    .border(1.dp, MaterialTheme.colorScheme.outline, RoundedCornerShape(12.dp))

Background and shadow

// Solid color background
Modifier.background(Color.Blue)

// Background with shape
Modifier.background(Color.Blue, RoundedCornerShape(12.dp))

// Brush background (gradient)
Modifier.background(
    Brush.linearGradient(
        colors = listOf(Color.Blue, Color.Cyan),
        start = Offset(0f, 0f),
        end = Offset(1000f, 1000f),
    )
)

// Shadow (M3 Card uses elevation)
Modifier.shadow(4.dp, RoundedCornerShape(8.dp))

Visibility

// Conditional visibility
if (isVisible) {
    Text("Visible content")
}

// Animated visibility
AnimatedVisibility(visible = isVisible) {
    Text("Animated content")
}

// Animated visibility with slide
AnimatedVisibility(
    visible = isVisible,
    enter = slideInVertically() + fadeIn(),
    exit = slideOutVertically() + fadeOut(),
) {
    Text("Sliding content")
}

// Alpha for semi-hidden
Modifier.alpha(0.5f)

Focus and keyboard

val focusRequester = remember { FocusRequester() }
val focusManager = LocalFocusManager.current

Modifier
    .focusRequester(focusRequester)
    .focusable()

// Request focus
LaunchedEffect(Unit) {
    focusRequester.requestFocus()
}

// Clear focus (hide keyboard)
focusManager.clearFocus()

// Handle keyboard actions
TextField(
    value = text,
    onValueChange = { text = it },
    modifier = Modifier
        .focusRequester(focusRequester)
        .onFocusChanged { state -> isFocused = state.isFocused },
    keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
    keyboardActions = KeyboardActions(
        onDone = { focusManager.clearFocus() }
    ),
)

Gestures

// Drag
Modifier.draggable(
    state = rememberDraggableState { delta -> offset += delta },
    orientation = Orientation.Vertical,
)

// Swipe to dismiss
Modifier.swipeToDismiss(
    state = rememberSwipeToDismissBoxState(),
    directions = setOf(SwipeToDismissBoxDirection.EndToStart),
) { state ->
    if (state.currentValue == SwipeToDismissBoxValue.DismissedToEnd ||
        state.currentValue == SwipeToDismissBoxValue.DismissedToStart) {
        onDismiss()
    }
    Content()
}

// Transformable (pinch zoom, pan)
Modifier.transformable(state = rememberTransformableState { zoomChange, offsetChange, _ ->
    scale *= zoomChange
    offset += offsetChange
})

// Scroll with Transformable
Modifier.scrollable(
    state = rememberScrollableState { delta -> /* handle */ },
    orientation = Orientation.Vertical,
)

Common chains

// Card-like surface
Modifier
    .fillMaxWidth()
    .padding(horizontal = 16.dp, vertical = 4.dp)
    .clip(RoundedCornerShape(12.dp))
    .background(MaterialTheme.colorScheme.surface)
    .clickable { /* ... */ }
    .padding(16.dp)

// Avatar
Modifier
    .size(48.dp)
    .clip(CircleShape)
    .background(MaterialTheme.colorScheme.primaryContainer)

// Full-width button
Modifier
    .fillMaxWidth()
    .height(48.dp)

// List item
Modifier
    .fillMaxWidth()
    .clickable { /* navigate */ }
    .padding(horizontal = 16.dp, vertical = 12.dp)