操作說明

使用 Jetpack XR SDK 將 Androidify 帶入 XR

9 分鐘閱讀
Dereck Bridie
開發人員關係工程師

Samsung Galaxy XR 登場,搭載 Android XR!這篇網誌文章是 Android XR Spotlight Week 的一部分,我們將提供各種資源 (網誌文章、影片、程式碼範例等),協助您學習、建構及準備 Android XR 應用程式。

隨著 Samsung Galaxy XR 上市,首款搭載 Android XR 的裝置正式推出。現在,使用者可以透過 Play 商店,以全新維度 (3D) 體驗許多愛用的應用程式!

第三個維度是寬敞的空間,可容納許多應用程式。立即開始使用適合您應用程式的工具。舉例來說,您可以使用 Jetpack XR SDK,透過 Kotlin 和 Compose 等新式 Android 開發工具,建構沉浸式 XR 體驗。

在這篇網誌文章中,我們將分享將深受喜愛的 Androidify 應用程式帶入 XR 的過程,並說明將應用程式帶入 XR 的基本知識。

Androidify 導覽

Androidify 是一款開放原始碼應用程式,可讓您使用 Gemini、CameraX、Navigation 3 和 Jetpack Compose 等最新技術,建立 Android 機器人。Androidify 最初的設計目標是透過建立自適應版面配置,在手機、折疊式裝置和平板電腦上呈現最佳效果。

customize.png

Androidify 在多種板型規格上都能呈現最佳效果

可重複使用的可組合函式是自我調整式版面配置的關鍵支柱。Jetpack Compose 可協助您建立小巧的 UI 元件,並以不同方式配置,無論使用者使用哪種裝置,都能打造直覺式使用者體驗。事實上,Androidify 與 Android XR 相容,完全不需要修改應用程式!

customize_2.png

Androidify 採用大型螢幕專用的回應式版面配置,因此不必變更程式碼,就能適應 XR 裝置

如果應用程式未特別處理 Android XR,則可在適當大小的視窗中執行多工處理,運作方式與在大螢幕上類似。因此,Androidify 已經在 Android XR 上提供完整功能,不需額外作業!但我們不希望就此止步,因此決定更進一步,打造 XR 專屬應用程式,為 XR 使用者帶來愉悅體驗。

在 XR 中調整方向

讓我們來瞭解 Android XR 的基本概念,首先是應用程式的兩種執行模式:主畫面和全螢幕。

homespace.png
主畫面空間中的應用程式
homespace2.png
全螢幕模式中的應用程式

在「主畫面空間」中,多個應用程式可以並排執行,因此使用者可以跨不同視窗執行多項工作。從這個角度來看,這與大螢幕 Android 裝置上的電腦分割視窗很類似,但這是在虛擬空間中!

全螢幕模式中,應用程式沒有空間限制,可充分運用 Android XR 的空間功能,例如空間 UI 和控制虛擬環境。

雖然您可能會想讓應用程式只在全螢幕空間中執行,但使用者可能想透過應用程式執行多項工作,因此同時支援這兩種模式可提升使用者體驗。

為 Androidify 的新尺寸設計

設計精美的應用程式才能帶給使用者愉悅的體驗。Android DevRel 的資深設計倡導者 Ivy Knight 負責為 Androidify 進行現有設計,並為 XR 提出新設計。Ivy,請開始吧!

設計 XR 應用程式需要獨特的方法,但實際上與行動裝置設計有許多共通之處。我們首先思考的是區隔:如何在子空間中整理 UI 元素並分組,方法是清楚顯示界線或隱含界線。我們也學會接受各種大小的空間 UI 元素,這些元素會根據使用者調整和移動。如同 Androidify,使用自適應版面配置建構,將版面配置分解成空間 UI 的各個部分。

從主畫面開始設計

幸好,Android XR 允許您從目前的應用程式開始,為主畫面設計,因此我們只要新增視窗工具列和全螢幕轉場按鈕,就能轉換為擴展的 XR 設計。

