1. 准备工作
学习内容
- XR 设备类型能够提供的独特用户体验。
- 学习如何通过使用 Jetpack Compose XR 库提供的可组合项,调整应用以充分利用在 Android XR 头戴式设备上运行的优势。
- 如何使用 Compose XR 库提供的界面元素。
- 详细了解如何构建适用于 Android XR 的应用。
这并非是
- 有关在不使用 Compose 的情况下构建 Android XR 应用的指南。请参阅为基于 Android 视图的应用开发界面。
- 有关如何构建适用于 Android XR 的 Unity 或 OpenXR 应用的指南。请参阅使用 Unity for Android XR 进行开发和使用 OpenXR 进行开发。
所需条件
- Android Studio 预览版
- 一台能够运行 Android XR 模拟器的计算机
- 具备 Kotlin 和 Jetpack Compose 使用经验,例如,完成“Android 之 Compose 开发基础”课程
- 具备创建 Android 虚拟设备以及在 Android 虚拟设备上运行应用的经验。
构建内容
在此 Codelab 中,您将通过 Android XR 增强基本单屏应用,提供身临其境的用户体验。
起始代码 | 最终结果 |
2. 进行设置
获取代码
- 此 Codelab 的代码可以在
xr-codelabs
GitHub 存储库的xr-fundamentals
目录中找到。如需克隆此代码库,请运行以下命令:
git clone https://github.com/android/xr-codelabs.git
- 或者,您也可以下载代码库 Zip 文件。
打开项目
- 在启动 Android Studio 后,导入项目,仅选择
xr-fundamentals/start
目录。xr-fundamentals/part1
目录包含解决方案代码,如果您遇到困难或只想查看完整项目,可以随时参考。
熟悉代码
- 在 Android Studio 中打开项目后,花些时间浏览起始代码。
3. 了解 XR 概念:模式和空间面板
在此 Codelab 中,您将学习两个 Android XR 概念:模式和空间面板。您还将了解如何将这些概念应用于在 Android XR 设备上运行的应用。
Modes
在 Android XR 设备上,应用会在以下两种模式之一中运行:Home Space模式或 Full Space 模式。
Home Space 模式
在 Home Space 模式下,多个应用可以并排运行,以便用户在多个应用之间同时处理多个任务。Android 应用可以在不进行修改的情况下在 Home Space 模式下运行。
Full Space 模式
在 Full Space 模式下,一次只运行一个应用,且没有空间边界。所有其他应用都会被隐藏。应用必须执行额外的工作才能进入 Full Space 模式,并利用此模式中可用的其他功能。
如需详细了解这些模式,请参阅 Home Space 模式和 Full Space 模式
空间面板
空间面板是容器元素,是 Android XR 应用的基本构建块。
在 Home Space 模式中运行时,您的应用将包含在单个面板中,提供类似于大屏 Android 设备上的窗口化模式的体验。
在 Full Space 模式下运行时,您可以将应用的内容拆分到一个或多个面板中,以提供更具沉浸感的体验。
如需详细了解面板,请参阅空间面板。
4. 在 Android XR 模拟器中运行应用
在开始针对 Android XR 优化应用之前,您可以在 Android XR 模拟器中运行应用,查看其在 Home Space 模式下的外观。
安装 Android XR 系统映像
- 首先,在 Android Studio 中打开 SDK 管理器,然后选择 SDK Platforms 标签页(如果尚未选择)。在 SDK 管理器窗口的右下角,确保选中 Show package details 复选框。
- 在 Android 14 部分下,安装 Android XR ARM 64 v8a 或 Android XR Intel x86_64 模拟器映像。映像只能在具有与其相同架构 (x86/ARM) 的机器上运行。
创建 Android XR 虚拟设备
- 打开设备管理器后,选择窗口左侧 Category 列下的 Automotive。然后,从列表中选择 XR Device 硬件配置文件,然后点击 Next。
- 在下一页上,选择您之前安装的系统映像。点击 Next,并选择所需的任何高级选项,最后点击 Finish 以创建 AVD。
- 在您刚刚创建的 AVD 上运行应用。
5. 设置依赖项
在开始向应用添加 XR 专用功能之前,您需要添加对 Jetpack Compose for XR 库 androidx.xr.compose:compose
的依赖项,该库包含为应用构建 Android XR 优化体验所需的所有可组合项。
libs.version.toml
[versions]
...
xrCompose = "1.0.0-alpha01"
[libraries]
...
androidx-xr-compose = { group = "androidx.xr.compose", name = "compose", version.ref = "xrCompose" }
build.gradle.kts(模块 :app)
dependencies {
...
implementation(libs.androidx.xr.compose)
...
}
更新这些文件后,请务必执行 Gradle 同步,以确保依赖项已下载到您的项目中。
6. 进入 Full Space 模式
如需使用面板等 XR 功能,应用必须在 Full Space 模式下运行。应用可以通过以下两种方式进入 Full Space 模式:
- 以程序化方式,例如响应应用中的用户互动
- 在启动时立即执行,方法是向应用清单添加指令。
以程序化方式进入 Full Space 模式
如需以程序化方式进入 Full Space 模式,您可以在界面中提供相应功能,让用户控制他们希望在哪种模式下使用应用。此外,您还可以根据应用使用情境进入 Full Space 模式。例如,在开始观看视频内容时进入 Full Space 模式,在播放完毕后退出 Full Space 模式。
为简单起见,您可以先在顶部应用栏中添加一个按钮来切换模式。
- 在
com.example.android.xrfundamentals.ui.component
软件包中创建一个新文件ToggleSpaceModeButton.kt
,并添加以下可组合项:
ToggleSpaceModeButton.kt
package com.example.android.xrfundamentals.ui.component
import androidx.annotation.DrawableRes
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.xr.compose.platform.LocalSpatialCapabilities
import androidx.xr.compose.platform.LocalSpatialConfiguration
import com.example.android.xrfundamentals.R
import com.example.android.xrfundamentals.ui.theme.XRFundamentalsTheme
@Composable
fun ToggleSpaceModeButton(modifier: Modifier = Modifier) {
val spatialConfiguration = LocalSpatialConfiguration.current
if (LocalSpatialCapabilities.current.isSpatialUiEnabled) {
ToggleSpaceModeButton(
modifier = modifier,
contentDescription = "Request Home Space mode",
iconResource = R.drawable.ic_home_space_mode,
onClick = { spatialConfiguration.requestHomeSpaceMode() }
)
} else {
ToggleSpaceModeButton(
modifier = modifier,
contentDescription = "Request Full Space mode",
iconResource = R.drawable.ic_full_space_mode,
onClick = { spatialConfiguration.requestFullSpaceMode() }
)
}
}
@Composable
fun ToggleSpaceModeButton(
contentDescription: String,
@DrawableRes iconResource: Int,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
IconButton(
modifier = modifier,
onClick = onClick
) {
Icon(
painterResource(iconResource),
contentDescription
)
}
}
- 在应用在 XR 设备上运行时,将该按钮添加为
TopAppBar
中的操作
XRFundamentalsTopAppBar.kt
import androidx.xr.compose.platform.LocalHasXrSpatialFeature
...
TopAppBar(
...,
actions = {
// Only show the mode toggle if the device supports spatial UI
if (LocalHasXrSpatialFeature.current) {
ToggleSpaceModeButton()
}
}
)
现在运行应用。
应用在启动时在 Home Space 模式下运行。点按面板右上角的按钮,切换到 Full Space 模式。 | 应用在 Full Space 模式下运行。请注意,用于最小化/关闭应用的系统界面已消失。点按面板右上角的按钮,切换回 Home Space 模式。 |
这些代码段包含一些值得注意的新 API:
LocalSpatialConfiguration
是一个本地组合,可提供对应用当前空间配置的访问权限。除了用于请求更改模式的方法之外,它还包含其他信息,例如包含应用的卷的大小。LocalSpatialCapabilities
是一个本地组合,可用于确定应用当前可使用的空间功能。除了模式(Home Space 或 Full Space)之外,还包括空间音频和 3D 内容支持等功能。LocalHasXrSpatialFeature
是一个本地组合,可用于确定应用是否在支持空间界面功能的设备上运行。在后台,它会检查设备是否具有android.software.xr.immersive
系统功能。
在启动时进入 Full Space 模式
如需指示操作系统以 Full Space 模式启动 activity,您可以在相应的 <activity>
元素中添加具有以下属性的 <property>
元素。只有在用户不太可能在使用您的应用的同时使用其他应用时,我们才建议您使用这种方式。
AndroidManifest.xml
<activity
android:name=".MainActivity"
... >
<property
android:name="android.window.PROPERTY_XR_ACTIVITY_START_MODE"
android:value="XR_ACTIVITY_START_MODE_FULL_SPACE_MANAGED" />
</activity>
现在,当应用启动时,用户会立即进入 Full Space 模式。
在继续操作之前,请从清单中移除上述 <property>
元素,以便应用使用默认行为,即在 Home Space 模式下打开。
7. 将界面拆分为多个面板
现在,您的应用可以进入和退出 Full Space 模式,是时候更好地利用它了。一种很好的方法是,将应用的内容拆分为多个面板以填充空间,并(可选)允许用户根据需要移动和调整这些面板的大小。
将应用嵌入子空间
首先,在 XRFundamentalsApp
可组合项中的 Scaffold
可组合项后面添加一个 Subspace
可组合项。子空间是应用中 3D 空间的一部分,您可以在其中构建 3D 布局(例如添加空间面板)、放置 3D 模型,以及为原本的 2D 内容添加深度。
在非 XR 设备上运行时,Subspace
可组合项的内容永远不会进入组合。在 XR 设备上运行时,只有在应用以 Full Space 模式运行时,内容才会进入组合。
XRFundamentalsApp.kt
import androidx.xr.compose.spatial.Subspace
...
HelloAndroidXRTheme {
Scaffold(...)
Subspace {
}
}
现在,运行应用:
如果您的应用包含 Subspace
可组合项,系统会显示该可组合项,而不是 2D 内容。这意味着,当您点击该按钮进入 Full Space 模式时,系统不会再显示任何内容。为了解决此问题,您将在接下来的几个步骤中添加两个空间面板,一个用于包含主要内容,另一个用于包含次要内容。
为主要内容添加面板
如需在 Full Space 模式下显示主要内容,请在 Subspace
可组合项中添加 SpatialPanel
。
由于这是应用的主要面板,因此您可以在其中添加 Scaffold
,以保持顶部应用栏中的控件处于显示状态。在下一个 Codelab 中,您将了解轨道器,轨道器可用于对应用栏中通常包含的控件(例如导航和特定于上下文的操作)进行空间化处理。
XRFundamentalsApp.kt
import androidx.xr.compose.subspace.SpatialPanel
...
Subspace {
SpatialPanel() {
Scaffold(
topBar = { XRFundamentalsTopAppBar() }
) { innerPadding ->
Box(Modifier.padding(innerPadding)) {
PrimaryCard(
modifier = Modifier
.padding(16.dp)
.verticalScroll(rememberScrollState())
)
}
}
}
}
再次运行应用,您会看到包含主要内容的 SpatialPanel
在 Full Space 模式下可见,但非常小。
修改主要面板
为了让主面板更易于使用,您可以通过提供 SubspaceModifier
来增大主面板。子空间修饰符类似于修饰符,用于修饰面板等空间组件。
XRFundamentalsApp.kt
import androidx.xr.compose.subspace.layout.SubspaceModifier
import androidx.xr.compose.subspace.layout.height
import androidx.xr.compose.subspace.layout.width
import androidx.compose.ui.unit.dp
...
SpatialPanel(
modifier = SubspaceModifier
.width(1024.dp)
.height(800.dp)
){
...
}
再次运行应用,主面板应该会占用更多空间。
为次要内容添加面板
现在,您已经让应用在 Full Space 模式下运行,并使用面板来显示主要内容,接下来可以将次要内容移到自己的面板中了。请注意,在空间面板中使用 Surface
。如果没有该 Surface,次要卡片将没有背景,因为空间面板本身是透明的(Scaffold
可组合项在前一步中处理了此问题)。
XRFundamentalsApp.kt
Subspace {
SpatialPanel() { ... }
SpatialPanel(
modifier = SubspaceModifier
.width(340.dp)
.height(800.dp)
) {
Surface {
SecondaryCardList(
modifier = Modifier
.padding(16.dp)
.verticalScroll(rememberScrollState())
)
}
}
}
现在,再次运行应用。乍一看,第二个面板似乎没有显示,但实际上它是显示的,只是隐藏在主面板后面。
将面板排成一行
与 2D 内容一样,使用行和列有助于并排排列可组合项,而不会出现重叠。使用面板等空间组件时,您可以使用 SpatialRow
和 SpatialColumn
可组合项来实现此目的。
XRFundamentalsApp.kt
import androidx.xr.compose.subspace.SpatialRow
...
Subspace {
SpatialRow(
curveRadius = 825.dp
) {
SpatialPanel(...) { ... }
SpatialPanel(...) { ... }
}
}
再次运行应用,您应该会看到面板依次排列成一行。此外,由于向 SpatialRow
提供 curveRadius
,因此面板会围绕用户弯曲,而不是停留在同一平面上,从而提供更全面的体验。
使面板可调整大小
为了让用户能够控制应用的外观,您可以使用 resizable
子空间修饰符让面板可调整大小。
默认情况下,可调整大小的面板可以缩小到零或无限扩展,因此您可能需要花时间根据面板将包含的内容设置适当的 minimumSize
和 maximumSize
参数。
如需详细了解 resizable
修饰符支持的所有参数,请参阅参考文档。
XRFundamentalsApp.kt
import androidx.xr.compose.subspace.layout.resizable
...
SpatialPanel(
modifier = SubspaceModifier
...
.resizable(true)
)
使面板可移动
同样,您可以使用 movable
子空间修饰符使面板可移动。
XRFundamentalsApp.kt
import androidx.xr.compose.subspace.layout.movable
...
SpatialPanel(
modifier = SubspaceModifier
...
.movable(true)
)
如需详细了解 movable
修饰符支持的所有参数,请参阅参考文档。
8. 恭喜
如需继续了解如何充分利用 XR,请查看以下资源和练习。此外,您还可以申请参加 XR 训练营!
深入阅读
- 针对 XR 进行设计涵盖了在构建 Android XR 应用时要遵循的设计原则和最佳实践。
- 使用 Jetpack XR SDK 进行开发包含有关您可用于构建 Android XR 体验的 API 和工具的技术指南。
- Android XR 应用质量准则页面介绍了打造出色用户体验的标准。
- 深入了解 Hello Android XR 示例
挑战
- 使用可用于
resizable
和movable
子空间修饰符的其他参数。 - 添加其他面板。
- 使用其他空间组件,例如空间对话框