1. 事前準備
課程內容
- 可透過 XR 板型規格打造的獨特使用者體驗。
- 介紹基礎知識,瞭解如何使用 Jetpack Compose XR 程式庫提供的可組合函式調整應用程式,以便在 Android XR 頭戴式裝置上執行時發揮最大功效。
- 如何使用 Compose XR 程式庫提供的 UI 元素。
- 進一步瞭解如何建構 Android XR 應用程式的資源。
未提供的內容
- 不使用 Compose 來建構 Android XR 應用程式的指南。請參閱「為以 Android View 為基礎的應用程式開發 UI」一文。
- 建構適用於 Android XR 的 Unity 或 OpenXR 應用程式相關指南。請參閱「使用 Unity 為 Android XR 開發」和「使用 OpenXR 進行開發」這兩篇文章。
軟硬體需求
- Android Studio 預先發布版
- 能夠執行 Android XR 模擬器的電腦
- 具備 Kotlin 和 Jetpack Compose 相關經驗,例如,完成「Android 基本概念:使用 Compose」課程
- 具備建立 Android 虛擬裝置並在其中執行應用程式的經驗
建構項目
在本程式碼實驗室中,您將強化一個基本的單畫面應用程式,透過 Android XR 提供沈浸式使用者體驗。
起點 | 最終結果 |
2. 做好準備
取得程式碼
- 您可以在
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 概念:模式與空間面板
在本程式碼研究室中,您將瞭解模式和空間面板這兩個 Android XR 概念,並學習如何在 Android XR 裝置上執行的應用程式中套用這些概念。
模式
在 Android XR 裝置上,應用程式會在首頁空間模式或完整空間模式下執行。
首頁空間模式
在首頁空間模式中,多個應用程式可同時執行,因此使用者可以跨應用程式多工處理。Android 應用程式可在首頁空間模式執行,不需修改程式碼。
完整空間模式
在完整空間模式中,一次執行一個應用程式,沒有空間限制。所有其他應用程式都會隱藏起來。應用程式必須執行額外工作,才能進入完整空間模式,並使用此模式提供的額外功能。
如要進一步瞭解這些模式,請參閱「首頁空間和完整空間模式」相關說明。
空間面板
空間面板是容器元素,也是 Android XR 應用程式的基礎構成元素。
在首頁空間模式下執行時,應用程式會保存在單一面板中,提供類似於大螢幕 Android 裝置上的電腦分割視窗體驗。
在完整空間模式下執行時,您可以將應用程式的內容打散到一或多個面板中,提供更身歷其境的體驗。
如要進一步瞭解面板,請參閱「空間面板」相關說明。
4. 在 Android XR 模擬器中執行應用程式
開始強化這個 Android XR 應用程式之前,可以先在 Android XR 模擬器中執行應用程式,看看在首頁空間模式下執行的情形。
安裝 Android XR 系統映像檔
- 首先,在 Android Studio 中開啟 SDK Manager,然後選取「SDK Platforms」分頁標籤 (如果尚未選取)。在 SDK Manager 視窗的右下角,確認已勾選「Show package details」方塊。
- 在 Android 14 部分下方,安裝「Android XR ARM 64 v8a」或「Android XR Intel x86_64」模擬器映像檔。映像檔只能在與本身架構 (x86/ARM) 相同的機器上執行。
建立 Android XR 虛擬裝置
- 開啟裝置管理工具後,選取視窗左側「Category」欄下方的「XR」。接著,從清單中選取「XR Device」硬體設定檔,點選「Next」。
- 在下一頁中,選取先前安裝的系統映像檔。按一下「Next」,選取所需進階選項,最後點選「Finish」建立 AVD。
- 在剛剛建立的 AVD 上執行應用程式。
5. 設定依附元件
開始在應用程式中新增 XR 專屬功能前,您需要為 XR 程式庫新增 Jetpack Compose 的依附元件 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 (Module :app)
dependencies {
...
implementation(libs.androidx.xr.compose)
...
}
更新這些檔案後,請務必執行 Gradle 同步處理,確保依附元件已下載至專案。
6. 進入完整空間模式
應用程式必須在完整空間模式下執行,才能使用面板等 XR 功能。應用程式可透過以下兩種方式進入完整空間模式:
- 透過程式輔助,例如回應應用程式中的使用者互動
- 在應用程式資訊清單中加入指令,啟動後立即進入
透過程式輔助進入完整空間模式
如要透過程式輔助進入完整空間模式,您可以在 UI 中提供功能提示,讓使用者控制要在哪個模式中使用應用程式。此外,您也可以根據應用程式使用情境,在適當時機進入完整空間模式。例如,開始觀看影片內容時進入完整空間模式,播放完成時退出。
為簡單起見,只要在頂端應用程式列中新增一個按鈕來切換模式,就能達成這個目標。
- 在
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()
}
}
)
現在請執行應用程式。
應用程式啟動時,會在首頁空間模式下執行。輕觸面板右上方的按鈕,即可切換至完整空間模式。 | 應用程式在完整空間模式下執行。請注意,用於最小化/關閉應用程式的系統 UI 已消失。輕觸面板右上方的按鈕,即可切換回首頁空間模式。 |
這些程式碼片段包含幾個需要注意的新 API:
LocalSpatialConfiguration
是 CompositionLocal,可存取應用程式的目前空間設定。在要求變更模式的方法以外,這還包括容納應用程式的磁碟區大小等其他資訊。LocalSpatialCapabilities
也是 CompositionLocal,可用來判斷應用程式目前可用哪些空間功能。除了首頁或完整空間模式以外,這還包括空間音訊和 3D 內容支援等功能。LocalHasXrSpatialFeature
這個 CompositionLocal 可用來判斷執行應用程式的裝置是否支援空間 UI 功能。實際上,LocalHasXrSpatialFeature 會檢查裝置是否提供android.software.xr.immersive
系統功能。
啟動時進入完整空間模式
如要指示 OS 在完整空間模式下啟動活動,您可以在對應的 <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>
現在啟動應用程式時,會立即帶使用者進入完整空間模式。
繼續進行之前,請從資訊清單移除前述 <property>
元素,讓應用程式使用「在首頁空間模式下開啟」的預設行為。
7. 將 UI 分割到多個面板中
現在應用程式可以順利進入/退出完整空間模式,讓我們善加利用這項功能。其中一個絕佳做法是,將應用程式的內容分割到散布在空間的多個面板中,然後 (選擇性) 讓使用者根據需求移動這些面板及調整大小。
將應用程式嵌入子空間
首先,在 XRFundamentalsApp
可組合函式中,將 Subspace
可組合函式加到 Scaffold
可組合函式之後。子空間是應用程式內 3D 空間的分區,可在其中建構 3D 版面配置 (例如新增空間面板)、放置 3D 模型,以及為其他 2D 內容加上深度。
在非 XR 裝置上執行時,Subspace
可組合函式的內容一律不會進入 Composition。在 XR 裝置上,只有應用程式在完整空間模式下執行時,這些內容才會進入 Composition。
XRFundamentalsApp.kt
import androidx.xr.compose.spatial.Subspace
...
HelloAndroidXRTheme {
Scaffold(...)
Subspace {
}
}
現在執行應用程式:
應用程式會顯示加入的 Subspace
可組合函式,用來取代 2D 內容。這表示當您點選按鈕進入完整空間模式時,再也不會出現任何內容。為修正此問題,您將在接下來的幾個步驟中新增兩個空間面板,一個容納主要內容,另一個容納次要內容。
為主要內容新增面板
在 Subspace
可組合函式內加入 SpatialPanel
,即可在完整空間模式下顯示主要內容。
由於這是應用程式的主要面板,您可在其中加入 Scaffold
,以便持續顯示頂端應用程式列內的控制項。我們將在下一個程式碼研究室中介紹軌道器,可用來空間化應用程式列通常包含的控制項,例如導覽及情境專屬動作。
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
,但尺寸非常小。
修飾主要面板
如要提高主要面板的可用性,您可以提供 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)
){
...
}
再次執行應用程式,主要面板應該會加大許多。
為次要內容新增面板
現在應用程式已經能在完整空間模式下執行,並使用面板來顯示主要內容,該將次要內容移到其專屬面板了。請注意,必須在空間面板內使用 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(...) { ... }
}
}
請再次執行應用程式,您應該會看到這兩個面板已安排在一列中,依序顯示。此外,由於有提供 curveRadius
給 SpatialRow
,面板會在使用者左右呈弧形排列,而非放在同一個平面,可打造更身歷其境的體驗。
製作可調整大小的面板
如要讓使用者控制應用程式的外觀,可以使用 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 進行開發」內含 API 和工具相關技術指引,可用來打造 Android XR 體驗。
- 「Android XR 應用程式品質指南」頁面說明須符合哪些條件,才能建立優質使用者體驗。
- 深入研究 Hello Android XR 範例。
挑戰
- 使用
resizable
和movable
子空間修飾符適用的其他參數。 - 新增其他面板。
- 使用空間對話方塊等其他空間元件。