Mit Jetpack Compose for XR können Sie Ihre räumliche Benutzeroberfläche und Ihr Layout deklarativ mithilfe vertrauter Compose-Konzepte wie Zeilen und Spalten erstellen. Auf diese Weise können Sie Ihre vorhandene Android-Benutzeroberfläche auf den 3D-Raum erweitern oder komplett neue immersive 3D-Anwendungen erstellen.
Wenn Sie eine vorhandene Android Views-basierte App verräumen, haben Sie mehrere Entwicklungsoptionen. Sie können Interoperabilitäts-APIs verwenden, „Compose“ und „Views“ zusammen verwenden oder direkt mit der SceneCore-Bibliothek arbeiten. Weitere Informationen finden Sie in unserem Leitfaden zum Arbeiten mit Ansichten.
Über untergeordnete Räume und räumliche Komponenten
Wenn Sie Ihre App für Android XR schreiben, ist es wichtig, die Konzepte von untergeordneten Räumen und räumlichen Komponenten zu kennen.
Untergeordneter Gruppenbereich
Bei der Entwicklung für Android XR müssen Sie Ihrer App oder Ihrem Layout einen untergeordneten Raum hinzufügen. Ein untergeordneter Raum ist eine Partition eines 3D-Bereichs in Ihrer App, in dem Sie 3D-Inhalte platzieren, 3D-Layouts erstellen und ansonsten 2D-Inhalten Tiefe verleihen können. Ein untergeordneter Raum wird nur gerendert, wenn die Verräumlichung aktiviert ist. Im Home Space oder auf Nicht-XR-Geräten wird jeglicher Code innerhalb dieses untergeordneten Raums ignoriert.
Es gibt zwei Möglichkeiten, einen untergeordneten Space zu erstellen:
setSubspaceContent()
: Mit dieser Funktion wird ein untergeordneter Gruppenbereich auf App-Ebene erstellt. Dies kann in Ihrer Hauptaktivität auf die gleiche Weise wiesetContent()
aufgerufen werden. Höhe, Breite und Tiefe eines untergeordneten Raums auf App-Ebene sind unbegrenzt und bieten im Grunde eine unendliche Leinwand für raumbezogene Inhalte.Subspace
: Diese zusammensetzbare Funktion kann an beliebiger Stelle in der UI-Hierarchie Ihrer App platziert werden. So können Sie Layouts für 2D- und räumliche UI verwalten, ohne den Kontext zwischen den Dateien zu verlieren. Dies erleichtert die gemeinsame Nutzung der vorhandenen Anwendungsarchitektur zwischen XR und anderen Formfaktoren, ohne dass der Zustand über den gesamten UI-Baum gezogen oder die App neu gestaltet werden muss.
Weitere Informationen finden Sie unter Untergeordneten Gruppenbereich zur App hinzufügen.
Raumbezogene Komponenten
Zusammensetzbare Komponenten in Unterbereichen: Diese Komponenten können nur in einem untergeordneten Bereich gerendert werden.
Sie müssen in Subspace
oder setSubspaceContent
eingeschlossen werden, bevor sie in ein 2D-Layout platziert werden können. Mit einem SubspaceModifier
können Sie den zusammensetzbaren Funktionen des untergeordneten Bereichs Attribute wie Tiefe, Offset und Position hinzufügen.
Andere räumliche Komponenten müssen innerhalb eines untergeordneten Raums nicht aufgerufen werden. Sie bestehen aus herkömmlichen 2D-Elementen, die in einen räumlichen Container eingebettet sind. Diese Elemente können in 2D- oder 3D-Layouts verwendet werden, wenn sie für beide definiert sind. Wenn die Raumisierung nicht aktiviert ist, werden ihre räumlichen Funktionen ignoriert und auf ihre 2D-Entsprechungen zurückgesetzt.
Räumliches Steuerfeld erstellen
Ein SpatialPanel
ist eine zusammensetzbare Funktion für einen untergeordneten Bereich, mit dem Sie App-Inhalte anzeigen können, z. B. die Videowiedergabe, Standbilder oder andere Inhalte in einem räumlichen Steuerfeld.
Mit SubspaceModifier
können Sie die Größe, das Verhalten und die Position des räumlichen Steuerfelds ändern, wie im folgenden Beispiel gezeigt.
Subspace { SpatialPanel( SubspaceModifier .height(824.dp) .width(1400.dp) .movable() .resizable() ) { SpatialPanelContent() } }
@Composable fun SpatialPanelContent() { Box( Modifier .background(color = Color.Black) .height(500.dp) .width(500.dp), contentAlignment = Alignment.Center ) { Text( text = "Spatial Panel", color = Color.White, fontSize = 25.sp ) } }
Wichtige Punkte zum Code
- Da es sich bei
SpatialPanel
APIs um zusammensetzbare Komponenten für untergeordnete Bereiche handelt, müssen sie innerhalb vonSubspace
odersetSubspaceContent
aufgerufen werden. Wird sie außerhalb eines untergeordneten Bereichs aufgerufen, wird eine Ausnahme ausgelöst. - Erlauben Sie dem Nutzer, die Größe des Bereichs zu ändern oder das Feld zu verschieben, indem Sie die Modifikatoren
movable
oderresizable
hinzufügen. - Weitere Informationen zur Größe und Positionierung finden Sie in unserer Anleitung für die Gestaltung von raumbezogenen Bereichen. Ausführliche Informationen zur Codeimplementierung finden Sie in unserer Referenzdokumentation.
Orbiter erstellen
Ein Orbiter ist eine räumliche UI-Komponente. Es ist für die Verbindung mit einem entsprechenden räumlichen Feld, Layout oder einer anderen Entität vorgesehen. Ein Orbiter enthält in der Regel Navigations- und kontextbezogene Aktionselemente, die mit der Entität zusammenhängen, auf der er verankert ist. Wenn Sie beispielsweise einen räumlichen Bereich zur Anzeige von Videoinhalten erstellt haben, können Sie Steuerelemente für die Videowiedergabe innerhalb eines Orbiters hinzufügen.
Wie im folgenden Beispiel gezeigt, kannst du einen Orbiter innerhalb des 2D-Layouts in einem SpatialPanel
aufrufen, um Nutzersteuerelemente wie die Navigation zu umschließen. Dadurch werden sie entsprechend Ihrer Konfiguration aus Ihrem 2D-Layout extrahiert und an das räumliche Steuerfeld angehängt.
Subspace { SpatialPanel( SubspaceModifier .height(824.dp) .width(1400.dp) .movable() .resizable() ) { SpatialPanelContent() OrbiterExample() } }
@Composable fun OrbiterExample() { Orbiter( position = OrbiterEdge.Bottom, offset = 96.dp, alignment = Alignment.CenterHorizontally ) { Surface(Modifier.clip(CircleShape)) { Row( Modifier .background(color = Color.Black) .height(100.dp) .width(600.dp), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { Text( text = "Orbiter", color = Color.White, fontSize = 50.sp ) } } } }
Wichtige Punkte zum Code
- Da Orbiter räumliche UI-Komponenten sind, kann der Code in 2D- oder 3D-Layouts wiederverwendet werden. Bei einem 2D-Layout rendert Ihre App nur den Inhalt innerhalb des Orbiters und ignoriert den Orbiter selbst.
- Weitere Informationen zur Verwendung und Entwicklung von Orbitern findest du in unserem Designleitfaden.
Einem räumlichen Layout mehrere räumliche Steuerfelder hinzufügen
Mit SpatialRow
, SpatialColumn
, SpatialBox
und SpatialLayoutSpacer
kannst du mehrere räumliche Steuerfelder erstellen und in einem räumlichen Layout platzieren.
Das folgende Codebeispiel zeigt, wie dies funktioniert.
Subspace { SpatialRow { SpatialColumn { SpatialPanel(SubspaceModifier.height(250.dp).width(400.dp)) { SpatialPanelContent("Top Left") } SpatialPanel(SubspaceModifier.height(200.dp).width(400.dp)) { SpatialPanelContent("Middle Left") } SpatialPanel(SubspaceModifier.height(250.dp).width(400.dp)) { SpatialPanelContent("Bottom Left") } } SpatialColumn { SpatialPanel(SubspaceModifier.height(250.dp).width(400.dp)) { SpatialPanelContent("Top Right") } SpatialPanel(SubspaceModifier.height(200.dp).width(400.dp)) { SpatialPanelContent("Middle Right") } SpatialPanel(SubspaceModifier.height(250.dp).width(400.dp)) { SpatialPanelContent("Bottom Right") } } } }
@Composable fun SpatialPanelContent(text: String) { Column( Modifier .background(color = Color.Black) .fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Text( text = "Panel", color = Color.White, fontSize = 15.sp ) Text( text = text, color = Color.White, fontSize = 25.sp, fontWeight = FontWeight.Bold ) } }
Wichtige Punkte zum Code
SpatialRow
,SpatialColumn
,SpatialBox
undSpatialLayoutSpacer
sind zusammensetzbare Funktionen für untergeordnete Bereiche und müssen in einem untergeordneten Bereich platziert werden.- Mit
SubspaceModifier
können Sie Ihr Layout anpassen. - Bei Layouts mit mehreren aufeinanderfolgenden Steuerfeldern empfehlen wir, einen Kurvenradius von 825 dp mithilfe eines
SubspaceModifier
festzulegen, damit die Steuerfelder den Nutzer umgeben. Weitere Informationen finden Sie in unserem Leitfaden für die Designentwicklung.
Mit einem Volumen ein 3D-Objekt in Ihrem Layout platzieren
Um ein 3D-Objekt in Ihrem Layout zu platzieren, benötigen Sie eine zusammensetzbare Funktion für untergeordnete Bereiche, sogenannte Volumes. Hier ist ein Beispiel dafür.
Subspace { SpatialPanel( SubspaceModifier.height(1500.dp).width(1500.dp) .resizable().movable() ) { ObjectInAVolume(true) Box( Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { Text( text = "Welcome", fontSize = 50.sp, ) } } }
@Composable fun ObjectInAVolume(show3DObject: Boolean) {
Wichtige Punkte zum Code
- Weitere Informationen zum Laden von 3D-Inhalten in einem Volume finden Sie unter 3D-Modelle zu Ihrer App hinzufügen.
Weitere Komponenten für die räumliche Benutzeroberfläche hinzufügen
Räumliche UI-Komponenten können an einer beliebigen Stelle in der UI-Hierarchie Ihrer Anwendung platziert werden. Diese Elemente können in der 2D-UI wiederverwendet werden und ihre räumlichen Attribute sind nur sichtbar, wenn die räumlichen Funktionen aktiviert sind. Auf diese Weise können Sie Menüs, Dialogfeldern und anderen Komponenten Höhen hinzufügen, ohne den Code zweimal schreiben zu müssen. Die folgenden Beispiele für räumliche UI zeigen, wie diese Elemente verwendet werden.
UI-Komponente |
Wenn die Verräumlichung aktiviert ist |
In 2D-Umgebung |
---|---|---|
|
Das Steuerfeld wird in Z-Tiefe leicht nach hinten geschoben, um ein erweitertes Dialogfeld anzuzeigen |
2D-Modus |
|
Das Steuerfeld schiebt sich in Z-Tiefe leicht nach hinten, um ein erhöhtes Pop-up anzuzeigen. |
Es wird ein 2D- |
|
|
Shows ohne räumliche Elevation. |
SpatialDialog
Dies ist ein Beispiel für ein Dialogfeld, das nach einer kurzen Verzögerung geöffnet wird. Wenn SpatialDialog
verwendet wird, wird das Dialogfeld mit derselben Z-Tiefe wie das räumliche Steuerfeld angezeigt und das Feld wird bei aktivierter Verräumlichung um 125 dp verschoben. SpatialDialog
kann auch verwendet werden, wenn die Raumisierung nicht aktiviert ist. In diesem Fall greift SpatialDialog
auf sein 2D-Gegenstück Dialog
zurück.
@Composable fun DelayedDialog() { var showDialog by remember { mutableStateOf(false) } LaunchedEffect(Unit) { delay(3000) showDialog = true } if (showDialog) { SpatialDialog( onDismissRequest = { showDialog = false }, SpatialDialogProperties( dismissOnBackPress = true ) ) { Box( Modifier .height(150.dp) .width(150.dp) ) { Button(onClick = { showDialog = false }) { Text("OK") } } } } }
Wichtige Punkte zum Code
- Dies ist ein Beispiel für
SpatialDialog
. Die Verwendung vonSpatialPopup
undSpatialElevation
ist sehr ähnlich. Weitere Informationen finden Sie in unserer API-Referenz.
Benutzerdefinierte Steuerfelder und Layouts erstellen
Wenn Sie benutzerdefinierte Bereiche erstellen möchten, die von Compose for XR nicht unterstützt werden, können Sie direkt mit PanelEntities
und dem Szenendiagramm mithilfe der SceneCore
APIs arbeiten.
Orbiter an räumlichen Layouts und anderen Elementen verankern
Sie können einen Orbiter an jeder in „Compose“ deklarierten Entität verankern. Dazu muss ein Orbiter in einem räumlichen Layout von UI-Elementen wie SpatialRow
, SpatialColumn
oder SpatialBox
deklariert werden. Der Orbiter verankert sich bei der übergeordneten Entität, die der von Ihnen deklarierten Stelle am nächsten ist.
Das Verhalten des Orbiters hängt davon ab, wo du es deklarierst:
- In einem 2D-Layout, das in ein
SpatialPanel
eingebunden ist (wie in einem vorherigen Code-Snippet gezeigt), verankert sich der Orbiter an diesemSpatialPanel
. - In einem
Subspace
verankert sich der Orbiter bei der nächstgelegenen übergeordneten Entität, d. h. dem räumlichen Layout, in dem der Orbiter deklariert ist.
Das folgende Beispiel zeigt, wie ein Orbiter an einer räumlichen Zeile verankert wird:
Subspace { SpatialRow { Orbiter( position = OrbiterEdge.Top, offset = EdgeOffset.inner(8.dp), shape = SpatialRoundedCornerShape(size = CornerSize(50)) ) { Text( "Hello World!", style = MaterialTheme.typography.h2, modifier = Modifier .background(Color.White) .padding(16.dp) ) } SpatialPanel( SubspaceModifier .height(824.dp) .width(1400.dp) ) { Box( modifier = Modifier .background(Color.Red) ) } SpatialPanel( SubspaceModifier .height(824.dp) .width(1400.dp) ) { Box( modifier = Modifier .background(Color.Blue) ) } } }
Wichtige Punkte zum Code
- Wenn Sie einen Orbiter außerhalb eines 2D-Layouts deklarieren, verankert er sich an der nächstgelegenen übergeordneten Entität. In diesem Fall verankert sich der Orbiter am oberen Rand des
SpatialRow
, in dem er deklariert ist. - Räumlichen Layouts wie
SpatialRow
,SpatialColumn
undSpatialBox
sind inhaltslose Entitäten zugeordnet. Daher verankert ein in einem räumlich Layout deklarierter Orbiter bei diesem Layout.
Siehe auch
- 3D-Modelle zu Ihrer App hinzufügen
- Benutzeroberfläche für auf Android-Ansichten basierende Apps entwickeln
- Material Design for XR implementieren