The Android XR SDK is now available in Developer Preview. We want your feedback! Visit our
support page to reach out.
Develop UI for Android Views-based Apps
Stay organized with collections
Save and categorize content based on your preferences.
Try the Compose way
Jetpack Compose using the Jetpack XR SDK is the recommended UI toolkit for Android XR.
Using the Android Jetpack Compose framework is the best way to take
advantage of the latest advancements in Android UI development and to verify
that your application remains current with industry best practices.
However, if you haven't migrated, and are working to spatialize an Android
Views based app, there are a few approaches you can take.
Reuse your existing Views within SpatialPanels
While SpatialPanel
s are part of the Jetpack Compose for XR library, they
also accept Views. When using Subspace
in your MainActivity,
place an existing view into a SpatialPanel
as shown in the following
example.
setContent {
Subspace {
SpatialPanel(
modifier = SubspaceModifier.height(500.dp).width(500.dp).depth(25.dp)
) { MyCustomView(this@ActivityWithSubspaceContent) }
}
}
Use Android Views and Compose interoperability APIs
Consult guidance on interoperability between Views and Compose. This
documentation covers using these frameworks together and contains links to code
samples you can use.
Use a ComposeView to add spatial panels and orbiters to an existing fragment
Use a ComposeView
in your XML layout to add Composables and create new XR
content. Use View binding or findViewById
to find the
ComposeView
in the onCreateView()
function.
Read more about ComposeView
guidance.
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val view = inflater.inflate(R.layout.example_fragment, container, false)
view.findViewById<ComposeView>(R.id.compose_view).apply {
// Dispose of the Composition when the view's LifecycleOwner
// is destroyed
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
// In Compose world
SpatialPanel(SubspaceModifier.height(500.dp).width(500.dp)) {
Text("Spatial Panel with Orbiter")
}
}
}
return view
}
Work directly with the Jetpack SceneCore library
Compose for XR is built on top of Jetpack SceneCore. If you are
spatializing a Views based app, you may continue to use your existing UI code
within Compose for XR or choose to work directly with Jetpack SceneCore's
Session
instead.
You can build panels directly from SceneCore using PanelEntity
. Set the
size of the panel in meters using dimensions
, or in pixels using
pixelDimensions
. You can choose to make the panels movable or resizable
by using the corresponding components. For more information, see Add common
behavior to entities.
val panelContent = MyCustomView(this)
val panelEntity = PanelEntity.create(
session = xrSession,
view = panelContent,
pixelDimensions = IntSize2d(500, 500),
name = "panel entity"
)
Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
Last updated 2025-07-31 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-07-31 UTC."],[],[],null,["# Develop UI for Android Views-based Apps\n\nTry the Compose way \nJetpack Compose using the Jetpack XR SDK is the recommended UI toolkit for Android XR. \n[Develop with the Jetpack XR SDK →](/develop/xr/jetpack-xr-sdk) \n\n\u003cbr /\u003e\n\nUsing the [Android Jetpack Compose framework](/jetpack/compose) is the best way to take\nadvantage of the latest advancements in Android UI development and to verify\nthat your application remains current with industry best practices.\n\nHowever, if you haven't migrated, and are working to spatialize an [Android\nViews](/develop/ui/views/layout/declaring-layout) based app, there are a few approaches you can take.\n\nReuse your existing Views within SpatialPanels\n----------------------------------------------\n\nWhile [`SpatialPanel`s](/reference/kotlin/androidx/xr/compose/subspace/package-summary#SpatialPanel(androidx.xr.compose.subspace.layout.SubspaceModifier,androidx.xr.compose.subspace.layout.SpatialShape,kotlin.Function0)) are part of the Jetpack Compose for XR library, they\nalso accept Views. When using [`Subspace`](/reference/kotlin/androidx/xr/compose/spatial/package-summary#Subspace(kotlin.Function1)) in your MainActivity,\nplace an existing view into a [`SpatialPanel`](/reference/kotlin/androidx/xr/compose/subspace/package-summary#SpatialPanel(androidx.xr.compose.subspace.layout.SubspaceModifier,androidx.xr.compose.subspace.layout.SpatialShape,kotlin.Function0)) as shown in the following\nexample.\n\n\n```kotlin\nsetContent {\n Subspace {\n SpatialPanel(\n modifier = SubspaceModifier.height(500.dp).width(500.dp).depth(25.dp)\n ) { MyCustomView(this@ActivityWithSubspaceContent) }\n }\n}https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/xr/src/main/java/com/example/xr/compose/Views.kt#L48-L54\n```\n\n\u003cbr /\u003e\n\nUse Android Views and Compose interoperability APIs\n---------------------------------------------------\n\nConsult [guidance on interoperability between Views and Compose](/develop/ui/compose/migrate/interoperability-apis). This\ndocumentation covers using these frameworks together and contains links to code\nsamples you can use.\n\n### Use a ComposeView to add spatial panels and orbiters to an existing fragment\n\nUse a [`ComposeView`](/reference/kotlin/androidx/compose/ui/platform/ComposeView) in your XML layout to add Composables and create new XR\ncontent. Use [View binding](/topic/libraries/view-binding) or [`findViewById`](/reference/android/view/View#findViewById(int)) to find the\n[`ComposeView`](/reference/kotlin/androidx/compose/ui/platform/ComposeView) in the [`onCreateView()`](/reference/android/app/Fragment#onCreateView(android.view.LayoutInflater,%20android.view.ViewGroup,%20android.os.Bundle)) function.\n\n[Read more about `ComposeView` guidance](/develop/ui/compose/migrate/interoperability-apis/compose-in-views#compose-in-fragments).\n\n\n```kotlin\noverride fun onCreateView(\n inflater: LayoutInflater,\n container: ViewGroup?,\n savedInstanceState: Bundle?\n): View {\n val view = inflater.inflate(R.layout.example_fragment, container, false)\n view.findViewById\u003cComposeView\u003e(R.id.compose_view).apply {\n // Dispose of the Composition when the view's LifecycleOwner\n // is destroyed\n setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)\n setContent {\n // In Compose world\n SpatialPanel(SubspaceModifier.height(500.dp).width(500.dp)) {\n Text(\"Spatial Panel with Orbiter\")\n }\n }\n }\n return view\n}https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/xr/src/main/java/com/example/xr/compose/Views.kt#L61-L79\n```\n\n\u003cbr /\u003e\n\nWork directly with the Jetpack SceneCore library\n------------------------------------------------\n\n[Compose for XR](/develop/xr/jetpack-xr-sdk#jetpack-compose) is built on top of [Jetpack SceneCore](/develop/xr/jetpack-xr-sdk#jetpack-scenecore). If you are\nspatializing a Views based app, you may continue to use your existing UI code\nwithin Compose for XR or choose to work directly with Jetpack SceneCore's\n[`Session`](/reference/kotlin/androidx/xr/runtime/Session) instead.\n\nYou can build panels directly from SceneCore using [`PanelEntity`](/reference/kotlin/androidx/xr/scenecore/PanelEntity). Set the\nsize of the panel in meters using [`dimensions`](/reference/kotlin/androidx/xr/scenecore/PanelEntity#create(androidx.xr.runtime.Session,android.view.View,androidx.xr.runtime.math.FloatSize2d,kotlin.String,androidx.xr.runtime.math.Pose)), or in pixels using\n[`pixelDimensions`](/reference/kotlin/androidx/xr/scenecore/PanelEntity#create(androidx.xr.runtime.Session,android.view.View,androidx.xr.runtime.math.IntSize2d,kotlin.String,androidx.xr.runtime.math.Pose)). You can choose to make the panels movable or resizable\nby using the corresponding components. For more information, see [Add common\nbehavior to entities](/develop/xr/jetpack-xr-sdk/work-with-entities#add-common).\n\n\n```kotlin\nval panelContent = MyCustomView(this)\nval panelEntity = PanelEntity.create(\n session = xrSession,\n view = panelContent,\n pixelDimensions = IntSize2d(500, 500),\n name = \"panel entity\"\n)https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/xr/src/main/java/com/example/xr/compose/Views.kt#L85-L91\n```\n\n\u003cbr /\u003e"]]