Develop

Hybrid sample

Updated: May 8, 2026

Overview

This sample demonstrates how to build an application that seamlessly switches between a traditional 2D Android panel interface and an immersive VR environment while sharing the same Compose UI code.

Learning objectives

Complete this guide to learn how to:
  • Structure an app with separate 2D panel and immersive VR activities
  • Share a single Compose UI between 2D and immersive modes using composePanel
  • Switch from 2D to immersive mode using standard Android intents
  • Return from immersive to 2D mode using the extra_launch_in_home_pending_intent pattern
  • Register panels in immersive mode and position them using a GLXF scene

Requirements

  • Meta Quest device running Horizon OS
  • Android Studio with Spatial SDK configured
For detailed SDK versions, toolchain requirements, and setup steps, see the sample README.

Get started

Clone the Meta Spatial SDK Samples repository and open the HybridSample project in Android Studio. Build and deploy the app to your Quest device using the standard Android deployment workflow. The sample launches in 2D panel mode by default, where you can tap the button to switch to immersive VR mode.
For complete build instructions and troubleshooting, refer to the sample’s README.

Explore the sample

The sample consists of two activities that share a common UI component:
File / SceneWhat it demonstratesKey concepts
Standard Android 2D panel activity with shared HybridPanel composable
2D activity setup, launching immersive mode via intent
Immersive VR activity with panel registration and 3D scene
Panel registration, scene setup, returning to 2D mode
Activity declarations with 2D and VR intent categories
Dual-mode manifest configuration
Scene graph with panel placement
Spatial Editor scene authoring

Runtime behavior

When you launch the sample, you see a 2D Android panel displaying a themed interface with a Switch to immersive view button. Clicking the button transitions you into an immersive VR environment where you see the same UI rendered as a floating panel in 3D space, surrounded by a procedural skybox and environment. The panel now shows a Switch to 2D view button. Clicking it returns you to the traditional 2D panel interface.

Key concepts

Shared Compose UI across modes

The sample defines a single HybridPanel composable in PancakeActivity.kt that accepts buttonText and onButtonClick parameters. In 2D mode, the activity calls setContent { HybridPanel(...) } directly. In immersive mode, HybridSampleActivity.kt uses the same composable inside composePanel:
PanelRegistration(R.id.hybrid_panel) {
  config { /* dimensions, transparency */ }
  composePanel { setContent { HybridPanel(...) } }
}
This pattern eliminates UI duplication and ensures visual consistency. For more on panel registration, see 2D panel registration.

Switching from 2D to immersive

The sample switches from 2D to immersive mode using a standard Android intent. PancakeActivity creates an intent targeting HybridSampleActivity with ACTION_MAIN and FLAG_ACTIVITY_NEW_TASK, then calls startActivity(). See the onCreate() method in PancakeActivity.kt for the complete implementation.

Returning from immersive to 2D

Returning to 2D mode requires a more involved pattern. The launchPanelModeInHome() method in HybridSampleActivity.kt works in three steps:
  1. Creates an Intent targeting PancakeActivity with ACTION_MAIN and FLAG_ACTIVITY_NEW_TASK
  2. Wraps it in a PendingIntent with FLAG_UPDATE_CURRENT and FLAG_IMMUTABLE
  3. Sends a HOME intent (ACTION_MAIN + CATEGORY_HOME) with the PendingIntent attached as the extra_launch_in_home_pending_intent extra
This pattern ensures the 2D activity launches within the Horizon OS home environment rather than inside the immersive session.

Panel placement using GLXF scenes

The sample positions the immersive panel using a GLXF scene authored in Meta Spatial Editor. The scene contains a Panel node with a resource ID that matches the PanelRegistration ID. The registration uses R.id.hybrid_panel, which corresponds to the panel node in the scene file, and the Spatial SDK places the panel at the authored position and orientation.
For scene authoring workflows, see the Spatial Editor documentation.

Extend the sample

  • Modify the shared HybridPanel composable to add interactive elements like sliders or toggles, and observe how changes appear identically in both 2D and immersive modes.
  • Add a second panel in immersive mode to display additional UI elements positioned at a different location in the scene.
  • Replace the procedural skybox with a custom environment using the techniques shown in the EnvironmentsSample.