我們也考量了可能的硬體功能,以及使用者與這些功能的互動方式。Androidify 的行動版面配置會根據各種姿勢、班級大小和相機數量調整,提供更多拍照選項。因此,我們也必須根據這個模型調整頭戴式裝置的攝影機配置。此外,我們也需要調整文字,以配合 UI 與使用者的距離。

為全面改用全螢幕做好準備

全螢幕是最大的轉變,但為我們提供了最充裕的創意空間,可調整設計。

tablet_to_xr.webp
從平板電腦到 XR

Androidify 會使用視覺區隔或窗格,將功能與背景和外框分組,例如「拍攝或選擇相片」窗格。我們也使用頂端應用程式列等元件,透過設定其他窗格的框架,建立自然的容器。最後,某些元素與其他元素之間的距離會暗示內在限制,例如「開始轉換」底部按鈕與「選擇我的機器人顏色」窗格的距離。

空間面板可輕鬆分隔空間。如要決定如何調整空間面板的行動版設計,請嘗試從最遠的表面開始移除表面,然後往前移動。看看可以移除多少背景,以及移除後會留下什麼。我們為 Androidify 進行這項練習後,最後保留了大型綠色 Android 塗鴉。這個波浪線不僅是品牌宣傳和背景,也是 3D 空間中內容的錨點。

建立這個錨點後,我們更容易想像元素如何圍繞錨點移動,以及如何運用鄰近性,突破並轉換其餘使用者體驗。

其他設計秘訣,協助應用程式支援空間音訊

  • 讓事物不受限制:將元件分開,並給予一些實際 (空間) 空間。現在該為這些 UI 元素預留一些空間了。
  • 移除表面:隱藏背景,看看對設計有何影響。
  • 運用動態效果吸引使用者:您在應用程式中如何使用轉場效果?想像一下應用程式以該字元為中心,在 VR 中展開。
  • 選擇錨點:確保使用者不會在空間中迷路。擁有可協助收集或接地 UI 的元素。

如要進一步瞭解 XR UI 設計模式,請參閱 Android Developers 上的「Android XR 設計」

空間 UI 基礎知識

我們已瞭解 Ivy 在為 XR 設計 Androidify 時,如何調整心態,現在來談談開發空間 UI。如果您習慣使用新式 Android 工具和程式庫,應該會覺得使用 Jetpack XR SDK 開發空間 UI 相當容易。您會發現許多熟悉的概念,例如使用 Compose 建立版面配置。事實上,空間版面配置與使用資料列、資料欄和間隔的 2D 版面配置非常相似:

spatialrows.png

這些元素會排列在 SpatialRowsSpatialColumns

這裡顯示的空間元素是 SpatialPanel 可組合函式,可讓您顯示文字、按鈕和影片等 2D 內容。

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

SpatialPanel 是子空間可組合項。子空間可組合函式必須包含在子空間內,並由 SubspaceModifier 物件修改。子空間可放置在應用程式 UI 階層中的任何位置,且只能包含子空間可組合項。SubspaceModifier 物件與 Modifier 物件也很相似,可控制大小和位置等參數。

Orbiter  可以附加至 SpatialPanel,並隨著附加的內容移動。通常用來提供所附加內容的脈絡控制項,讓內容成為主要焦點。可放置在內容的任一側,距離可自行設定。

orbiter.png
軌道器會附加至 SpatialPanel 的底部

還有許多空間 UI 元素,但這些是我們為 Androidify 建立空間版面配置時使用的主要元素。

開始開發 XR 應用程式

首先來設定專案。我們新增了 Jetpack XR Compose 依附元件,您可以在 Jetpack XR 依附元件頁面找到。

我們新增了按鈕的程式碼,可將使用者帶往全螢幕,首先是偵測執行這項操作的功能:

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

接著,我們在現有版面配置中新增按鈕元件,並使用「展開內容」圖示 ,並為按鈕指定 onClick 行為:

  @Composable

fun 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"),
       )
   }
}

