查看引用/信息源請(qǐng)點(diǎn)擊:中國(guó)AI網(wǎng)

使用Jetpack XR SDK,借助Kotlin和Compose等現(xiàn)代Android開發(fā)工具構(gòu)建沉浸式XR體驗(yàn)

中國(guó)AI網(wǎng) 2025年10月23日)隨著三星Galaxy XR的發(fā)布,首款搭載Android XR的設(shè)備正式到來(lái)。用戶現(xiàn)在可以從Play商店以全新的維度——第三維度,來(lái)體驗(yàn)自己喜愛的應(yīng)用。

第三維度是一個(gè)廣闊的空間,同時(shí)為你的應(yīng)用提供了充足的用武之地。立即開始,使用適合的工具進(jìn)行開發(fā)。例如,你可以使用Jetpack XR SDK,借助Kotlin和Compose等現(xiàn)代Android開發(fā)工具構(gòu)建沉浸式XR體驗(yàn)。

在這篇博文中,谷歌分享了如何將備受喜愛的Androidify的帶入XR世界,并介紹將你的應(yīng)用引入XR所需了解的基礎(chǔ)知識(shí)。

谷歌分享:Android應(yīng)用XR適配開發(fā)案例  第1張

Androidify之旅

Androidify是一款開源應(yīng)用,允許你使用最新技術(shù)(如Gemini、CameraX、Navigation 3,當(dāng)然還有Jetpack Compose)來(lái)創(chuàng)建Android bot。Androidify最初通過(guò)創(chuàng)建自適應(yīng)布局,旨在手機(jī)、可折疊設(shè)備和平板電腦上都能呈現(xiàn)出色的視覺效果。

自適應(yīng)布局的一個(gè)關(guān)鍵支柱是可復(fù)用的Composable組件。Jetpack Compose幫助你創(chuàng)建小巧的UI組件,這些組件可以通過(guò)不同的方式布局,以創(chuàng)建直觀的用戶體驗(yàn),無(wú)論用戶使用何種類型的設(shè)備。事實(shí)上,Androidify無(wú)需對(duì)應(yīng)用進(jìn)行任何修改,即可兼容Android XR。

對(duì)于沒有為Android XR做特殊處理的應(yīng)用,它們可以在適當(dāng)大小的窗口中進(jìn)行多任務(wù)處理,其工作方式與在大屏幕上非常相似。正因如此,Androidify在Android XR上已經(jīng)功能完備,無(wú)需額外工作。但我們并不想止步于此,所以我們決定更進(jìn)一步,創(chuàng)建一個(gè)具有XR差異化的應(yīng)用,為我們的XR用戶帶來(lái)愉悅的體驗(yàn)。

熟悉XR環(huán)境

我們回顧一下Android XR的關(guān)鍵基本概念,首先從應(yīng)用可以運(yùn)行的兩種模式開始:主空間和完整空間。

在主空間中,可以并排運(yùn)行多個(gè)應(yīng)用,因此用戶可以在不同窗口之間進(jìn)行多任務(wù)處理。從這個(gè)意義上說(shuō),它很像大型屏幕Android設(shè)備上的桌面窗口管理,但這是在虛擬空間中。

在完整空間中,應(yīng)用沒有空間邊界,可以利用Android XR的全部空間特性,例如空間UI和控制虛擬環(huán)境。

盡管允許你的應(yīng)用僅在完整空間中運(yùn)行似乎很誘人,但你的用戶可能希望與你的應(yīng)用進(jìn)行多任務(wù)處理,所以同時(shí)支持這兩種模式可以帶來(lái)更好的用戶體驗(yàn)。

為Androidify的新維度設(shè)計(jì)

一個(gè)令人愉悅的應(yīng)用始于出色的設(shè)計(jì)。Android開發(fā)者關(guān)系團(tuán)隊(duì)的高級(jí)設(shè)計(jì)倡導(dǎo)者Ivy Knight承擔(dān)了這項(xiàng)任務(wù):基于Androidify的現(xiàn)有設(shè)計(jì),為XR構(gòu)思新的設(shè)計(jì)。接下來(lái)交給Ivy了。

