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.
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.
Our recommendation for using Fragments in Compose is documented here.
Specifically, you should use the AndroidViewBinding composable to inflate an XML containing a FragmentContainerView hosting the fragment you want to use in Compose. AndroidViewBinding has fragment-specific handling which is why you want to use this over AndroidView. Note that you need to have view binding enabled for this.
Example XML file:
<androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container_view"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:name="com.example.MyFragment" />
And then in your Composable function:
@Composable
fun FragmentInComposeExample() {
AndroidViewBinding(MyFragmentLayoutBinding::inflate) {
val myFragment = fragmentContainerView.getFragment<MyFragment>()
// ...
}
}
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.
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.
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>