現在點選該按鈕只會在全螢幕模式中顯示「中」版面配置。我們可以檢查空間功能,判斷是否能顯示空間 UI。如果可以,我們會改為顯示新的空間版面配置:

  @Composable

fun 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(...)
   }
}

實作主畫面設計

讓我們回到「全螢幕」中的主畫面空間設計,瞭解實作方式。

customize_3.png

我們在這裡識別出兩個 SpatialPanel 元素:一個是右側的影片資訊卡所在面板,另一個則包含主要 UI。最後,頂端還附有 Orbiter。先從影片播放器面板開始:

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

我們只是將一般版面配置中的 2D VideoPlayer 元件重複用於 SpatialPanel,完全不需要進行額外變更!獨立顯示時的外觀如下:

bluetiel.png

主要內容面板也遵循相同的故事:我們在 SpatialPanel 中重複使用中等面板內容。

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

我們為這個面板提供 ResizePolicy,讓面板邊緣附近出現一些控點,方便使用者調整面板大小。此外,它也具有 MovePolicy,可讓使用者拖曳。

customize_4.png

將兩者放在同一個 Subspace 中,可讓兩者彼此獨立,因此我們將 VideoPlayer 面板設為主要內容面板的子項。這樣一來,當主要內容面板透過父項和子項的關係拖曳時,VideoPlayer 面板就會移動。

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

這就是我們製作第一個畫面的方式!

繼續處理其他畫面

我還會簡要介紹其他畫面,並強調每個畫面需要考量的事項。

fullspace.png
全螢幕中的建立畫面

我們在這裡使用 SpatialRow 和 SpatialColumn 可組合函式,建立符合建議觀看空間的版面配置,再次重複使用中型版面配置的元件。

fullspace_2.png

全螢幕的結果畫面:機器人是根據提示詞生成,穿著紅色棒球帽、飛行員墨鏡、淺藍色 T 恤、紅白格紋短褲和綠色夾腳拖,並拿著網球拍。


結果畫面會以柔邊效果顯示免費的引文,讓引文在螢幕邊緣附近淡出。此外,查看所用輸入內容時,還會使用實際的 3D 轉場效果,在空間中翻轉圖片。

發布至 Google Play 商店

應用程式已準備好支援 XR 和空間版面配置,因此我們接著將其發布到 Play 商店。我們對應用程式的 AndroidManifest.xml 檔案進行了最後一項重要變更:

  <!-- Androidify can use XR features if they're available; they're not required. -->
<uses-feature android:name="android.software.xr.api.spatial" 
              android:required="false" />

這樣一來,Play 商店就會知道這個應用程式具有 XR 差異化功能,並顯示徽章,讓使用者知道這個應用程式是專為 XR 打造:

androidify2.png
Android XR 上的 Google Play 商店顯示的 Androidify


上傳版本時,我們不需要任何特殊步驟即可發布 XR 版本:系統會將相同的應用程式發布至行動裝置測試群組,以及 XR 裝置使用者!不過,您可以選擇新增應用程式的延展實境專屬螢幕截圖,甚至使用空間影片素材資源上傳應用程式的沉浸式預覽畫面。在 Android XR 裝置上,Play 商店會自動將這項資訊顯示為沉浸式 3D 預覽畫面,讓使用者在安裝應用程式前,體驗內容的深度和規模。

立即開始打造專屬體驗

Androidify 是絕佳範例,說明如何將現有的 2D Jetpack Compose 應用程式空間化。今天,我們展示了 Androidify 空間 UI 的完整開發流程,從設計到程式碼再到發布,無一不包。我們修改了現有設計,使其適用於空間範例,並使用 SpatialPanel 和 Orbiter 可組合函式建立空間版面配置,在使用者進入全螢幕時顯示,最後將新版應用程式發布到 Play 商店。

希望這篇網誌文章有助於您瞭解如何將自己的應用程式帶到 Android XR!以下提供幾個實用連結:

撰寫者:

繼續閱讀