サブスペースは、アプリ内の 3D 空間を区切ったパーティションです。これにより、3D モデルの配置、3D レイアウトの構築、2D コンテンツへの奥行き追加ができるようになります。サブスペースは、空間化が有効になっている場合にのみレンダリングされます。ホーム スペースまたは非 XR デバイスでは、そのサブスペース内のコードは無視されます。
SpatialPanel、SpatialRow、SpatialColumn などのサブスペース コンポーザブルを使用して、レイアウトを作成し、3D 空間に 2D コンテンツを配置できます。3D コンテンツを配置するには、3D モデルの場合は SceneCoreEntity、ステレオ画像の場合は SpatialExternalSurface など、適切な Subspace コンポーザブルを使用します。Orbiter や SpatialDialog などの一部の XR コンポーネントは、2D UI 階層のどこでも使用できる標準の 2D コンポーザブルですが、SubspaceComposable はアプリのサブスペースで呼び出す必要があります。これを行うには、Subspace サブスペース コンポーザブルを使用します。
サブスペース階層について
最上位の Subspace は、アプリによって呼び出される最も外側のサブスペースです。Subspace の呼び出しごとに、新しい独立した空間 UI 階層が作成されます。ネストされている親 Subspace の空間位置、向き、スケールは継承されません。
SpatialPanel、Orbiter、SpatialPopup などのコンポーネント内に埋め込みまたはネストされた Subspace を作成するには、PlanarEmbeddedSubspace を使用します。
PlanarEmbeddedSubspace と Subspace には、次の 2 つの主な違いがあります。
- それらは、呼び出された 2D レイアウトに参加します。つまり、サブスペースの高さと幅は、その 2D 親レイアウトの高さと幅によって制約されます。
- 呼び出されたエンティティの子として動作します。つまり、
SpatialPanel内にネストされたサブスペース コンポーザブルを呼び出すと、そのサブスペースは呼び出し元のSpatialPanelの子になります。
PlanarEmbeddedSubspace のこれらの動作により、次のような機能が実現します。
- 親エンティティとともに子を移動する
- オフセット
SubspaceModifierを使用して子の位置をオフセットする - 2D UI の上に浮かび、2D レイアウトの適切なスペースの高さと幅に一致する 3D オブジェクトを表示する
サブスペースのレイアウトを調整する
Android XR では、アプリのレイアウトはデフォルトでフルスペース モードの Subspace の VolumeConstraints にバインドされます。そのため、ユーザーが利用できる表示スペースの量を考慮し、それに応じてレイアウトを調整する必要があります。recommendedContentBoxInFullSpace は、ActivitySpace 内の境界ボックスの具体的な寸法を提供し、コンテンツをユーザーの視野内に配置できるようにします。
アプリの主要コンテンツはこのボックス内に収まるようにしてください。推奨される境界を超えるコンテンツがある場合は、ユーザーが頭を動かして空間を探索するようなレイアウトを検討してください。recommendedContentBoxInFullSpace のデフォルトの制約は、SubspaceModifier.requiredSizeIn などのカスタム サイズベースの修飾子を適用することでオーバーライドできます。無制限の動作の場合は、allowUnboundedSubspace = true を設定します。
必要に応じて、現在の Session を使用して recommendedContentBoxInFullSpace を呼び出し、これらの特定のディメンションを取得します。次の例をご覧ください。
val session = LocalSession.current session?.scene?.activitySpace?.recommendedContentBoxInFullSpace
アプリにサブスペースを追加する
次のコード例は、アプリに Subspace と PlanarEmbeddedSubspace を追加する方法を示しています。
setContent { // This is a top-level subspace Subspace { SpatialPanel { MyComposable() } } }
@Composable private fun MyComposable() { Row { PrimaryPane() SecondaryPane() } } @Composable private fun PrimaryPane() { // This is an embedded subspace, because PrimaryPane is in a SpatialPanel // and that SpatialPanel is in the top-level Subspace PlanarEmbeddedSubspace { SpatialPanel {} } }
詳細については、Subspace と PlanarEmbeddedSubspace の完全なリファレンス ドキュメントをご覧ください。