Reputation: 1669
I want to develop a single Activity multi fragments Apps using Jetpack Compose. For recyclerView, we have Vertical and HorizontalScroller. But, for fragments what should I use.
fun loadFragment(fragment: Fragment) {
val transaction:FragmentTransaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.f_container, fragment)
transaction.addToBackStack(null)
transaction.commit()
}
In this case, I don't have R.id.f_container because I'm creating UI using only compose.
<FrameLayout
android:id="@+id/f_container"
android:layout_width="match_parent"
android:layout_height="match_parent"`enter code here`
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout_constraintEnd_toEndOf="parent"
tools:layout_editor_absoluteY="-56dp">
</FrameLayout>
Upvotes: 22
Views: 17372
Reputation: 709
Probably late for the answer, just leaving it so others find it useful.
Since version 1.8.1, the Android development framework includes an AndroidFragment composable, which facilitates the integration of Fragments into Compose.
For more information, visit the AndroidFragment Release Notes.
Here is an example of how to use AndroidFragment:
@Composable
fun ExampleInteropScreen() {
AndroidFragment<ExampleFragment>(
modifier = Modifier
.fillMaxSize()
)
}
This composable allows developers to seamlessly use Fragments within a Compose UI, enhancing interoperability and expanding the capabilities of modern Android applications.
Upvotes: 3
Reputation: 611
You can create your own @Composable FragmentContainer function
@Composable
fun FragmentContainer(
modifier: Modifier = Modifier,
fragmentManager: FragmentManager,
commit: FragmentTransaction.(containerId: Int) -> Unit
) {
val containerId by rememberSaveable { mutableStateOf(View.generateViewId()) }
var initialized by rememberSaveable { mutableStateOf(false) }
AndroidView(
modifier = modifier,
factory = { context ->
FragmentContainerView(context)
.apply { id = containerId }
},
update = { view ->
if (!initialized) {
fragmentManager.commit { commit(view.id) }
initialized = true
} else {
fragmentManager.onContainerAvailable(view)
}
}
)
}
/** Access to package-private method in FragmentManager through reflection */
private fun FragmentManager.onContainerAvailable(view: FragmentContainerView) {
val method = FragmentManager::class.java.getDeclaredMethod(
"onContainerAvailable",
FragmentContainerView::class.java
)
method.isAccessible = true
method.invoke(this, view)
}
and then use it in activity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
FragmentContainer(
modifier = Modifier.fillMaxSize(),
fragmentManager = supportFragmentManager,
commit = { add(it, YourFragment()) }
)
}
}
or in fragment
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = ComposeView(requireContext()).apply {
setContent {
FragmentContainer(
modifier = Modifier.fillMaxSize(),
fragmentManager = parentFragmentManager,
commit = { add(it, YourNestedFragment()) }
)
}
}
Upvotes: 13
Reputation: 1160
I would not suggest you reuse an existing fragment, but instead, try to recycle its inner views to create a new composable.
Anyway if you want to have fun here is a possible solution:
AndroidView(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(),
factory = { context ->
FrameLayout(context).apply {
FragmentBlankBinding.inflate(LayoutInflater.from(context), this, true).root
}
})
Enjoy!
Upvotes: 4
Reputation: 1214
If you are creating a new app, you can skip using Fragments altogether and just use composable functions to represent your screens.
Upvotes: -2