Released documentation snapshot. This immutable manual describes
viewcompose-gesture:0.1.0-alpha01from source revisionfbe1614d. For current guidance, open the current module catalog.
Gesture
viewcompose-gesture is the composition-facing gesture DSL for ViewCompose. It adds raw pointer,
combined click, drag, anchored drag, transform, priority, and nested-scroll elements to Modifier,
and provides remembered callback/state holders for renderer delivery. The module declares behavior;
the Android renderer owns the native pointer stream and recognition engine.
Artifact and stability
dependencies {
implementation("com.viewcompose:viewcompose-gesture:0.1.0-alpha01")
}
- Stability: Alpha. Modifier shapes and current state semantics are reviewed and tested; gesture arbitration and richer mutation APIs may evolve between alphas.
- Platform: Android library API, although the public values are renderer-neutral.
- It exposes
viewcompose-gesture-coretransitively and uses runtime/widget composition internally. - Most applications should depend on this artifact rather than gesture core directly.
Recognition ownership
Gesture modifiers are immutable descriptions. They do not install Android listeners when built and
do not recognize input themselves. The renderer interprets them when a node is mounted, owns
MotionEvent, pointer IDs, VelocityTracker, touch slop, layout-direction resolution, competing
recognizers, nested-scroll ordering, and cancellation caused by replacement or disposal.
Callbacks run synchronously on the renderer dispatch thread, normally Android's UI thread. Keep them short and move blocking or suspend work into an application-owned coroutine. Distances and pan values are normally physical pixels; terminal drag velocity is pixels per second.
Pointer and click input
pointerInput exposes normalized down, move, up, and cancel events without the native event object.
Its key is an identity input for the handler. Return Consumed only when subsequent recognition
should treat the event as consumed.
combinedClickable lets one renderer recognizer coordinate single, double, and long clicks. Timing
and slop come from Android. Disabled calls and calls with no callbacks return the original modifier
unchanged, avoiding an inert native recognizer.
val actions = Modifier.combinedClickable(
onClick = { openItem() },
onLongClick = { openContextMenu() },
)
One-dimensional drag
rememberDraggableState returns a stable object while always forwarding to the latest callback.
It does not accumulate or clamp an offset, so application state owns those rules. draggable
declares the orientation and lifecycle callbacks. Start is delivered only after recognition crosses
slop and produces local movement; normal stop carries signed axis velocity, while cancellation is a
separate callback.
Free orientation locks to the dominant axis. Cancellation can report system cancellation, transform takeover, pointer consumption, modifier replacement, or disposal. Do not treat cancellation as a zero-velocity normal stop.
Anchored drag
DraggableAnchors is a validated, immutable, non-empty set of finite unique pixel offsets. Input
order is sorted automatically. Semantic values may repeat, but unique values are recommended
because offsetOf selects the first match. Exact floating-point equality is used by valueAt.
val anchors = draggableAnchors<SheetValue> {
anchor(0f, SheetValue.Collapsed)
anchor(480f, SheetValue.Expanded)
}
val sheet = rememberAnchoredDraggableState(SheetValue.Collapsed)
val modifier = Modifier.anchoredDraggable(
state = sheet,
anchors = anchors,
orientation = GestureOrientation.Vertical,
)
The modifier synchronously installs its latest anchors into the state on each composition call.
When the current value still exists, its exact offset is preserved. If it disappears, the nearest
anchor to the current visual offset becomes current. Raw movement updates an unclamped visual
offset; completion commits the renderer-selected nearest target. This release settles immediately
without an animation, so targetValue normally changes with currentValue.
rememberAnchoredDraggableState reads initialValue only when first remembered. Changing the
argument later does not reset state; call snapTo explicitly. Snapping to a value absent from the
current anchors stores the semantic value and clears the offset until the next anchor reconciliation.
Anchored dragging accepts horizontal or vertical orientation only.
Transform gestures
rememberTransformableState forwards incremental multiplicative zoom, pan in physical pixels, and
clockwise rotation in degrees. It does not accumulate, constrain, or animate a transform.
transformable supplies start, normal-stop, and cancellation callbacks. Multi-pointer activation
can take over and cancel an active drag on the same dispatch path.
Application state should accumulate scale and translation and apply its own bounds. Avoid retaining per-event objects or launching a new coroutine for every transform delta.
Gesture priority and nested scroll
gesturePriority(High) requests an earlier recognition opportunity but never guarantees
consumption. A high-priority recognizer that rejects the event still allows other recognizers to run.
nestedScroll attaches a NestedScrollConnection to the mounted ancestor chain. Pre callbacks run
before child consumption and post callbacks after it. An optional NestedScrollDispatcher supports
imperative application dispatch; while detached it consumes zero, and renderer disposal detaches
the old connector without disrupting a newer mount. Connections must return only the distance or
velocity they actually consumed.
Testing gesture UI
- Unit-test state accumulation and anchor replacement separately from native recognition.
- Test callback order across start, deltas, normal stop, and every cancellation reason.
- Exercise touch-slop thresholds, competing drag/transform recognizers, and RTL swipe direction in renderer or instrumented tests.
- Test nested-scroll pre order outside-in and post order inside-out, including over-consumption clamping at the renderer boundary.
- Recompose with changed lambdas and verify remembered state forwards to the latest callback.
The module suite covers modifier encoding, no-op click declarations, drag and transform forwarding, anchored nearest settle, invalid free orientation, priority encoding, and nested-scroll attachment.
Related documentation
- Gesture Core module
- UI Contract module
- Renderer module
- Source documentation and API comment standard
The complete generated reference is available in the
viewcompose-gesture API tree.
Compatibility notes
The 0.1.0-alpha01 line establishes synchronous callback delivery, latest-lambda remembered state,
renderer-owned recognition, immediate anchored settling, explicit cancellation, and detachable
nested-scroll dispatch. API resemblance to Jetpack Compose gesture modifiers does not imply the same
suspend mutation, MutatorMutex, or animation behavior.