Subspace

Functions summary

Unit

Create a 3D area that the app can render spatial content into.

Unit
@Composable
@ComposableOpenTarget(index = -1)
Subspace(
    modifier: SubspaceModifier,
    allowUnboundedSubspace: Boolean,
    content: @Composable @SubspaceComposable SpatialBoxScope.() -> Unit
)

This function is deprecated. The allowUnboundedSubspace parameter is deprecated.

Functions

@Composable
@ComposableOpenTarget(index = -1)
fun Subspace(
    modifier: SubspaceModifier = SubspaceModifier,
    content: @Composable @SubspaceComposable SpatialBoxScope.() -> Unit
): Unit

Create a 3D area that the app can render spatial content into.

Subspace creates a Compose for XR Spatial UI hierarchy (3D Scene Graph) in your application's regular Compose UI tree. In this Subspace, You can use a @SubspaceComposable annotated composable functions to create 3D UI elements.

Each call to Subspace creates a new, independent Spatial UI hierarchy. It does not inherit the spatial position, orientation, or scale of any parent Subspace it is nested within. Its position and scale are solely decided by the system's recommended position and scale. To create an embedded Subspace within a SpatialPanel, Orbiter, SpatialPopup and etc, use the PlanarEmbeddedSubspace instead.

By default, this Subspace is automatically bounded by the system's recommended content box. The recommended content box is a fixed 3D volume that uses the device's field of view (FOV) angles, the system's default launch distance from the user, and the default scale of the system to calculate a box that is sized to encompass the user's primary field of view.

This size does not change throughout the lifecycle of the application, and it does not have an independent concept of pose. When used by Compose for XR to set the constraints of a Subspace, its effective pose is the root of the Subspace.

Using this default is the suggested way to create responsive spatial layouts that look great without hardcoding dimensions. SubspaceModifiers like SubspaceModifier.fillMaxSize will expand to fill this recommended box. This default can be overridden by applying a custom size-based modifier.

This composable is a no-op and does not render anything in non-XR environments (i.e., Phone and Tablet).

On XR devices that cannot currently render spatial UI, the Subspace will still create its scene and all of its internal state, even though nothing may be rendered. This is to ensure that the state is maintained consistently in the spatial scene and to allow preparation for the support of rendering spatial UI. State should be maintained by the compose runtime and events that cause the compose runtime to lose state (app process killed or configuration change) will also cause the Subspace to lose its state.

import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.dp
import androidx.xr.compose.spatial.Subspace
import androidx.xr.compose.subspace.SpatialPanel
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.fillMaxSize
import androidx.xr.compose.subspace.layout.requiredSizeIn

@Composable
fun AppContent() {
    // By default, Subspace is automatically bounded by the system's recommended content box.
    // SubspaceModifiers like fillMaxSize() will expand to fill this recommended box.
    Subspace {
        SpatialPanel(SubspaceModifier.fillMaxSize()) {
            Text("Panel filling the default recommended content box")
        }
    }

    // To escape the default recommended content box constraints and define a custom
    // bounded or unbounded Subspace, apply the requiredSizeIn modifier.
    Subspace(
        modifier =
            SubspaceModifier.requiredSizeIn(
                maxWidth = 10000.dp,
                maxHeight = 10000.dp,
                maxDepth = 10000.dp,
            )
    ) {
        SpatialPanel(SubspaceModifier.fillMaxSize()) {
            Text("Panel in a custom sized Subspace escaping default constraints")
        }
    }
}
Parameters
modifier: SubspaceModifier = SubspaceModifier

The SubspaceModifier to be applied to the content of this Subspace.

content: @Composable @SubspaceComposable SpatialBoxScope.() -> Unit

The 3D content to render within this Subspace.

@Composable
@ComposableOpenTarget(index = -1)
fun Subspace(
    modifier: SubspaceModifier = SubspaceModifier,
    allowUnboundedSubspace: Boolean,
    content: @Composable @SubspaceComposable SpatialBoxScope.() -> Unit
): Unit

Create a 3D area that the app can render spatial content into.

Parameters
modifier: SubspaceModifier = SubspaceModifier

The SubspaceModifier to be applied to the content of this Subspace.

allowUnboundedSubspace: Boolean

If true, the default recommended content box constraints will not be applied, allowing the Subspace to be infinite. Unbounded Subspaces are considered unsafe because they can lead to poor performance or even a crash as the content expands to the maximum volume constraint size. In addition, content placed too far away may not be visible to the user. Defaults to false, providing a safe, bounded space within the system's recommended content box.

content: @Composable @SubspaceComposable SpatialBoxScope.() -> Unit

The 3D content to render within this Subspace.