Back openDesk Edu for a sovereign, open-source education â every vote counts.
Vote nowSave products you love by clicking the heart icon.
Optimizing AI inference for XR devices â model quantization, NPU acceleration, hierarchical serving, bandwidth optimization for real-time 60fps rendering.
Google and Samsung just shipped the biggest Android XR update since launch. Auto-spatialization turns any 2D app into 3D, Android Enterprise enables fleet deployments, and the SDK now supports five engines.
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.