Dzięki Jetpack Compose for XR możesz deklaratywnie tworzyć interfejs i układ przestrzenny, korzystając z dobrze znanych koncepcji Compose, takich jak wiersze i kolumny. Dzięki temu możesz rozszerzyć istniejące interfejsy Androida na przestrzeń 3D lub tworzyć zupełnie nowe, wciągające aplikacje 3D.
Jeśli chcesz dodać obsługę dźwięku przestrzennego w istniejącej aplikacji opartej na Android Views, masz do wyboru kilka opcji. Możesz używać interfejsów API interoperacyjności, używać komponentu Compose i widżetów razem lub pracować bezpośrednio z biblioteką SceneCore. Więcej informacji znajdziesz w przewodniku po widokach.
Informacje o podprzestrzeniach i komponentach przestrzennych
Podczas pisania aplikacji na Androida XR ważne jest zrozumienie koncepcji podprzestrzeni i przestrzennych komponentów.
Subspace
Podczas tworzenia aplikacji na Androida XR musisz dodać do niej podprzestrzeń lub układ. Subprzestrzeń to część przestrzeni 3D w aplikacji, w której możesz umieszczać treści 3D, tworzyć układy 3D i dodawać głębię do treści 2D. Subprzestrzeń jest renderowana tylko wtedy, gdy włączona jest przestrzenność. W domu lub na urządzeniach bez funkcji XR każdy kod w tym podprzestrzeni jest ignorowany.
Subprzestrzeń możesz utworzyć na 2 sposoby:
setSubspaceContent
: ta funkcja tworzy podprzestrzeń na poziomie aplikacji. Można go wywołać w MainActivity w taki sam sposób jaksetContent
. Subprzestrzeń na poziomie aplikacji jest nieograniczona pod względem wysokości, szerokości i głębi, co zapewnia nieograniczone pole do popisu dla treści przestrzennych.Subspace
: ten komponent można umieścić w dowolnym miejscu w hierarchii interfejsu aplikacji, co umożliwia zachowanie układów interfejsu 2D i przestrzennego bez utraty kontekstu między plikami. Dzięki temu łatwiej jest udostępniać takie elementy jak istniejąca architektura aplikacji między XR a innymi formatami bez konieczności przenoszenia stanu przez całe drzewo interfejsu użytkownika ani przekształcania aplikacji.
Więcej informacji znajdziesz w artykule o dodawaniu podpokoju do aplikacji.
Komponenty zlokalizowane
Komponenty w podprzestrzeni: te komponenty można renderować tylko w podprzestrzeni.
Przed umieszczeniem w układzie 2D muszą być one umieszczone w elementach Subspace
lub setSubspaceContent
. SubspaceModifier
pozwala dodawać atrybuty, takie jak głębia, przesunięcie i pozycjonowanie, do komponentów w przestrzeni podrzędnej.
- Uwaga na modyfikatory podprzestrzeni: zwróć uwagę na kolejność interfejsów API
SubspaceModifier
.- Przesunięcie musi wystąpić jako pierwsze w łańcuchu modyfikatorów.
- Możliwość przenoszenia i zmiany rozmiaru musi być wymieniona na końcu.
- Obrót musi zostać zastosowany przed skalowaniem.
Inne komponenty przestrzenne nie wymagają wywołania w podprzestrzeni. Składają się one z tradycyjnych elementów 2D umieszczonych w kontenerze przestrzennym. Te elementy mogą być używane w układach 2D lub 3D, jeśli są zdefiniowane dla obu. Jeśli funkcja dźwięku przestrzennego jest wyłączona, funkcje dźwięku przestrzennego zostaną zignorowane, a dźwięk będzie odtwarzany w trybie 2D.
Tworzenie panelu dźwięku przestrzennego
SpatialPanel
to komponent podprzestrzeni, który umożliwia wyświetlanie treści aplikacji. Możesz na przykład wyświetlić film, obrazy lub inne treści na panelu przestrzennym.
Za pomocą SubspaceModifier
możesz zmienić rozmiar, zachowanie i umiejscowienie panelu przestrzennego, jak pokazano w tym przykładzie.
Subspace {
SpatialPanel(
SubspaceModifier
.height(824.dp)
.width(1400.dp)
.movable()
.resizable()
) {
SpatialPanelContent()
}
}
// 2D content placed within the spatial panel
@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
)
}
}
Najważniejsze informacje o kodzie
- Uwaga dotycząca modyfikatorów podprzestrzeni: zwróć uwagę na kolejność interfejsów API
SubspaceModifier
.- Odsunięcie musi wystąpić jako pierwsze w łańcuchu modyfikatorów.
- Modyfikatory ruchomości i rozmiaru muszą występować na końcu.
- Obrót musi zostać zastosowany przed skalowaniem.
- Ponieważ interfejsy API
SpatialPanel
są składanymi interfejsami API w subprzestrzeni, musisz je wywoływać w ramachSubspace
lubsetSubspaceContent
. Wywołanie ich poza subprzestrzenią spowoduje wyjątek. - Zezwól użytkownikowi na zmianę rozmiaru lub przeniesienie panelu przez dodanie
.movable
lub.resizable
SubspaceModifier
. - Szczegółowe informacje o rozmiarach i umieszczaniu znajdziesz w wskazówkach dotyczących projektowania paneli przestrzennych. Więcej informacji o implementacji kodu znajdziesz w dokumentacji.
Tworzenie orbitera
Orbiter to komponent UI przestrzennego. Jest ona przeznaczona do dołączania do odpowiedniego panelu przestrzennego i zawiera elementy nawigacji oraz działania kontekstowe powiązane z tym panelem. Jeśli na przykład utworzysz panel przestrzenny do wyświetlania treści wideo, możesz dodać elementy sterujące odtwarzaniem filmu w orbicie.
Jak pokazano w następnym przykładzie, wywołaj orbiter w komponencie SpatialPanel
, aby owinąć elementy sterowania użytkownika, takie jak nawigacja. W ten sposób wyodrębniasz je z układu 2D i dołączasz do panelu przestrzennego zgodnie z konfiguracją.
setContent {
Subspace {
SpatialPanel(
SubspaceModifier
.height(824.dp)
.width(1400.dp)
.movable()
.resizable()
) {
SpatialPanelContent()
OrbiterExample()
}
}
}
//2D content inside Orbiter
@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
)
}
}
}
}
Najważniejsze informacje o kodzie
- Uwaga na temat modyfikatorów przestrzeni podrzędnej: zwróć uwagę na kolejność interfejsów API
SubspaceModifier
.- Przesunięcie musi wystąpić jako pierwsze w łańcuchu modyfikatorów.
- Możliwość przenoszenia i zmiany rozmiaru musi być wymieniona na końcu.
- Obrót musi zostać zastosowany przed skalowaniem.
- Orbitery to komponenty UI przestrzennego, więc kod można ponownie wykorzystać w układzie 2D lub 3D. W układzie 2D aplikacja renderuje tylko zawartość wewnątrz orbitera i ignoruje sam orbiter.
- Więcej informacji o używaniu i projektowaniu orbiterów znajdziesz w wskazówkach dotyczących projektowania.
Dodawanie wielu paneli przestrzennych do układu przestrzennego
Możesz utworzyć wiele paneli przestrzennych i umieścić je w ramach układu przestrzennego za pomocą elementów SpatialRow
, SpatialColumn
, SpatialBox
i SpatialLayoutSpacer
.
Jak to zrobić, pokazuje przykładowy kod poniżej.
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
)
}
}
Najważniejsze informacje o kodzie
SpatialRow
,SpatialColumn
,SpatialBox
iSpatialLayoutSpacer
to wszystkie komponenty w podprzestrzeni i muszą być umieszczone w podprzestrzeni.- Aby dostosować układ, użyj
SubspaceModifier
. - W przypadku układów z większą liczbą paneli w wierszu zalecamy ustawienie krzywizny o promieniu 825 dp za pomocą funkcji
SubspaceModifier
, aby panele otaczały użytkownika. Więcej informacji znajdziesz w wskazówkach dotyczących projektowania.
Umieszczanie obiektu 3D w układzie za pomocą wolumenu
Aby umieścić obiekt 3D na stronie, musisz użyć komponentu podprzestrzeni zwanego objętością. Oto przykład, jak to zrobić.
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) {
val xrCoreSession = checkNotNull(LocalSession.current)
val scope = rememberCoroutineScope()
if (show3DObject) {
Subspace {
Volume(
modifier = SubspaceModifier
.offset(volumeXOffset, volumeYOffset, volumeZOffset) //
Relative position
.scale(1.2f) // Scale to 120% of the size
) { parent ->
scope.launch {
// Load your 3D Object here
}
}
}
}
}
Najważniejsze informacje o kodzie
- Uwaga na temat modyfikatorów podprzestrzeni: zwróć uwagę na kolejność interfejsów API
SubspaceModifier
.- Przesunięcie musi wystąpić jako pierwsze w łańcuchu modyfikatorów.
- Możliwość przenoszenia i zmiany rozmiaru musi być wymieniona na końcu.
- Obrót musi zostać zastosowany przed skalowaniem.
- Aby dowiedzieć się więcej o wczytywaniu treści 3D w tomach, przeczytaj artykuł Dodawanie treści 3D.
Dodawanie innych komponentów UI w przestrzeni
Komponenty UI przestrzennego można umieścić w dowolnym miejscu w hierarchii UI aplikacji. Elementy te można ponownie wykorzystać w interfejsie 2D, a ich atrybuty przestrzenne będą widoczne tylko wtedy, gdy włączone są funkcje przestrzenne. Dzięki temu możesz dodawać menu, dialogi i inne komponenty bez konieczności dwukrotnego pisania kodu. Aby lepiej zrozumieć, jak używać tych elementów, zapoznaj się z podanymi niżej przykładami interfejsu przestrzennego.
Komponent interfejsu użytkownika |
Gdy włączona jest lokalizacja przestrzenna |
W środowisku 2D |
---|---|---|
|
Panel przesunie się nieco w głębi, aby wyświetlić okno dialogowe na pierwszym planie |
Przełącza się na widok 2D |
|
Panel przesunie się nieco w głębi, aby wyświetlić wyskakujące okienko |
Przełącza się na widok 2D |
|
|
programy bez dźwięku przestrzennego; |
SpatialDialog
Oto przykład okna, które otwiera się po krótkim opóźnieniu. Gdy używasz SpatialDialog
, okno pojawia się na tej samej głębi, co panel przestrzenny, a panel jest przesuwany do tyłu o 125 dp, gdy włączona jest lokalizacja przestrzenna.
SpatialDialog
można nadal używać, gdy przestrzenność nie jest włączona. W takim przypadku SpatialDialog
przełączy się na odpowiednik 2D: Dialog
.
@Composable
fun DelayedDialog() {
var showDialog by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
Handler(Looper.getMainLooper()).postDelayed({
showDialog = true
}, 3000)
}
if (showDialog) {
SpatialDialog (
onDismissRequest = { showDialog = false },
SpatialDialogProperties(
dismissOnBackPress = true)
){
Box(Modifier
.height(150.dp)
.width(150.dp)
) {
Button(onClick = { showDialog = false }) {
Text("OK")
}
}
}
}
}
Najważniejsze informacje o kodzie
- Oto przykład
SpatialDialog
. UżycieSpatialPopUp
iSpatialElevation
będzie bardzo podobne. Więcej informacji znajdziesz w dokumentacji interfejsu API.
Tworzenie paneli i układów niestandardowych
Aby tworzyć panele niestandardowe, których nie obsługuje Compose for XR, możesz pracować bezpośrednio z PanelEntities
i grafami sceny za pomocą interfejsów API SceneCore
.