С помощью Jetpack Compose для XR вы можете декларативно создавать пространственный пользовательский интерфейс и макет, используя знакомые концепции Compose, такие как строки и столбцы. Это позволяет расширить существующий пользовательский интерфейс Android в трехмерном пространстве или создавать совершенно новые иммерсивные трехмерные приложения.
Если вы занимаетесь пространственным определением существующего приложения на базе Android Views, у вас есть несколько вариантов разработки. Вы можете использовать API-интерфейсы совместимости, использовать Compose и Views вместе или работать напрямую с библиотекой SceneCore. Более подробную информацию можно найти в нашем руководстве по работе с представлениями .
О подпространствах и пространственных компонентах
Когда вы пишете приложение для Android XR, важно понимать концепции подпространства и пространственных компонентов .
О подпространстве
При разработке для Android XR вам потребуется добавить подпространство в ваше приложение или макет. Подпространство — это раздел 3D-пространства внутри вашего приложения, где вы можете размещать 3D-контент, создавать 3D-макеты и добавлять глубину к 2D-контенту. Подпространство визуализируется только тогда, когда включена пространственная обработка. В «Домашнем пространстве» или на устройствах, отличных от XR, любой код в этом подпространстве игнорируется.
Существует два способа создания подпространства:
-
setSubspaceContent
: эта функция создает подпространство уровня приложения. Это можно вызвать в MainActivity так же, как вы используетеsetContent
. Подпространство уровня приложения не ограничено по высоте, ширине и глубине, что по сути обеспечивает бесконечный холст для пространственного контента. -
Subspace
: этот составной элемент можно разместить в любом месте иерархии пользовательского интерфейса вашего приложения, что позволяет вам поддерживать макеты для 2D- и пространственного пользовательского интерфейса без потери контекста между файлами. Это упрощает совместное использование таких вещей, как существующая архитектура приложения, между XR и другими форм-факторами без необходимости поднимать состояние по всему дереву пользовательского интерфейса или перепроектировать ваше приложение.
Для получения дополнительной информации прочитайте о добавлении подпространства в ваше приложение .
О пространственных компонентах
Составные части подпространства : эти компоненты можно визуализировать только в подпространстве. Прежде чем помещать их в 2D-макет, они должны быть заключены в Subspace
или setSubspaceContent
. SubspaceModifier
позволяет добавлять такие атрибуты, как глубина, смещение и позиционирование, к составным объектам подпространства.
- Примечание о модификаторах подпространства . Обратите особое внимание на порядок API
SubspaceModifier
.- Смещение должно идти первым в цепочке модификаторов.
- Подвижные и изменяемые размеры должны идти последними.
- Поворот должен применяться перед масштабированием
Другие пространственные компоненты не требуют вызова внутри подпространства. Они состоят из обычных 2D-элементов, заключенных в пространственный контейнер. Эти элементы можно использовать в 2D- или 3D-макетах, если они определены для обоих. Если пространственная обработка не включена, их пространственные объекты будут игнорироваться и будут возвращаться к своим 2D-аналогам.
Создайте пространственную панель
SpatialPanel
— это компонуемое подпространство, которое позволяет отображать содержимое приложения — например, вы можете отображать воспроизведение видео, неподвижные изображения или любой другой контент на пространственной панели.
Вы можете использовать SubspaceModifier
для изменения размера, поведения и положения пространственной панели, как показано в следующем примере.
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
)
}
}
Ключевые моменты о коде
- Примечание о модификаторах подпространства . Обратите особое внимание на порядок API
SubspaceModifier
.- Смещение должно идти первым в цепочке модификаторов.
- Модификаторы Movable и изменяемого размера должны располагаться последними.
- Поворот необходимо применять перед масштабированием.
- Поскольку API-интерфейсы
SpatialPanel
являются компонуемыми подпространствами, вы должны вызывать их внутриSubspace
илиsetSubspaceContent
. Вызов их за пределами подпространства вызовет исключение. - Разрешите пользователю изменять размер или перемещать панель, добавляя
.movable
или.resizable
SubspaceModifier
. - Подробную информацию о размерах и расположении см. в нашем руководстве по проектированию пространственных панелей . Дополнительную информацию о реализации кода см. в нашей справочной документации .
Создать орбитальный аппарат
Орбитальный аппарат — это пространственный компонент пользовательского интерфейса. Он предназначен для прикрепления к соответствующей пространственной панели и содержит элементы навигации и контекстных действий, связанные с этой пространственной панелью. Например, если вы создали пространственную панель для отображения видеоконтента, вы можете добавить элементы управления воспроизведением видео внутри орбитального аппарата.
Как показано в следующем примере, вызовите орбитальный аппарат внутри SpatialPanel
чтобы обернуть пользовательские элементы управления, такие как навигация. При этом они извлекаются из вашего 2D-макета и прикрепляются к пространственной панели в соответствии с вашей конфигурацией.
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
)
}
}
}
}
Ключевые моменты о коде
- Примечание о модификаторах подпространства . Обратите особое внимание на порядок API-интерфейсов
SubspaceModifier
.- Смещение должно идти первым в цепочке модификаторов.
- Подвижные и изменяемые размеры должны идти последними.
- Поворот должен применяться перед масштабированием
- Поскольку орбитальные аппараты являются пространственными компонентами пользовательского интерфейса, код можно повторно использовать в 2D- или 3D-макетах. В 2D-макете ваше приложение отображает только содержимое внутри орбитального аппарата и игнорирует сам орбитальный аппарат.
- Ознакомьтесь с нашим руководством по проектированию , чтобы получить дополнительную информацию о том, как использовать и проектировать орбитальные аппараты.
Добавление нескольких пространственных панелей в пространственный макет
Вы можете создать несколько пространственных панелей и разместить их в SpatialLayout
используя SpatialRow
, SpatialColumn
, SpatialBox
и SpatialLayoutSpacer
.
В следующем примере кода показано, как это сделать.
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
)
}
}
Ключевые моменты о коде
-
SpatialRow
,SpatialColumn
,SpatialBox
иSpatialLayoutSpacer
являются компонуемыми подпространствами и должны быть размещены внутри подпространства. - Используйте
SubspaceModifier
для настройки макета. - Для макетов с несколькими панелями подряд мы рекомендуем установить радиус кривой 825dp с помощью
SubspaceModifier
, чтобы панели окружали пользователя. Подробности смотрите в нашем руководстве по проектированию .
Используйте объем для размещения 3D-объекта в макете.
Чтобы разместить 3D-объект в макете, вам нужно будет использовать составное подпространство, называемое объемом. Вот пример того, как это сделать.
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
}
}
}
}
}
Ключевые моменты о коде
- Примечание о модификаторах подпространства . Обратите особое внимание на порядок API-интерфейсов
SubspaceModifier
.- Смещение должно идти первым в цепочке модификаторов.
- Подвижные и изменяемые размеры должны идти последними.
- Поворот должен применяться перед масштабированием
- См. раздел «Добавление 3D-контента» , чтобы лучше понять, как загружать 3D-контент в объем.
Добавьте другие компоненты пространственного пользовательского интерфейса.
Компоненты пространственного пользовательского интерфейса можно размещать в любом месте иерархии пользовательского интерфейса вашего приложения. Эти элементы можно повторно использовать в вашем 2D-интерфейсе, а их пространственные атрибуты будут видны только при включении пространственных возможностей. Это позволяет вам добавлять высоту к меню, диалоговым окнам и другим компонентам без необходимости писать код дважды. См. следующие примеры пространственного пользовательского интерфейса, чтобы лучше понять, как использовать эти элементы.
Компонент пользовательского интерфейса | Когда пространственное определение включено | В 2D-среде |
---|---|---|
| Панель слегка отодвинется назад по оси Z, чтобы отобразить диалоговое окно с повышенными правами. | Возвращается к 2D- |
| Панель слегка отодвинется назад по оси Z, чтобы отобразить приподнятое всплывающее окно. | Возвращается к 2D |
| | Показывает без пространственной возвышенности. |
Пространственный Диалог
Это пример диалогового окна, которое открывается после небольшой задержки. При использовании SpatialDialog
диалоговое окно отображается на той же глубине по оси Z, что и пространственная панель, а панель смещается на 125dp, когда пространственная обработка включена. SpatialDialog
по-прежнему можно использовать, когда пространственная обработка также не включена, и он возвращается к своему 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")
}
}
}
}
}
Ключевые моменты о коде
- Это пример
SpatialDialog
. ИспользованиеSpatialPopUp
иSpatialElevation
будет очень похожим. Более подробную информацию можно найти в нашем справочнике по API .
Создавайте собственные панели и макеты
Чтобы создавать пользовательские панели, которые не поддерживаются Compose для XR, вы можете работать напрямую с PanelEntities
и графом сцены, используя API-интерфейсы SceneCore
.
См. также
- Добавить 3D-модели
- Разработка пользовательского интерфейса для XR с представлениями
- Материальный дизайн для XR