Android : Compose Interoperability APIs

Chaitanya Reddy
3 min readOct 1, 2023

In this article, We’ll be discussing how to use compose and views together in the same project.

Using Views in Compose

To integrate existing android views into compose, Jetpack Compose provides the AndroidView component, which allows seamless integration of complex, custom, or third-party Android Views into your Compose-based UI without having to recreate them from scratch using Compose’s built-in components.

This will be also useful if you want to use UI elements that are not yet available in Compose like AdView..etc

To use View in compose, use AndroidView composable.

  • AndroidView is passed a lambda that returns a View
  • AndroidView provides an factory callback that is used to create the view
  • AndroidView provides an update callback that is called when the view is inflated
  • AndroidView takes a Modifier parameter that can be used to set padding, width, height…etc
AndroidView(
modifier = // pass modifier to adjust the position
factory = { context ->
// Create custom view
},
update = { view ->
// This will call once the view inflated
}
)

Note: We can only use custom view with this approach. If you want to embed xml layout in compose then we need to use AndroidViewBinding API

Using AndroidView in Lists

If you are using an AndroidView in a Lazy list (LazyColumn, LazyRow, Pager, etc.), consider using the AndroidView overload introduced in version 1.4.0-rc01 and later. This overload allows Compose to reuse the underlying View instance when the containing composition is reused as is the case for Lazy lists.

This overload of AndroidView adds 2 additional parameters:

  • onReset - A callback invoked to signal that the View is about to be reused. This must be non-null to enable View reuse.
  • onRelease (optional) - A callback invoked to signal that the View has exited the composition and will not be reused again.
@Composable
fun SampleComposeList() {
LazyColumn {
items(10) { index ->
AndroidView(
modifier = Modifier.fillMaxSize(), // Occupy the max size in the Compose UI
factory = { context ->
MyListView(context)
},
update = { view ->
view.selectedItem = index
},
onReset = { view ->
view.clear()
}
)
}
}
}

Using XML layout in Compose UI

To embed an XML layout, use the AndroidViewBinding API.

// layout file: main_layout.xml....viewbinding generated class MainLayoutBinding

@Composable
fun MainScreen() {
AndroidViewBinding(MainLayoutBinding::inflate) {
sampleView.setBackgroundColor(Color.BLACK)
}
}

To use this API, follow below setups

  • Add dependency: implementation "androidx.compose.ui:ui-viewbinding:<compose version>"
  • Enable view binding in build.gradle
android {
...
buildFeatures {
viewBinding = true
}
}

To add Fragment in Compose

we can use the AndroidViewBinding composable to add a Fragment in Compose

//Layout
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="<Add Fragment class>" />

@Composable
fun FragmentInComposeExample() {
AndroidViewBinding(MyFragmentLayoutBinding::inflate) {
val myFragment = fragmentContainerView.getFragment<MyFragment>()
// ...
}
}

Using Compose in Views

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

ComposeView API is an Android View

Using Compose in Activity

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

class ExampleActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContent { // In here, we can call composables!
MaterialTheme {
Greeting(name = "compose")
}
}
}
}

@Composable
fun Greeting(name: String) {
Text(text = "Hello $name!")
}

Using ComposeView in XML

  • Add ComposeView tag in xml
  • use setContent to set the ComposeView

// XML layout activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">

<androidx.compose.ui.platform.ComposeView
android:id="@+id/compose_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</LinearLayout>


// Activity
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

val composeView = findViewById<ComposeView>(R.id.compose_view)
// use the setContent to display Composable UI.
composeView.setContent {
// We then render a simple Text component from Compose.
Text(
text = "Hello Compose"
)
}
}
}

Using ComposeView without XML

To create ComposeView in Fragment or Activity directly in Code without adding in XML layout

class ExampleFragmentNoXml : Fragment() {

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

--

--

Chaitanya Reddy

Senior Engineer | Android | Jetpack Compose | Kotlin | Android AOSP | Multi Platform | Wear OS