transformingMovable
Deprecated
This modifier is deprecated. Use movable() with MovePolicy.default() instead.
public fun SubspaceModifier.transformingMovable(
enabled: Boolean = true,
scaleWithDistance: Boolean = true,
onMove: ((SpatialMoveEvent) -> Unit)? = null,
): SubspaceModifier
Configures this subspace element to be interactive and movable, delegating the pose transformation to the system.
When this modifier is present and enabled, draggable UI controls will be shown that allow the user to move the element in 3D space. The system intercepts spatial input events, calculates the resulting Pose and scale, and automatically applies these transformations to the element's layout. This is the default behavior for standard movable UI elements where a 1:1 transformation is desired, and custom gesture handling or manual state management is not required. Input events used for moving in this way are consumed.
Modifier Chaining & Ordering Behavior
When combining transformingMovable with orientation modifiers such as rotateToLookAtUser, the order of the modifier chain significantly affects the translation and rotation behavior:
transformingMovable().rotateToLookAtUser(): SincetransformingMovableacts as the parent, the drag translation is applied directly inActivitySpacecoordinates. The childrotateToLookAtUsercontinuously overrides local rotation to point toward the user's head pose. To prevent visual conflicts and jitter with the system's drag gesture orientation handling, continuous head-tracking updates are intentionally suppressed while a system move is ongoing. Consequently, during active dragging, the panel uses the default smooth drag orientation, and active face-user head-tracking resumes once the drag gesture ends.rotateToLookAtUser().transformingMovable(): SincerotateToLookAtUseracts as the parent, the childtransformingMovabletranslates within the parent's rotated space. As a result, the translation offset applied by the drag is rotated by the parent's orientation, causing the final translation of the panel inActivitySpaceto be mathematically rotated relative to the straight drag path.
There are some limitations that should be considered when using this modifier: 1) the draggable UI controls of nested composables using the transformingMovable modifier and movable modifier may conflict with each other, 2) attaching multiple transformingMovable modifiers to the same element will compound the movement distance, since each modifier independently applies the drag offset upon release. 3) It should not be used with the following composables androidx.xr.compose.subspace.SpatialExternalSurfaceHemisphere and androidx.xr.compose.subspace.SpatialExternalSurfaceSphere due to their similarity with the system environment and not having any layout size. 4) If this element has animations that affect its layout properties (e.g., offset), these animations should be stopped when a move gesture starts (detected via the onMove callback with SpatialMoveEventType.Start) to prevent rendering jitter, and can be resumed when the gesture ends (SpatialMoveEventType.End).
Parameters
| enabled | true if this composable should be movable. Setting this to false will remove the interactable affordance associated with the content. Disabling the modifier after movement keeps the composable at its last dragged position. Removing the modifier entirely resets the composable to its original layout position. |
| scaleWithDistance | true if this composable should scale in size when moved in depth. When enabled, the subspace element will grow if pushed away from the user or shrink when pulled toward the user in order to maintain the interact-ability and legibility of the panel. Scaling with distance respects other transformations applied to this layout. |
| onMove | Optional observer callback invoked during the manipulation. Since the system automatically applies the move, this callback is strictly for monitoring changes and should not control the position. The onMove callback values can be used to position other sibling composables with the offset modifier. This callback reports a SpatialMoveEvent which will contain a Pose. The Pose contained in this event represents the accumulated spatial transformation (including drag translation offsets and system-calculated orientation changes) expressed in ActivitySpace coordinates. |