Back openDesk Edu for a sovereign, open-source education — every vote counts.
Vote nowSave products you love by clicking the heart icon.
Eine umfassende Einführung in die Virtual Reality, die die Grundlagen der Computergrafik, stereoskopisches Sehen, die Geschichte von VR, Gerätekategorien, Motion Tracking und das Reality-Virtuality-Kontinuum abdeckt.
Optimierung der KI-Inferenz für XR-Geräte — Modellquantisierung, NPU-Beschleunigung, hierarchisches Serving, Bandbreitenoptimierung für Echtzeit-Rendering mit 60 fps.
Zehn Millionen Android-Entwickler kennen Jetpack Compose bereits. Mit Compose for XR lässt sich dieses Wissen direkt in den 3D-Raum übertragen. Keine neue Sprache, keine Scene-Graph-API, die man auswendig lernen muss, kein Unity-Projekt, das aufgesetzt werden muss. Sie schreiben Kotlin, verwenden dieselben deklarativen Muster, und das Framework übernimmt die Tiefe, Perspektive und den Eye-Tracking-Fokus für Sie.
Das SDK befindet sich in der Version 1.0.0-alpha12 (veröffentlicht im März 2026) und entwickelt sich schnell weiter. Die API-Oberfläche stabilisiert sich um einen kleinen Satz von Primitiven, die sauber auf die Ihnen bereits bekannten Compose-Konzepte abgebildet werden.
Alles Räumliche beginnt mit Subspace. Es erstellt eine Partition des 3D-Raums innerhalb Ihres regulären Compose-UI-Baums. Alles darin wird an der vom System empfohlenen Position und Skalierung gerendert. Auf Nicht-XR-Geräten ist der gesamte Block ein No-Op.
if (LocalSpatialCapabilities.current.isSpatialUiEnabled) {
Subspace {
SpatialPanel(
SubspaceModifier
.height(824.dp)
.width(1400.dp)
) {
// Your existing Compose UI renders on a 2D plane in 3D space
MyExistingScreen()
}
}
} else {
MyExistingScreen() // Falls back to 2D on phones/tablets
}
```text
Die `LocalSpatialCapabilities`-Prüfung ist der Verzweigungspunkt. Auf XR-Hardware betreten Sie den Subspace. Überall sonst wird normal gerendert. Das bedeutet, dass Sie eine einzige Codebasis für Telefon, Tablet und Headset beibehalten können, ohne Layouts duplizieren zu müssen.
`SpatialPanel` ist das Arbeitstier. Es rendert eine 2D-Ebene im 3D-Raum. Maximale Größe: 2560dp mal 1800dp. Das System empfiehlt, dass Panels etwa 1,75 Meter von der Sichtlinie des Benutzers entfernt erscheinen, und skaliert Inhalte basierend auf der Entfernung automatisch zwischen 0,75 m und 1,75 m. Wenn Sie ein Panel benötigen, das unabhängig von der Entfernung die gleiche wahrgenommene Größe behält, setzen Sie `shouldScaleWithDistance` auf false.
## Spatial Layouts: Row, Column, CurvedRow
Hier wird es interessant. Compose bietet Ihnen `Row` und `Column`. Compose for XR bietet Ihnen `SpatialRow`, `SpatialColumn` und `SpatialCurvedRow`, welche räumliche Panels im 3D-Raum unter Verwendung desselben mentalen Modells anordnen.
```kotlin
Subspace {
SpatialRow {
SpatialColumn {
SpatialPanel(
SubspaceModifier.height(250.dp).width(400.dp)
) {
NavigationPanel()
}
SpatialPanel(
SubspaceModifier.height(200.dp).width(400.dp)
) {
SecondaryContent()
}
}
SpatialPanel(
SubspaceModifier.height(824.dp).width(1400.dp)
) {
MainContent()
}
}
}
```text
`SpatialCurvedRow` ist das Element, das sich wirklich neu anfühlt. Es ordnet Child-Elemente entlang einer Kurve an und hüllt sie um das Sichtfeld des Benutzers. Der Parameter `curveRadius` steuert die Krümmung: Ein größerer Radius erzeugt einen sanften Bogen, kleinere Werte eine engere Umschließung.
```kotlin
Subspace {
SpatialCurvedRow(
curveRadius = 1025.dp,
verticalAlignment = SpatialAlignment.CenterVertically,
horizontalArrangement = SpatialArrangement.Center,
) {
SpatialPanel(SubspaceModifier.weight(0.3f)) {
Text("Left")
}
SpatialPanel(SubspaceModifier.weight(0.5f)) {
Text("Centre")
}
SpatialPanel(SubspaceModifier.weight(0.3f)) {
Text("Right")
}
}
}
```text
Dies ist besonders nützlich für Media-Dashboards, Überwachungsraster und jedes Szenario, bei dem Inhalte das periphere Sichtfeld des Benutzers auf natürliche Weise ausfüllen sollen.
## 2D vs. Spatial: Ein kurzer Mapping-Überblick
| Compose 2D | Compose XR | Zweck |
| --- | --- | --- |
| `Row` | `SpatialRow` | Horizontale Anordnung |
| `Column` | `SpatialColumn` | Vertikale Anordnung |
| `Box` | `SpatialBox` | Überlappende Elemente |
| `Modifier` | `SubspaceModifier` | Größe, Offset, Tiefe |
| `Dialog` | `SpatialDialog` | Modale Overlays |
| `Popup` | `SpatialPopup` | Schwebende Kontextmenüs |
| (keine) | `SpatialCurvedRow` | Gebogenes horizontales Layout |
| (keine) | `Orbiter` | Befestigungen für schwebende Panels |
| (keine) | `Volume` | 3D-Modell-Subspace |
## Orbiters: Schwebende UI-Anker
Ein `Orbiter` ist ein schwebendes Element, das an einem räumlichen Panel oder Layout verankert ist. Betrachten Sie es als eine Toolbar, die in der Nähe Ihres Inhalts schwebt, ohne selbst Teil des Panels zu sein.
```kotlin
Subspace {
SpatialRow {
Orbiter(
position = ContentEdge.Top,
offset = 8.dp,
offsetType = OrbiterOffsetType.InnerEdge,
alignment = Alignment.CenterHorizontally,
) {
Surface(Modifier.clip(CircleShape)) {
IconButton(onClick = { /* toggle settings */ }) {
Icon(Icons.Default.Settings, contentDescription = "Settings")
}
}
}
SpatialPanel(
SubspaceModifier.height(824.dp).width(1400.dp)
) {
MainContent()
}
```
}
}
```text
The `position` parameter (ContentEdge.Top, Bottom, Start, End) defines which edge of the parent the orbiter anchors to. `offset` controls how far it floats. Orbiters are the right place for FABs, toolbars, and status indicators that need to stay close to a panel but outside its content area.
## 3D Content: Models and Volumes
Alpha 12 introduced `SpatialGltfModel` for rendering glTF assets directly in a subspace. For lower-level control, `SceneCoreEntity` wraps any SceneCore entity (the underlying 3D engine) in a composable.
```kotlin
Subspace(allowUnboundedSubspace = true) {
SpatialGltfModel(
model = "models/robot.glb",
modifier = SubspaceModifier
.width(400.dp)
.height(400.dp),
) { state ->
// Control animations via SpatialGltfModelAnimation
state.animations.firstOrNull()?.let { anim ->
anim.play()
}
}
}
```text
`Volume` is a specialised subspace designed specifically for 3D entities. It provides the spatial bounds and rendering context that 3D models need, separate from the 2D panel hierarchy.
`SpatialExternalSurface` handles video and image content, including flat, 180-degree hemisphere, and full 360-degree sphere projections. This is the API for immersive media players.
```kotlin
Subspace {
SpatialExternalSurface(
stereoMode = StereoMode.SideBySide,
modifier = SubspaceModifier
.width(1200.dp)
.height(676.dp),
) {
// Access the Surface to render video frames
val surface = this.surface
videoPlayer.setSurface(surface)
}
}
```text
For nesting 3D content inside a panel, `PlanarEmbeddedSubspace` creates a subspace within a SpatialPanel, letting you embed a 3D viewport inside a 2D layout, much like a WebView inside an Android activity.
## Spatial UI Components
`SpatialDialog`, `SpatialPopup`, and `SpatialElevation` are the spatial equivalents of their 2D counterparts. They render in 3D space with proper depth sorting and eye-tracking focus.
```kotlin
var showDialog by remember { mutableStateOf(false) }
if (showDialog) {
SpatialDialog(
onDismissRequest = { showDialog = false },
properties = SpatialDialogProperties(
dismissOnBackPress = true,
dismissOnClickOutside = true,
),
) {
Surface(shape = MaterialTheme.shapes.large) {
Column(Modifier.padding(24.dp)) {
Text("Confirm action?", style = MaterialTheme.typography.headlineSmall)
Spacer(Modifier.height(16.dp))
Row(horizontalArrangement = Arrangement.End) {
TextButton(onClick = { showDialog = false }) { Text("Cancel") }
Button(onClick = { /* confirm */ showDialog = false }) { Text("Confirm") }
}
}
}
}
}
```text
Eye-tracking focus is automatic. When a user looks at a spatial element, it receives focus as if they had tapped it. Your existing focus handlers work without changes.
## Getting Started
You need Android Studio Preview Narwhal (or later) with the XR emulator plugin. The emulator simulates the headset's field of view and head tracking on your development machine.
**1. Add the dependency** to your module's `build.gradle.kts`:
```kotlin
dependencies {
implementation("androidx.xr.compose:compose:1.0.0-alpha12")
implementation("androidx.xr.scenecore:scenecore:1.0.0-alpha12")
testImplementation("androidx.xr.compose:compose-testing:1.0.0-alpha12")
}
```text
**2. Check spatial capabilities** before entering subspace code:
```kotlin
val isSpatial = LocalSpatialCapabilities.current.isSpatialUiEnabled
```text
**3. Create your first spatial layout** by wrapping existing UI in `Subspace` and `SpatialPanel`:
```kotlin
setContent {
MaterialTheme {
if (LocalSpatialCapabilities.current.isSpatialUiEnabled) {
Subspace {
SpatialPanel(
SubspaceModifier
.height(824.dp)
.width(1400.dp),
) {
MyExistingApp()
}
}
} else {
MyExistingApp()
}
}
}
**4. Testen Sie auf dem Emulator** und wechseln Sie anschließend zu einem Samsung Galaxy XR-Headset für die Interaktion in der realen Welt.
Die offizielle Dokumentation finden Sie unter [developer.android.com/develop/xr](https://developer.android.com/develop/xr). Das Android XR Codelab („Learn Android XR Fundamentals: Part 1“) führt in etwa 30 Minuten durch die Modi und räumlichen Panels. Das [android/snippets](https://github.com/android/snippets)-Repository von Google auf GitHub enthält funktionierenden Code für jede hier besprochene API.
## Was Sie als Nächstes bauen sollten
Beginnen Sie mit etwas, das Sie bereits haben. Nehmen Sie eine bestehende Compose-App, betten Sie deren Hauptbildschirm in `Subspace` + `SpatialPanel` ein und sehen Sie, wie diese in 3D schwebt. Fügen Sie dann ein `SpatialCurvedRow` mit ergänzenden Panels hinzu. Versuchen Sie anschließend ein `Orbiter` für schwebende Steuerelemente. Das SDK ist so konzipiert, dass jedes räumliche Feature ein inkrementeller Schritt ist und kein kompletter Rewrite.
Für ambitioniertere Projekte eröffnet die Kombination aus Volume + SpatialGltfModel Möglichkeiten für Produktvisualisierungen, Architektur-Walkthroughs und dreidimensionale Datenvisualisierungen. Die API befindet sich noch in der Alpha-Phase und weist einige Ecken und Kanten auf, aber das mentale Modell ist solide: Compose, nur im Raum.