Modifier.magnetic¶
Drag horizontally; on release, snap to the nearest anchor.
When to use¶
- Drawer-style "swipe to reveal actions" rows where settled positions are 0 / partial / full.
- Slider-with-stops inputs (volume presets, intensity levels).
- "Drag the chip into a category" gestures.
When not to use¶
- Continuous-range sliders (use
Sliderfrom Material). - Gestures where overshoot/elastic feel matters more than discreteness.
Usage¶
Box(
modifier = Modifier
.size(48.dp)
.magnetic(anchors = listOf((-120).dp, 0.dp, 120.dp))
.background(Color.Blue, CircleShape),
)
Parameters¶
| Name | Type | Default | Notes |
|---|---|---|---|
anchors | List<Dp> | required | Offsets from rest. 0.dp is included implicitly as a rest anchor. |
snapThreshold | Dp | 24.dp | Distance from an anchor within which snap occurs. Larger = stickier. |
Design notes¶
- Node subtype:
DelegatingNode + LayoutModifierNode. Delegates to aSuspendingPointerInputModifierNoderunningdetectDragGestures. On release, we find the nearest anchor in pixel-space andAnimatable.animateToit. - Density handling: the modifier needs density to convert the dp-typed anchors to pixels at snap time. We snapshot density inside
measure()(where theMeasureScopeprovides it) and use the captured value at gesture-end time. - Implicit rest anchor: if your anchor list doesn't include
0.dp, the modifier adds it. Lets you writeanchors = listOf(120.dp)for a single non-zero detent and still get spring-back. - No haptic by default: intentional. Wire your own
HapticFeedback.performHapticFeedback(LongPress)from a state observer if you want a tap-on-snap.