Les éléments partagés rendent les transitions entre les écrans plus fluides et plus attrayantes en créant une connexion visuelle qui guide l'utilisateur. Ce guide explique comment utiliser les API d'éléments partagés avec les bibliothèques Jetpack Navigation 3 et Navigation 2.
L'extrait de code suivant inclut les composables DetailsScreen et HomeScreen, qui servent de destinations entre lesquelles les utilisateurs peuvent naviguer. Dans chaque écran, le
sharedElement modificateur est utilisé à la fois sur l'image et sur le texte, de sorte que
chacun de ces éléments s'anime indépendamment entre les écrans.
@Composable fun DetailsScreen( id: Int, snack: Snack, sharedTransitionScope: SharedTransitionScope, animatedVisibilityScope: AnimatedVisibilityScope, onBackPressed: () -> Unit ) { with(sharedTransitionScope) { Column( modifier = Modifier .fillMaxSize() .clickable { onBackPressed() }, ) { Image( painterResource(id = snack.image), contentDescription = snack.description, contentScale = ContentScale.Crop, modifier = Modifier .sharedElement( sharedTransitionScope.rememberSharedContentState(key = "image-$id"), animatedVisibilityScope = animatedVisibilityScope ) .aspectRatio(1f) .fillMaxWidth() ) Text( text = snack.name, fontSize = 18.sp, modifier = Modifier .sharedElement( sharedTransitionScope.rememberSharedContentState(key = "text-$id"), animatedVisibilityScope = animatedVisibilityScope ) .fillMaxWidth(), ) } } } @Composable fun HomeScreen( sharedTransitionScope: SharedTransitionScope, animatedVisibilityScope: AnimatedVisibilityScope, onItemClick: (Int) -> Unit, ) { LazyColumn( modifier = Modifier .fillMaxSize() .padding(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { itemsIndexed(listSnacks) { index, item -> Row( modifier = Modifier .fillMaxWidth() .clickable { onItemClick(index) }, ) { Spacer(modifier = Modifier.width(8.dp)) with(sharedTransitionScope) { Image( painterResource(id = item.image), contentDescription = item.description, contentScale = ContentScale.Crop, modifier = Modifier .sharedElement( sharedTransitionScope.rememberSharedContentState(key = "image-$index"), animatedVisibilityScope = animatedVisibilityScope ) .size(100.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text( item.name, fontSize = 18.sp, modifier = Modifier .align(Alignment.CenterVertically) .sharedElement( sharedTransitionScope.rememberSharedContentState(key = "text-$index"), animatedVisibilityScope = animatedVisibilityScope, ) ) } } } } }
Navigation 3
Pour utiliser les API d'éléments partagés avec Navigation 3, vous devez d'abord encapsuler le
NavDisplay de votre application dans un SharedTransitionLayout. Vous pouvez ensuite transmettre le
fourni SharedTransitionScope aux composables d'écran.
Pour le AnimatedVisibilityScope, utilisez la
LocalNavAnimatedContentScope composition locale qui fournit le
AnimatedContentScope à partir du AnimatedContent que NavDisplay
utilise en interne pour animer les scènes.
@Composable fun SharedElement_Nav3() { SharedTransitionLayout { val backStack = rememberNavBackStack(HomeRoute) // Note: NavDisplay accepts a `sharedTransitionScope` parameter, which is used to animate // NavEntry instances between scenes. This parameter *isn't* required for shared element // or shared bounds transitioning elements between different NavEntry, as demonstrated in // this sample. // See https://developer.android.com/guide/navigation/navigation-3/animate-destinations#transition-nav-entries NavDisplay( modifier = Modifier.safeDrawingPadding(), backStack = backStack, entryProvider = entryProvider { entry<HomeRoute> { HomeScreen( sharedTransitionScope = this@SharedTransitionLayout, animatedVisibilityScope = LocalNavAnimatedContentScope.current, onItemClick = { backStack.add(DetailsRoute(it)) }) } entry<DetailsRoute> { detailsRoute -> val id = detailsRoute.item val snack = listSnacks[id] DetailsScreen( id = id, snack = snack, sharedTransitionScope = this@SharedTransitionLayout, animatedVisibilityScope = LocalNavAnimatedContentScope.current, onBackPressed = { backStack.removeLastOrNull() }, ) } }) } }
Navigation 2
Pour utiliser les API d'éléments partagés avec Navigation 2, vous devez d'abord encapsuler le
NavHost dans un SharedTransitionLayout. Vous pouvez ensuite transmettre le SharedTransitionScope fourni aux composables d'écran.
Le paramètre content du compilateur composable utilise
AnimatedContentScope comme récepteur. Vous pouvez donc utiliser this@composable pour
faire référence à cette portée.
@Composable fun SharedElement_Nav2() { SharedTransitionLayout { val navController = rememberNavController() NavHost( navController = navController, startDestination = "home", modifier = Modifier.safeDrawingPadding() ) { composable("home") { HomeScreen( sharedTransitionScope = this@SharedTransitionLayout, animatedVisibilityScope = this@composable, onItemClick = { navController.navigate("details/$it") }) } composable( "details/{item}", arguments = listOf(navArgument("item") { type = NavType.IntType }) ) { backStackEntry -> val id = backStackEntry.arguments?.getInt("item") ?: 0 val snack = listSnacks[id] DetailsScreen( id = id, snack = snack, sharedTransitionScope = this@SharedTransitionLayout, animatedVisibilityScope = this@composable, onBackPressed = { navController.popBackStack() } ) } } } }
Prévisualisation du Retour avec des éléments partagés
Pour utiliser la prévisualisation du Retour avec des éléments partagés, procédez comme suit :
Toutes les versions de Navigation 3 sont compatibles avec la prévisualisation du Retour. Pour Navigation 2, utilisez la version
2.8.0-alpha02denavigation-composeou une version ultérieure :[versions] androidx-navigation = "2.8.0-alpha02" # Or newer [libraries] androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" }dependencies { implementation(libs.androidx.navigation.compose) }Les animations de la prévisualisation du Retour sont activées par défaut sur les appareils équipés d'Android 15 (niveau d'API 35) ou version ultérieure. Pour les appareils équipés d'Android 14 (niveau d'API 34), vous devez activer le paramètre Prévisualisation du Retour dans les options pour les développeurs.
Si votre application cible Android 14 ou une version antérieure, vous devez ajouter
android:enableOnBackInvokedCallback="true"aux<application>ou éléments<activity>spécifiques de votre fichierAndroidManifest.xml. Cet indicateur n'est pas nécessaire si votre application cible Android 15 ou une version ultérieure.<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application ... android:enableOnBackInvokedCallback="true"> </application> </manifest>