Using Compose in Views

You can add Compose-based UI into an existing app that uses a View-based design.

To create a new, entirely Compose-based screen, have your activity call the setContent() method, and pass whatever composable functions you like.

classExampleActivity:ComponentActivity(){
overridefunonCreate(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContent{// In here, we can call composables!
MaterialTheme{
Greeting(name="compose")
}
}
}
}
@Composable
funGreeting(name:String){
Text(text="Hello $name!")
}

This code looks just like what you'd find in a Compose-only app.

ViewCompositionStrategy for ComposeView

ViewCompositionStrategy defines when the Composition should be disposed. The default, ViewCompositionStrategy.Default, disposes the Composition when the underlying ComposeView detaches from the window, unless it is part of a pooling container such as a RecyclerView. In a single-Activity Compose-only app, this default behavior is what you would want, however, if you are incrementally adding Compose in your codebase, this behavior may cause state loss in some scenarios.

To change the ViewCompositionStrategy, call the setViewCompositionStrategy() method and provide a different strategy.

The table below summarizes the different scenarios you can use ViewCompositionStrategy in:

ViewCompositionStrategy Description and Interop Scenario
DisposeOnDetachedFromWindow The Composition will be disposed when the underlying ComposeView is detached from the window. Has since been superseded by DisposeOnDetachedFromWindowOrReleasedFromPool.

Interop scenario:

* ComposeView whether it’s the sole element in the View hierarchy, or in the context of a mixed View/Compose screen (not in Fragment).
DisposeOnDetachedFromWindowOrReleasedFromPool (Default) Similar to DisposeOnDetachedFromWindow, when the Composition is not in a pooling container, such as a RecyclerView. If it is in a pooling container, it will dispose when either the pooling container itself detaches from the window, or when the item is being discarded (i.e. when the pool is full).

Interop scenario:

* ComposeView whether it's the sole element in the View hierarchy, or in the context of a mixed View/Compose screen (not in Fragment).
* ComposeView as an item in a pooling container such as RecyclerView.
DisposeOnLifecycleDestroyed The Composition will be disposed when the provided Lifecycle is destroyed.

Interop scenario

* ComposeView in a Fragment's View.
DisposeOnViewTreeLifecycleDestroyed The Composition will be disposed when the Lifecycle owned by the LifecycleOwner returned by ViewTreeLifecycleOwner.get of the next window the View is attached to is destroyed.

Interop scenario:

* ComposeView in a Fragment's View.
* ComposeView in a View wherein the Lifecycle is not known yet.

ComposeView in Fragments

If you want to incorporate Compose UI content in a fragment or an existing View layout, use ComposeView and call its setContent() method. ComposeView is an Android View.

You can put the ComposeView in your XML layout just like any other View:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<androidx.compose.ui.platform.ComposeView
android:id="@+id/compose_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

In the Kotlin source code, inflate the layout from the layout resource defined in XML. Then get the ComposeView using the XML ID, set a Composition strategy that works best for the host View, and call setContent() to use Compose.

classExampleFragmentXml:Fragment(){
overridefunonCreateView(
inflater:LayoutInflater,
container:ViewGroup?,
savedInstanceState:Bundle?
):View{
valview=inflater.inflate(R.layout.fragment_example,container,false)
valcomposeView=view.findViewById<ComposeView>(R.id.compose_view)
composeView.apply{
// Dispose of the Composition when the view's LifecycleOwner
// is destroyed
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent{
// In Compose world
MaterialTheme{
Text("Hello Compose!")
}
}
}
returnview
}
}

Alternatively, you can also use view binding to obtain references to the ComposeView by referencing the generated binding class for your XML layout file:

classExampleFragment:Fragment(){
privatevar_binding:FragmentExampleBinding? =null
// This property is only valid between onCreateView and onDestroyView.
privatevalbindingget()=_binding!!
overridefunonCreateView(
inflater:LayoutInflater,
container:ViewGroup?,
savedInstanceState:Bundle?
):View{
_binding=FragmentExampleBinding.inflate(inflater,container,false)
valview=binding.root
binding.composeView.apply{
// Dispose of the Composition when the view's LifecycleOwner
// is destroyed
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent{
// In Compose world
MaterialTheme{
Text("Hello Compose!")
}
}
}
returnview
}
overridefunonDestroyView(){
super.onDestroyView()
_binding=null
}
}

Two slightly different text elements, one above the other

Figure 1. This shows the output of the code that adds Compose elements in a View UI hierarchy. The "Hello Android!" text is displayed by a TextView widget. The "Hello Compose!" text is displayed by a Compose text element.

You can also include a ComposeView directly in a fragment if your full screen is built with Compose, which lets you avoid using an XML layout file entirely.

classExampleFragmentNoXml:Fragment(){
overridefunonCreateView(
inflater:LayoutInflater,
container:ViewGroup?,
savedInstanceState:Bundle?
):View{
returnComposeView(requireContext()).apply{
// Dispose of the Composition when the view's LifecycleOwner
// is destroyed
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent{
MaterialTheme{
// In Compose world
Text("Hello Compose!")
}
}
}
}
}

Multiple ComposeView instances in the same layout

If there are multiple ComposeView elements in the same layout, each one must have a unique ID for savedInstanceState to work.

classExampleFragmentMultipleComposeView:Fragment(){
overridefunonCreateView(
inflater:LayoutInflater,
container:ViewGroup?,
savedInstanceState:Bundle?
):View=LinearLayout(requireContext()).apply{
addView(
ComposeView(requireContext()).apply{
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
)
id=R.id.compose_view_x
// ...
}
)
addView(TextView(requireContext()))
addView(
ComposeView(requireContext()).apply{
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
)
id=R.id.compose_view_y
// ...
}
)
}
}

The ComposeView IDs are defined in the res/values/ids.xml file:

<resources>
<itemname="compose_view_x"type="id"/>
<itemname="compose_view_y"type="id"/>
</resources>

Preview composables in Layout Editor

You can also preview composables within the Layout Editor for your XML layout containing a ComposeView. Doing so lets you see how your composables look within a mixed Views and Compose layout.

Say you want to display the following composable in the Layout Editor. Note that composables annotated with @Preview are good candidates to preview in the Layout Editor.

@Preview
@Composable
funGreetingPreview(){
Greeting(name="Android")
}

To display this composable, use the tools:composableName tools attribute and set its value to the fully qualified name of the composable to preview in the layout.

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.compose.ui.platform.ComposeView
android:id="@+id/my_compose_view"
tools:composableName="com.example.compose.snippets.interop.InteroperabilityAPIsSnippetsKt.GreetingPreview"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</LinearLayout>

Composable displayed within layout editor

Next steps

Now that you know the interoperability APIs to use Compose in Views, learn how to use Views in Compose.

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年11月17日 UTC.