Kompoz0.1.1 Türkçe
Design

Modifiers

A Modifier decorates or augments a composable: its size and padding, its background, what happens when it is clicked, what it tells accessibility services. Modifiers chain, and the order of the chain matters.

Using modifiers

Most composables take a Modifier as a parameter. A chain starts from Modifier() and each call adds an element:

void ArtistCard(const std::string& name) {
Row(Modifier()
.fillMaxWidth()
.clickable([] { /* open the artist */ })
.padding(16),
[&] {
Icon(Icons::Filled::Person, "", Modifier().size(40));
Spacer(Modifier().width(12));
Text(name, {.font = typography().titleMedium});
});
}

Modifiers are plain values: you can store them in variables, pass them around and build them conditionally.

Modifier base = Modifier().fillMaxWidth().padding(8);
Box(selected ? base.background(colorScheme().secondaryContainer, 12) : base);

Order matters

Each element wraps everything after it in the chain. The first element is the outermost: it is measured first and draws around the rest. So the same elements in a different order give a different result:

// The whole 72 dp area is clickable, and the padding is inside the click area.
Box(Modifier().clickable([] {}).padding(16).size(40));

// Only the 40 dp box is clickable; the padding is outside it.
Box(Modifier().padding(16).clickable([] {}).size(40));

The same goes for backgrounds:

Box(Modifier().background(colorScheme().primaryContainer).padding(16).size(40));   // padding is colored
Box(Modifier().padding(16).background(colorScheme().primaryContainer).size(40));   // padding is not

Read a chain from left to right as "from the outside in".

Common modifiers

Size

ModifierWhat it does
size(s), size(w, h), width(w), height(h)A preferred size, within the parent's constraints.
requiredSize(…), requiredWidth(w), requiredHeight(h)The size even if the parent's constraints say otherwise.
widthIn(min, max), heightIn(min, max), sizeIn(…)Bounds on the size.
defaultMinSize(w, h)A minimum the content may override.
fillMaxWidth(f), fillMaxHeight(f), fillMaxSize(f)All of the space the parent offers (or a fraction of it).
wrapContentSize(align), wrapContentWidth, wrapContentHeightThe content's own size, aligned in what the parent forces.
aspectRatio(r)A width-to-height ratio within the constraints.
width(IntrinsicSize::Min), height(IntrinsicSize::Max)The content's intrinsic size (see Custom layouts).

All lengths are in dp.

Padding and position

ModifierWhat it does
padding(all), padding(h, v), padding(start, top, end, bottom), padding(PaddingValues)Space around the content. start and end swap in right-to-left layouts.
absolutePadding(left, top, right, bottom)Padding that doesn't mirror.
offset(x, y)Moves the content without changing its layout size.
offset([] { return Offset{…}; })The same, read during layout: for offsets that change often (see Phases).
windowInsetsPadding(insets), safeDrawingPadding(), systemBarsPadding(), imePadding()…Keeps content clear of the system bars, the display cutout or the keyboard.

Drawing

ModifierWhat it does
background(color, shape), background(brush, shape)Fills behind the content.
border(width, color, shape)Draws an outline.
clip(shape)Clips the content to a shape.
shadow(elevation, shape), dropShadow, innerShadowShadows.
alpha(a), scale(s), rotate(degrees), graphicsLayer(…), blur(r)Changes how the content is drawn, not its layout.
drawBehind(…), drawWithContent(…), drawWithCache(…)Your own drawing (see Graphics).

Interaction

ModifierWhat it does
clickable(onClick), combinedClickable(onClick, onLongClick)Clicks and taps, with a ripple, keyboard activation and accessibility.
selectable(selected, onClick, role), toggleable(value, onChange, role)Selection and toggling, for rows that act as a radio button or a checkbox.
draggable, anchoredDraggable, transformable, pointerInputGestures (see Gestures).
verticalScroll(state), horizontalScroll(state), scrollableScrolling (see Lists and grids).
focusable(), focusRequester(r), onKeyEvent(…)Keyboard focus and keys.
pointerHoverIcon(PointerIcon::Hand)The mouse cursor over it.

Accessibility and tests

ModifierWhat it does
semantics({…}), clearAndSetSemantics({…})What accessibility services are told (see Accessibility).
testTag("name")A name tests can find the node by (see Testing).

Layout callbacks

ModifierWhat it does
onSizeChanged([](Size s) { … })Called when the node's size changes.
onGloballyPositioned([](const LayoutCoordinates& c) { … })Called when its position in the window changes.
onVisibilityChanged([](bool visible) { … })Called when it becomes visible or stops being.
zIndex(z)Draws it above or below its siblings.

Scope modifiers

Some modifiers only make sense inside a particular parent, like Compose's scoped modifiers (RowScope.weight):

ModifierInsideWhat it does
weight(w)Row, ColumnShares the space left over among weighted children.
align(Alignment::…)BoxAligns this child in the box.
align(Alignment::CenterHorizontally)ColumnAligns this child across the column.
align(Alignment::CenterVertically), alignByBaseline()RowAligns this child across the row.
matchParentSize()BoxAs big as the box, without making it bigger.
fillParentMaxWidth(), fillParentMaxHeight()Lazy list itemsA share of the list's viewport.
animateItem()Lazy list itemsAnimates the item when it appears, moves or goes away.
flex(config)FlexBoxHow the child grows and shrinks.
gridItem(row, column, …)GridWhere the child goes in the grid.

In C++ these are ordinary Modifier methods: the compiler won't stop you from using weight outside a Row or a Column, it just has no effect there.

Row(Modifier().fillMaxWidth(), [&] {
Text("Left", Modifier().weight(1));
Text("Right");
});

Writing your own

Combining modifiers

C++ has no extension functions, so a modifier of your own is a function that returns a chain. Join it to another chain with then:

Modifier cardSurface() {
return Modifier().shadow(2, RoundedCornerShape(16)).background(colorScheme().surfaceContainerLow, RoundedCornerShape(16)).padding(16);
}

void Note(const std::string& text) {
Box(Modifier().fillMaxWidth().then(cardSurface()), [&] { Text(text); });
}

A function that takes the chain to extend reads naturally, too: Modifier card(const Modifier& m = {}) { return m.padding(…); }.

Changing measurement

layout measures the content through measure with the constraints you choose and returns this node's size; placeAt says where the content goes inside it:

// The content centered in a square as big as its longer side.
Modifier squareAround() {
return Modifier().layout([](const MeasureNext& measure, const Constraints& c, Offset& placeAt) {
Size content = measure(c.loosen());
float side = std::max(content.width, content.height);
placeAt = {(side - content.width) / 2, (side - content.height) / 2};
return c.constrain(Size{side, side});
});
}

Custom drawing

drawBehind draws behind the content, drawWithContent around it. See Graphics.

Modifier underline(Color color) {
return Modifier().drawBehind([color](DrawScope& d) {
d.drawLine(color, {0, d.size().height}, {d.size().width, d.size().height}, 2);
});
}

Modifier elements

Underneath, a modifier is a list of ModifierElements. An element can take part in measuring, drawing and input; then(std::make_shared<MyElement>(…)) adds one. This is a lower-level API, used by the library's own modifiers; the functions above cover most needs. If you write an element, implement equals so that a composable called with an equal modifier can still be skipped.

See also

  • Layouts: the parents scope modifiers work in.
  • Phases: modifiers that read state while laying out or drawing.
  • Gestures and Graphics for the interaction and drawing modifiers.
Kompoz is licensed under the Apache License 2.0. Code samples on this site are part of it.