Blog Infos
Author
Published
Topics
, , , ,
Author
Published

This article aims to provide an overview of the different APIs available for developers to integrate composables in Fragments and vice versa.

We will cover the following topics

  • Composable in XML-based Fragment
  • Full content of the fragment as Composable
  • Using Fragment in Compose-based UI — AndroidViewBinding
  • Using Fragment in Compose-based UI — AndroidViewFragment
  • Using Composables directly with Navigation library
Composable in XML-based Fragment
  • Layout file
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinator_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    

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

</androidx.coordinatorlayout.widget.CoordinatorLayout>
  • Accessing ComposeView from Kotlin-based Activity or Fragment
class FragmentWithComposable : Fragment() {

    
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val rootView: View = inflater.inflate(R.layout.fragment_with_composable, container, false)

        rootView.findViewById<ComposeView>(R.id.hello_compose_view).apply {
            setContent {
                YourAppTheme {
                        Text("Hello from Composable")
                    }
                }
        }
        return rootView
    }
}

You can also use viewBinding instead of findViewById

Multiple composables
  • When we want to use multiple composables, we must add an ID to each composable.
  • Define IDs in res/values/ids.xml file
<?xml version="1.0" encoding="utf-8"?>

<resources>
    <item name="compose_view_1" type="id" />
    <item name="compose_view_1" type="id" />
</resources>
class ExFragmentMultipleComposeView : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View = LinearLayout(requireContext()).apply {
        addView(
            ComposeView(requireContext()).apply {
                setViewCompositionStrategy(
                    ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
                )
                id = R.id.compose_view_1
                // ...
            }
        )
        addView(TextView(requireContext()))
        addView(
            ComposeView(requireContext()).apply {
                setViewCompositionStrategy(
                    ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
                )
                id = R.id.compose_view_1
                // ...
            }
        )
    }
}
Fragment with full Compose based UI — ComposeView
  1. Manually set the view composition strategy and then set the content
class BlankFragment : Fragment() {

     var uri: Uri? = null

    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
                    HomeScreen()
                }
            }
        }
    }

}
2. Fragment — content extension function

It’s available starting with version 1.7.0 of fragment via fragment-compose artifact

Add dependency to your project. Here is an example of using the Version catalog

fragmentKtx = "1.8.4"
androidx-fragment-compose = { module = "androidx.fragment:fragment-compose", version.ref = "fragmentKtx" }
  • In your module’s build.gradle file
implementation(libs.androidx.fragment.compose)
  • Code of content function
fun Fragment.content(content: @Composable () -> Unit): ComposeView {
    return ComposeView(requireContext()).apply {
        setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
        setContent(content)
    }
}

As you can see it handles the setting of view composition strategy and it takes content as Composable and call setContent internally for us.

class FragmentWithContentExt : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View = content {
        Column(modifier = Modifier
            .fillMaxSize()
            .systemBarsPadding()) {
            Text("Hello World")
        }
    }
}
Fragment in Compose-based UI — AndroidViewBinding
  • Fragment code
class BlankFragment : Fragment() {

     var uri: Uri? = null

    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
                    HomeScreen()
                }
            }
        }
    }

}
  • Layout file — FragmentContainerView
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container_view"
        android:name="com.example.compose.BlankFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
  • Composable AndroidViewBinding code
@Composable
fun FragmentUsingViewBindingInCompose(modifier: Modifier = Modifier) {
    AndroidViewBinding(FragmentContainerBinding::inflate, modifier){
        val blankFragment = fragmentContainerView.getFragment<BlankFragment>()
        blankFragment.uri = Uri.parse("https://developer.android.com")
    }
}

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

, ,

Kobweb:Creating websites in Kotlin leveraging Compose HTML

Kobweb is a Kotlin web framework that aims to make web development enjoyable by building on top of Compose HTML and drawing inspiration from Jetpack Compose.
Watch Video

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author of Kobweb

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author o ...

Kobweb:Creating websites in Kotlin leveraging Compose HTML

David Herman
Ex-Googler, author of Kob ...

Jobs

Fragment in compose-based UI — AndroidFragment

AndroidFragment has been available since version 1.8.0 via fragment-compose artifact

  • Composable code
@Composable
fun FragmentUsingAndroidFragmentInCompose(modifier: Modifier = Modifier) {
    AndroidFragment<BlankFragment> { blankFragment ->
        blankFragment.uri = Uri.parse("https://developer.android.com")
    }
}
Navigation Fragment Composable

Starting with version 2.8.0 we get support for adding composable directly into XML-based nav-graphs via navigation-fragment-compose

2 important steps that must be implemented to use this API

  1. Each composable destination must be a top-level, no argument @Composable method
  2. A fully qualified name is used as the android:name attribute for each destination

💡Tip: for the file name you can use @file:JvmName annotation for better/custom naming — By default, Kotlin uses the file name and appends Kt

com.example.compose.HomeScreenKt$HomeScreen
@file:JvmName("HelloScreenComposableDestination")

package com.example.compose

import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import com.example.compose.theme.YourTheme


@Composable
fun HomeScreen() {
    Text("Hello")
}

@Preview
@Composable
private fun PreviewHomeComposable() {
    YourTheme {
        HomeScreen()
    }
}
  • Nav graph with composableas destination
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@+id/nav_fragmentWithContentExt">
    <fragment
        android:id="@+id/nav_fragmentWithContentExt"
        android:name="com.example.compose.FragmentWithContentExt"
        android:label="FragmentWithContentExt" />
    <composable
        android:id="@+id/nav_homeComposable"
        android:name="com.example.compose.HomeScreenKt$HomeScreen"
        />


</navigation>
  • Navigating to the destination using its ID
findNavController().navigate(R.id.nav_homeComposable)
Stay in touch

https://www.linkedin.com/in/navczydev/

 

https://github.com/navczydev?source=post_page—–a9a8efee0040——————————–

https://x.com/navczydev?source=post_page—–a9a8efee0040——————————–

This article is previously published on proandroiddev.com

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
In this part of our series on introducing Jetpack Compose into an existing project,…
READ MORE
blog
In the world of Jetpack Compose, where designing reusable and customizable UI components is…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE
Menu