為XR設(shè)計(jì)需要一種獨(dú)特的方法,但實(shí)際上與移動(dòng)設(shè)計(jì)仍有很多共同之處。我們首先考慮的是“容器”概念:如何在子空間內(nèi)組織和分組UI元素,可以通過(guò)清晰地顯示邊界,也可以通過(guò)微妙地暗示邊界。我們同時(shí)學(xué)會(huì)了接納各種尺寸的空間UI元素,以響應(yīng)用戶而調(diào)整和移動(dòng)。正如Androidify所做的那樣,使用自適應(yīng)布局進(jìn)行構(gòu)建,這樣你就可以將布局分解成若干部分,用于你的空間UI。

從主空間開始設(shè)計(jì)

幸運(yùn)的是,Android XR允許你從應(yīng)用的當(dāng)前狀態(tài)開始為主空間進(jìn)行適配,所以只需添加一個(gè)窗口工具欄和完整空間切換按鈕,即可過(guò)渡到擴(kuò)展的XR設(shè)計(jì)。

我們同時(shí)考慮了可能的硬件特性以及用戶將如何與它們交互。Androidify的移動(dòng)端布局適應(yīng)各種設(shè)備形態(tài)、屏幕尺寸和攝像頭數(shù)量,以提供更多照片選項(xiàng)。遵循這種模式,我們必須為頭戴式設(shè)備調(diào)整camera布局。我們同時(shí)需要對(duì)文本進(jìn)行調(diào)整,以考慮UI與用戶的接近程度。

為向完整空間的更大轉(zhuǎn)變進(jìn)行設(shè)計(jì)

向完整空間的轉(zhuǎn)變是最大的挑戰(zhàn),但也給了我們最大的創(chuàng)意空間來(lái)調(diào)整設(shè)計(jì)。

Androidify使用視覺容器(或窗格)通過(guò)背景和輪廓來(lái)對(duì)功能進(jìn)行分組,例如拍攝或選擇照片窗格。我們使用了頂部應(yīng)用欄等組件,通過(guò)框住其他窗格來(lái)創(chuàng)建自然的容器。最后,通過(guò)特定元素彼此之間的接近性來(lái)暗示內(nèi)在的容器關(guān)系,例如靠近“選擇我的bot顏色”窗格的開始轉(zhuǎn)換底部按鈕。

空間面板便于實(shí)現(xiàn)輕松分離。要決定如何使你的移動(dòng)設(shè)計(jì)適應(yīng)空間面板,請(qǐng)嘗試從最遠(yuǎn)的表面開始移除表面,然后向前移動(dòng)。看看你可以移除多少背景,以及剩下什么。當(dāng)我們?yōu)锳ndroidify完成這個(gè)練習(xí)后,剩下的是那個(gè)巨大的綠色Android波浪形圖案。這個(gè)波浪形圖案不僅起到了品牌標(biāo)識(shí)和背景的作用,還成為了3D空間中內(nèi)容的錨點(diǎn)。

建立這個(gè)錨點(diǎn)既讓我們更容易想象元素如何圍繞它移動(dòng),也讓我們能夠利用接近性來(lái)突破并轉(zhuǎn)化用戶體驗(yàn)的其余部分。

幫助你的應(yīng)用實(shí)現(xiàn)空間化的其他設(shè)計(jì)技巧

讓元素突破容器限制:將組件分離出來(lái),給它們一些真正的(空間)空間。是時(shí)候給那些UI元素一些呼吸空間了。

移除表面:隱藏背景,看看這會(huì)對(duì)你的設(shè)計(jì)產(chǎn)生什么影響。

用動(dòng)效激發(fā)活力:你在應(yīng)用中如何使用過(guò)渡效果?利用這種特性來(lái)想象你的應(yīng)用如何突破到VR中。

選擇一個(gè)錨點(diǎn):不要讓你的用戶在空間中迷失。設(shè)置一個(gè)有助于匯集或固定UI的元素。

有關(guān)XR UI設(shè)計(jì)模式的更多信息,請(qǐng)查閱這個(gè)頁(yè)面。

空間UI基礎(chǔ)

既然我們已經(jīng)了解了Ivy在為XR設(shè)計(jì)Androidify時(shí)調(diào)整思維方式的經(jīng)驗(yàn),現(xiàn)在我們談?wù)勯_發(fā)空間UI。如果你習(xí)慣于使用現(xiàn)代Android工具和庫(kù),那么使用Jetpack XR SDK開發(fā)空間UI應(yīng)該會(huì)感覺很熟悉。你會(huì)發(fā)現(xiàn)你已經(jīng)熟悉的概念,例如使用Compose創(chuàng)建布局。實(shí)際上,空間布局與使用行、列和間隔物的2D布局非常相似:

