Hi, I am using the new Shared Element Transition e...
# compose-android
n
Hi, I am using the new Shared Element Transition effect to navigate from cards in my homescreen to their corresponding screens. It works really nicely and I love the effect. Occasionally, though, on my device, when I return to the app, I get a white screen rather than my homescreen. I am a bit stumped as to what I might be doing wrong. I'll put my homescreen code in the chat.
Copy code
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun SharedTransitionScope.HomeScreen(
    modifier: Modifier = Modifier,
    onItemClick: (Int, String) -> Unit,
    animatedVisibilityScope: AnimatedVisibilityScope
) {
    Scaffold(
        topBar = { TopBar() },
    ) { innerPadding ->

        val listOfCardTitles = listOf("Art", "Books", "Music", "Cinema")
        val listOfImages =
            listOf(R.drawable.art, R.drawable.literature, R.drawable.music, R.drawable.cinema)

        Box(
            modifier = modifier
                .fillMaxSize()
                .padding(innerPadding)
        ) {
            Column(
                modifier = Modifier.fillMaxSize(),
                verticalArrangement = Arrangement.Center
            ) {
                listOfImages.forEachIndexed { index, resId ->
                    HomeCard(
                        modifier = Modifier
                            .padding(10.dp)
                            .weight(0.25f)
                            .clickable { onItemClick(resId, listOfCardTitles[index]) }
                            .sharedElement(
                                state = rememberSharedContentState(key = "image/$resId"),
                                animatedVisibilityScope = animatedVisibilityScope,
                                boundsTransform = { _, _ ->
                                    tween(durationMillis = 1000, easing = LinearOutSlowInEasing)
                                }
                            ),
                        title = listOfCardTitles[index],
                        image = listOfImages[index]
                    )
                }
            }
        }
    }
}
s
Nothing draws my attention here tbh, it looks fine? Can you consistently repro this issue? Perhaps you can file a bug report? Also this is complete guess-work, but can you try without having a Scaffold there? I think that one still introduces sub-composition, which perhaps is part of what is going wrong here? If it were me that's the first thing I'd try at least. Bonus that it looks like your Scaffold is only there to do
Copy code
Column {
  TopBar()
  Content()
}
anyway since you're not using snackbars or whatever.
n
Thanks for your reply. I haven't worked out how to consistently reproduce the issue; it seems random at this stage. I will try and remove the Scaffold and will come back if it does not solve it!
r
Can you show where your SharedTransitionLayout is created?
n
Yes, here it is:
Copy code
@OptIn(ExperimentalSharedTransitionApi::class)
@Composable
fun NavigationGraph(
    navController: NavHostController
) {

    SharedTransitionLayout {
        NavHost(
            navController = navController,
            startDestination = Screen.HomeScreen.route
        ) {
            composable(route = Screen.HomeScreen.route) {
                HomeScreen(
                    onItemClick = { resId, text ->
                        when (resId) {
                            2131099650 -> navController.navigate(Screen.ArtScreen.route + "/$resId/$text")
                            2131099660 -> navController.navigate(Screen.BooksScreen.route + "/$resId/$text")
                            2131099661 -> navController.navigate(Screen.MusicScreen.route + "/$resId/$text")
                            2131099651 -> navController.navigate(Screen.CinemaScreen.route + "/$resId/$text")
                        }
                    },
                    animatedVisibilityScope = this
                )
            }
            composable(route = Screen.ArtScreen.route + "/{resId}/{title}",
                arguments = listOf(
                    navArgument("resId") { type = NavType.IntType },
                    navArgument("title") { type = NavType.StringType }
                )
            ) {
                val resId = it.arguments?.getInt("resId") ?: 0
                val title = it.arguments?.getString("title") ?: ""
                ArtScreen(
                    resId = resId, title = title,
                    animatedVisibilityScope = this
                )
            }

            composable(route = Screen.BooksScreen.route + "/{resId}/{title}",
                arguments = listOf(
                    navArgument("resId") { type = NavType.IntType },
                    navArgument("title") { type = NavType.StringType }
                )
            ) {
                val resId = it.arguments?.getInt("resId") ?: 0
                val title = it.arguments?.getString("title") ?: ""
                BooksScreen(
                    resId = resId, title = title,
                    animatedVisibilityScope = this
                )
            }

            composable(route = Screen.MusicScreen.route + "/{resId}/{title}",
                arguments = listOf(
                    navArgument("resId") { type = NavType.IntType },
                    navArgument("title") { type = NavType.StringType }
                )
            ) {
                val resId = it.arguments?.getInt("resId") ?: 0
                val title = it.arguments?.getString("title") ?: ""
                MusicScreen(
                    resId = resId, title = title,
                    animatedVisibilityScope = this
                )
            }

            composable(route = Screen.CinemaScreen.route + "/{resId}/{title}",
                arguments = listOf(
                    navArgument("resId") { type = NavType.IntType },
                    navArgument("title") { type = NavType.StringType }
                )
            ) {
                val resId = it.arguments?.getInt("resId") ?: 0
                val title = it.arguments?.getString("title") ?: ""
                CinemaScreen(
                    resId = resId, title = title,
                    animatedVisibilityScope = this
                )
            }
        }
    }
}
r
On your NavHost, if you set enter and exit transitions to use fadeIn(alpha = 0.5f) and fadeOut(alpha = 0.5f), do you still see a blank screen? If not and the items are not blank, it could be similar to an issue that I was also seeing intermittently. 🤔 https://issuetracker.google.com/333675164
n
Thanks, I will try and keep you posted. 😊
Yes, it still happens with enter and exit transitions. I will now remove the Scaffold and try again.
Still happens with no Scaffold. 😭
sad panda 1
s
Are you on the latest version of the dependency that brings in shared element transitions? Just to rule out already fixed problems
n
I think so, I'm on composeAnimation = "1.7.0-beta02"
I tapped the white screen and the app crashed. The log says: java.lang.IllegalStateException: Recording currently in progress - missing #endRecording() call?
No idea what that means.
r
It'd be worth filing if you can extract a small sample from your project.
👍 1
It sounds different from the issue I saw
t
There's a few layers issues in beta 2 https://issuetracker.google.com/issues/343750859 if you have a repro you can post in that issue to help @Nader Jawad
🙏 1
l
I think it's related to GraphicsLayer too. Which API level are you having the issue on?
n
I'm on Android 14, API 34.