Con Jetpack Compose para XR, puedes compilar de forma declarativa tu IU y diseño espacial con conceptos conocidos de Compose, como filas y columnas. Esto te permite extender tu IU de Android existente al espacio 3D o compilar aplicaciones 3D envolventes completamente nuevas.
Si espacializas una app existente basada en objetos View de Android, tienes varias opciones de desarrollo. Puedes usar APIs de interoperabilidad, usar Compose y Views juntos, o trabajar directamente con la biblioteca de SceneCore. Consulta nuestra guía para trabajar con vistas para obtener más detalles.
Información acerca de los subespacios y los componentes espacializados
Cuando escribes tu app para Android XR, es importante comprender los conceptos de subespacio y componentes espacializados.
Información acerca del subespacio
Cuando desarrolles para Android XR, deberás agregar un subespacio a tu app o diseño. Un subespacio es una partición del espacio 3D dentro de tu app en la que puedes colocar contenido 3D, compilar diseños 3D y agregar profundidad a contenido que, de otro modo, sería 2D. Un subespacio solo se renderiza cuando la espacialización está habilitada. En Home Space o en dispositivos que no son XR, se ignora cualquier código dentro de ese subespacio.
Existen dos formas de crear un subespacio:
setSubspaceContent
: Esta función crea un subespacio a nivel de la app. Se puede llamar a esta función en MainActivity de la misma manera que usassetContent
. Un subespacio a nivel de la app no tiene límites de altura, ancho ni profundidad, lo que proporciona un lienzo infinito para el contenido espacial.Subspace
: Este elemento componible se puede colocar en cualquier lugar dentro de la jerarquía de la IU de tu app, lo que te permite mantener diseños para la IU 2D y espacial sin perder el contexto entre los archivos. Esto facilita compartir elementos como la arquitectura de la app existente entre XR y otros factores de forma sin necesidad de elevar el estado a través de todo el árbol de la IU ni volver a diseñar la arquitectura de tu app.
Para obtener más información, consulta Cómo agregar un subespacio a tu app.
Información acerca de los componentes espacializados
Elementos componibles de subespacio: Estos componentes solo se pueden renderizar en un subespacio.
Deben encerrarse en Subspace
o setSubspaceContent
antes de colocarse en un diseño 2D. Un SubspaceModifier
te permite agregar atributos como profundidad, desplazamiento y posicionamiento a tus elementos componibles de subespacio.
- Nota sobre los modificadores de subespacio: Presta especial atención al orden de las APIs de
SubspaceModifier
.- El desplazamiento debe ocurrir primero en una cadena de modificadores
- Mover y cambiar el tamaño deben ocurrir al final
- La rotación se debe aplicar antes de la escala
Otros componentes espacializados no requieren que se los llame dentro de un subespacio. Consisten en elementos 2D convencionales unidos en un contenedor espacial. Estos elementos se pueden usar en diseños 2D o 3D si se definen para ambos. Cuando la espacialización no esté habilitada, se ignorarán sus componentes espacializados y se usarán sus contrapartes en 2D.
Crea un panel espacial
Un SpatialPanel
es un subespacio componible que te permite mostrar contenido de la app. Por ejemplo, puedes mostrar la reproducción de video, imágenes fijas o cualquier otro contenido en un panel espacial.
Puedes usar SubspaceModifier
para cambiar el tamaño, el comportamiento y la posición del panel espacial, como se muestra en el siguiente ejemplo.
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
)
}
}
Puntos clave sobre el código
- Nota sobre los modificadores de subespacio: Presta especial atención al orden de las APIs de
SubspaceModifier
.- El desplazamiento debe ocurrir primero en una cadena de modificadores.
- Los modificadores móviles y de tamaño variable deben aparecer al final.
- La rotación se debe aplicar antes de la escala.
- Debido a que las APIs de
SpatialPanel
son componibles de subespacio, debes llamarlas dentro deSubspace
osetSubspaceContent
. Si los llamas fuera de un subespacio, se arrojará una excepción. - Agrega
SubspaceModifier
.movable
o.resizable
para permitir que el usuario cambie el tamaño del panel o lo mueva. - Consulta nuestra guía de diseño de paneles espaciales para obtener detalles sobre el tamaño y el posicionamiento. Consulta nuestra documentación de referencia para obtener más detalles sobre la implementación de códigos.
Crea un satélite en órbita
Un orbitador es un componente de IU espacial. Está diseñado para adjuntarse a un panel espacial correspondiente y contiene elementos de acción contextual y de navegación relacionados con ese panel espacial. Por ejemplo, si creaste un panel espacial para mostrar contenido de video, puedes agregar controles de reproducción de video dentro de un orbitador.
Como se muestra en el siguiente ejemplo, llama a un orbitador dentro de un SpatialPanel
para unir los controles del usuario, como la navegación. De esta manera, se extraen de tu diseño 2D y se adjuntan al panel espacial según tu configuración.
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
)
}
}
}
}
Puntos clave sobre el código
- Nota sobre los modificadores de subespacio: Presta especial atención al orden de las APIs de
SubspaceModifier
.- El desplazamiento debe ocurrir primero en una cadena de modificadores
- Mover y cambiar el tamaño deben ocurrir al final
- La rotación se debe aplicar antes de la escala
- Debido a que los orbitadores son componentes espaciales de la IU, el código se puede reutilizar en diseños 2D o 3D. En un diseño 2D, tu app renderiza solo el contenido dentro del orbitador y omite el orbitador en sí.
- Consulta nuestra guía de diseño para obtener más información sobre cómo usar y diseñar orbitadores.
Cómo agregar varios paneles espaciales a un diseño espacial
Puedes crear varios paneles espaciales y colocarlos dentro de un SpatialLayout
con SpatialRow
, SpatialColumn
, SpatialBox
y SpatialLayoutSpacer
.
En el siguiente ejemplo de código, se muestra cómo hacerlo.
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
)
}
}
Puntos clave sobre el código
SpatialRow
,SpatialColumn
,SpatialBox
ySpatialLayoutSpacer
son elementos componibles de subespacio y deben colocarse dentro de un subespacio.- Usa
SubspaceModifier
para personalizar el diseño. - Para diseños con varios paneles en una fila, te recomendamos que configures un radio de curva de 825 dp con un
SubspaceModifier
para que los paneles rodeen al usuario. Consulta nuestra guía de diseño para obtener más detalles.
Usa un volumen para colocar un objeto 3D en tu diseño
Para colocar un objeto 3D en tu diseño, deberás usar un elemento componible de subespacio llamado volumen. Este es un ejemplo de cómo hacerlo.
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
}
}
}
}
}
Puntos clave sobre el código
- Nota sobre los modificadores de subespacio: Presta especial atención al orden de las APIs de
SubspaceModifier
.- El desplazamiento debe ocurrir primero en una cadena de modificadores
- Mover y cambiar el tamaño deben ocurrir al final
- La rotación se debe aplicar antes de la escala
- Consulta Cómo agregar contenido 3D para comprender mejor cómo cargar contenido 3D dentro de un volumen.
Cómo agregar otros componentes espaciales de la IU
Los componentes de la IU espacial se pueden colocar en cualquier lugar de la jerarquía de la IU de tu aplicación. Estos elementos se pueden volver a usar en tu IU 2D, y sus atributos espaciales solo serán visibles cuando se habiliten las capacidades espaciales. Esto te permite agregar elevación a menús, diálogos y otros componentes sin necesidad de escribir el código dos veces. Consulta los siguientes ejemplos de IU espacial para comprender mejor cómo usar estos elementos.
Componente de IU |
Cuándo se habilita la espacialización |
En el entorno 2D |
---|---|---|
|
El panel se empujará ligeramente hacia atrás en la profundidad en Z para mostrar un diálogo elevado. |
Recurre a 2D |
|
El panel se empujará ligeramente hacia atrás en la profundidad en Z para mostrar una ventana emergente elevada. |
Recurre a un |
|
Se puede configurar |
Muestras sin elevación espacial. |
SpatialDialog
Este es un ejemplo de un diálogo que se abre después de una breve demora. Cuando se usa SpatialDialog
, el diálogo aparece en la misma profundidad en Z que el panel espacial, y el panel se aleja 125 dp cuando se habilita la espacialización.
SpatialDialog
se puede usar cuando la espacialización tampoco está habilitada y se recurre a su contraparte en 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")
}
}
}
}
}
Puntos clave sobre el código
- Este es un ejemplo de
SpatialDialog
. El uso deSpatialPopUp
ySpatialElevation
será muy similar. Consulta nuestra referencia de la API para obtener más detalles.
Crea paneles y diseños personalizados
Para crear paneles personalizados que Compose para XR no admite, puedes trabajar directamente con PanelEntities
y el grafo de escenas con las APIs de SceneCore
.