這里顯示的空間元素是SpatialPanel Composable,它允許你顯示文本、按鈕和視頻等2D內(nèi)容。

Subspace { SpatialPanel( SubspaceModifier .height(824.dp) .width(1400.dp) ) { Text("I'm a panel!") }}

SpatialPanel是一個(gè)子空間Composable。子空間Composable必須包含在Subspace內(nèi),并由SubspaceModifier對(duì)象修飾。Subspace可以放置在應(yīng)用UI層次結(jié)構(gòu)中的任何位置,并且只能包含子空間Composable。SubspaceModifier對(duì)象也與Modifier對(duì)象非常相似:它們控制大小和位置等參數(shù)。

一個(gè)Orbiter可以附加到SpatialPanel上,并隨其附著的內(nèi)容一起移動(dòng)。它們通常用于提供關(guān)于所附著內(nèi)容的上下文控件,使內(nèi)容成為主要焦點(diǎn)。它們可以放置在內(nèi)容四個(gè)邊中的任何一邊,距離可配置。

還有更多的空間UI元素,但這是我們?yōu)锳ndroidify創(chuàng)建空間布局時(shí)使用的主要元素。

開始XR開發(fā)

我們從項(xiàng)目設(shè)置開始。我們添加了Jetpack XR Compose依賴項(xiàng),你可以在Jetpack XR依賴項(xiàng)頁(yè)面上找到它。

我們添加了一個(gè)按鈕的代碼,該按鈕用于將用戶切換到完整空間,首先檢測(cè)是否具有此功能:

@Composablefun couldRequestFullSpace(): Boolean = LocalSpatialConfiguration.current.hasXrSpatialFeature &&  !LocalSpatialCapabilities.current.isSpatialUiEnabled}

然后,我們制作了一個(gè)新的按鈕組件,將”擴(kuò)展內(nèi)容”圖標(biāo)添加到我們現(xiàn)有的布局中,并為其設(shè)置了onClick行為:

@Composablefun RequestFullSpaceIconButton() { if (!couldRequestFullSpace()) return val session = LocalSession.current ?: return IconButton( onClick = { session.scene.requestFullSpaceMode() }, ) { Icon( imageVector =  vectorResource(R.drawable.expand_content_24px), contentDescription =  stringResource("To Full Space"), ) }}

現(xiàn)在,點(diǎn)擊該按鈕只是在完整空間中顯示中等布局。我們可以檢查空間能力并確定是否可以顯示空間UI——在這種情況下,我們將顯示新的空間布局:

@Composablefun HomeScreenContents(layoutType: HomeScreenLayoutType) { val layoutType = when { LocalSpatialCapabilities.current.isSpatialUiEnabled ->  HomeScreenLayoutType.Spatial isAtLeastMedium() -> HomeScreenLayoutType.Medium else -> HomeScreenLayoutType.Compact } when (layoutType) { HomeScreenLayoutType.Compact -> HomeScreenCompactPager(...) HomeScreenLayoutType.Medium -> HomeScreenMediumContents(...) HomeScreenLayoutType.Spatial -> HomeScreenContentsSpatial(...) }}

實(shí)現(xiàn)主屏幕的設(shè)計(jì)

我們回到完整空間中主屏幕的空間設(shè)計(jì),了解它是如何實(shí)現(xiàn)的。

我們?cè)谶@里確定了兩個(gè)SpatialPanel元素:右側(cè)一個(gè)包含視頻卡的面板,以及一個(gè)包含主UI的面板。最后,頂部附加了一個(gè)Orbiter。讓我們從視頻播放器面板開始:

@Composablefun HomeScreenContentsSpatial(...) { Subspace { SpatialPanel(SubspaceModifier .fillMaxWidth(0.2f) .fillMaxHeight(0.8f) .aspectRatio(0.77f) .rotate(0f, 0f, 5f), ) { VideoPlayer(videoLink) } }}

我們直接將常規(guī)布局中的2D VideoPlayer組件復(fù)用到SpatialPanel中,無(wú)需任何額外更改。

