https://kotlinlang.org logo
#compose
Title
# compose
e

Ehsan Mehranberg

12/02/2021, 3:26 PM
Hello devs. I want to have shared element transition in a hybrid app where we have fragments and the fragment content is composable. I’ve created the following composable to have an
AndroidView
that wraps a
ComposeView
and the content of the
ComposeView
could be any composable
Copy code
@Composable
fun SharedElement(
    modifier: Modifier = Modifier,
    transitionTag: String,
    @IdRes viewId: Int,
    content: @Composable () -> Unit
) {
    AndroidView(
        modifier = modifier,
        factory = { context ->
            ComposeView(context).apply {
                transitionName = transitionTag
                id = viewId
                setContent {
                    content()
                }
            }
        }
    )
}
The problem is when the first fragment gets destroyed, the content of shared element gets decomposed as well and we can’t have a smooth transition between fragments. Ideally, shared composables should decompose when the element transition ends but I couldn’t find a way to do that. Any idea how this shared element transition can be nailed with composables and fragments?
i

Ian Lake

12/02/2021, 4:37 PM
Are you setting the correct
ViewCompositionStrategy
on your ComposeView? If so, your Composable wouldn't be disposed until the fragment transition completes https://developer.android.com/jetpack/compose/interop/interop-apis#compose-in-fragments
e

Ehsan Mehranberg

12/03/2021, 10:54 AM
@Ian Lake i set
DisposeOnViewTreeLifecycleDestroyed
but transition continues after view gets destroyed
i

Ian Lake

12/03/2021, 4:45 PM
That's not how Fragment Transition support works if you're using any version from the last few years - onDestroyView and the destruction of the view tree lifecycle only happens after the transition completes. What version of fragments / AppCompat are you using?
e

Ehsan Mehranberg

12/05/2021, 11:51 PM
@Ian Lake fragment version is 1.3.6 and appcompat is 1.3.0
i

Ian Lake

12/06/2021, 1:26 AM
Then your fragment's view does not get destroyed until your transition finishes
e

Ehsan Mehranberg

12/06/2021, 5:34 PM
I made a simple sample project. Would you mind check it if I’m doing something wrong? @Ian Lake thanks mate
i

Ian Lake

12/07/2021, 12:15 AM
Well, I see your Transition running on my API 28 device, so your ComposeView isn't being disposed too early or anything
If you want to see what is happening more closely, I bumped your duration to
3000
and added
modifier = Modifier.border(5.dp, Color.Red)
to the
Image
within the
ComposeView
of your
SharedElement
There's definitely something going on with the bounds/location on screen - if you enable debug logging, you might see the same thing I see in bounds:
Copy code
V/FragmentManager: >>>>> Beginning transition <<<<<
V/FragmentManager: >>>>> SharedElementFirstOutViews <<<<<
V/FragmentManager: View: androidx.compose.ui.platform.ComposeView{52fd18e V.E...... ........ 0,0-1050,1050 #7f080170 app:id/shared_element_1} Name: MyTag
V/FragmentManager: View: android.view.View{909adaf V.ED..... ........ 0,0-0,0} Name: null
V/FragmentManager: >>>>> SharedElementLastInViews <<<<<
V/FragmentManager: View: androidx.compose.ui.platform.ComposeView{6475bc V.E...... ........ 0,0-350,350 #7f080171 app:id/shared_element_2} Name: null
The fact that both views have an upper left corner of
0,0
seems rather suspicious - I would have expected your
Align.BottomEnd
ComposeView to be positioned, in a View sense, in the lower right, not the upper left corner
36 Views