'How to add existing fragment from inside Compose

I want to open an existing fragment from compose or if i can add inside the same compose in full screen, that will also work. Also how to navigate from one existing fragment to another existing fragment from compose.



Solution 1:[1]

In order to work with your existing xml views and fragments, in a Jetpack Compose app, you can refer to Interoperability APIs.
Specifically, I understand that you want to manage Android Views in Compose.

I want to open an existing fragment from compose

@Composable
fun CustomView() {

    AndroidView(
        factory = { context ->
            MyView(context).apply {
                // myView listeners
            }
        },
        update = { view ->
            // Recomposition logics
        }
    )
}

..how to navigate from one existing fragment to another existing fragment from compose.

In the above example you now have a composable function, so just use Jetpack Compose navigation library.

Solution 2:[2]

I solved this as following:

@Composable
fun ReusableFragmentComponent(
    someArgumentForFragment: FragmentArgument,
    fragmentManager: FragmentManager,
    modifier: Modifier = Modifier,
    tag: String = "ReusableFragmentTag"
) {
    AndroidView(
        modifier = modifier,
        factory = { context ->
            FrameLayout(context).apply {
                id = ViewCompat.generateViewId()
            }
        },
        update = {
            val fragmentAlreadyAdded = fragmentManager.findFragmentByTag(tag) != null

            if (!fragmentAlreadyAdded) {
                fragmentManager.commit {
                    add(it.id, ReusableFragment.newInstance(someArgumentForFragment), tag)
                }
            }
        }
    )
}

In my case I called this from a fragment (hosted by navigation component), in an effort to make our reusable fragments compose compatible. I did that like so:

class ReusableFragments : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        return ComposeView(requireContext()).apply {
            setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
            setContent {
                Column {
                    Text("ReusableFragment 1")
                    ReusableFragmentComponent(someArgument1, childFragmentManager, tag = "ReusableFragmentTag1")

                    Text("ReusableFragment 2")
                    ReusableFragmentComponent(someArgument2, childFragmentManager, tag = "ReusableFragmentTag2")
                }
            }
        }
    }

}

By making the tag customizable it's possible to add multiple different instances of the same fragment to the same fragment manager.

Solution 3:[3]

This helped me:

@Composable
fun MyFragmentView(
    fragmentManager: FragmentManager,
    modifier: Modifier = Modifier
) {
    AndroidView(
        modifier = modifier.fillMaxSize(),
        factory = { context ->
            val containerId = R.id.container // some unique id
            val fragmentContainerView = FragmentContainerView(context).apply {
                id = containerId
            }

            val fragment = MyFragment()
            fragmentManager.beginTransaction()
                .replace(containerId, fragment, fragment.javaClass.simpleName)
                .commitAllowingStateLoss()

            fragmentContainerView
        }
    )
}

ids.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="container" type="id"/>
</resources>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Stefano Sansone
Solution 2 Hylke
Solution 3