主要內(nèi)容面板的情況類似:我們?cè)赟patialPanel中復(fù)用了中等面板的內(nèi)容。

SpatialPanel(SubspaceModifier.fillMaxSize(), resizePolicy = ResizePolicy( shouldMaintainAspectRatio = true ), dragPolicy = MovePolicy()) { Box { FillBackground(R.drawable.squiggle_full) HomeScreenSpatialMainContent(...) }}

我們給這個(gè)面板設(shè)置了一個(gè)ResizePolicy,它會(huì)在面板邊緣附近提供一些手柄,讓用戶可以調(diào)整面板大小。它還有一個(gè)MovePolicy,允許用戶拖動(dòng)它。

將它們放在同一個(gè)Subspace中會(huì)使它們彼此獨(dú)立,因此我們將VideoPlayer面板設(shè)為主要內(nèi)容面板的子級(jí)。這樣,當(dāng)主要內(nèi)容面板被拖動(dòng)時(shí),VideoPlayer面板會(huì)通過(guò)父子關(guān)系隨之移動(dòng)。

@Composablefun HomeScreenContentsSpatial(...) { Subspace { SpatialPanel(SubspaceModifier..., resizePolicy, dragPolicy) { Box { FillBackground(R.drawable.squiggle_full) HomeScreenSpatialMainContent(...) } Subspace { SpatialPanel(SubspaceModifier...) { VideoPlayer(videoLink) } } } }}

我們就是這樣完成第一個(gè)屏幕的。

繼續(xù)其他屏幕

我將簡(jiǎn)要介紹其他一些屏幕,重點(diǎn)說(shuō)明為每個(gè)屏幕所做的具體考慮。

在這里,我們使用SpatialRow和SpatialColumn Composable來(lái)創(chuàng)建適合推薦觀看區(qū)域的布局,再次復(fù)用了中等布局中的組件。

完整空間中的結(jié)果屏幕:生成的機(jī)器人,描述為:紅色棒球帽、飛行員太陽(yáng)鏡、淺藍(lán)色T恤、紅白格子短褲、綠色人字拖,并拿著一個(gè)網(wǎng)球拍。

結(jié)果屏幕使用羽化效果顯示贊美詞,使它們?cè)谄聊贿吘壐浇饾u淡出。在查看所使用的輸入時(shí),它還使用了真正的3D過(guò)渡效果,將圖片在空間中翻轉(zhuǎn)過(guò)來(lái)。

發(fā)布到Google Play商店

現(xiàn)在,應(yīng)用已經(jīng)通過(guò)空間布局為XR做好了準(zhǔn)備,我們繼續(xù)將其發(fā)布到Play商店。我們對(duì)應(yīng)用的AndroidManifest.xml文件進(jìn)行了一項(xiàng)最終的重要更改:

這可以讓Play商店知道此應(yīng)用具有XR差異化功能,顯示一個(gè)徽章,讓用戶知道該應(yīng)用是考慮到XR而制作的:

上傳版本時(shí),我們不需要為XR發(fā)布執(zhí)行任何特殊步驟:同一個(gè)應(yīng)用會(huì)像分發(fā)給移動(dòng)端用戶一樣,正常分發(fā)給XR設(shè)備上的用戶!但是,你可以選擇添加應(yīng)用的XR特定截圖,甚至可以使用空間視頻資源上傳應(yīng)用的沉浸式預(yù)覽。在Android XR設(shè)備上,Play商店會(huì)自動(dòng)將其顯示為沉浸式3D預(yù)覽,讓用戶在安裝應(yīng)用之前就能體驗(yàn)內(nèi)容的深度和規(guī)模。

立即開始構(gòu)建

Androidify是一個(gè)如何將現(xiàn)有2D Jetpack Compose應(yīng)用空間化的絕佳示例。今天,我們展示了為Androidify開發(fā)空間UI的完整過(guò)程,從設(shè)計(jì)到編碼再到發(fā)布。我們修改了現(xiàn)有設(shè)計(jì)以適應(yīng)空間范式,使用SpatialPanel和Orbiter Composable創(chuàng)建了在用戶進(jìn)入完整空間時(shí)顯示的空間布局,最后將新版本的應(yīng)用發(fā)布到Play商店。

希望這篇博文能幫助你了解如何將你自己的應(yīng)用帶入Android XR。