Les éléments partagés rendent les transitions entre les écrans plus fluides et plus attrayantes en créant un lien visuel 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 suivant inclut les composables DetailsScreen et HomeScreen qui servent de destinations entre lesquelles les utilisateurs peuvent naviguer. Dans chaque écran, le modificateur sharedElement est utilisé à la fois sur l'image et sur le texte afin 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ément partagé avec Navigation 3, vous devez d'abord encapsuler le NavDisplay de votre application dans un SharedTransitionLayout. Vous pouvez ensuite transmettre le SharedTransitionScope fourni aux composables d'écran.
Pour AnimatedVisibilityScope, utilisez la composition locale LocalNavAnimatedContentScope qui fournit AnimatedContentScope à partir de 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ément partagé avec Navigation 2, vous devez d'abord encapsuler le NavHost de votre application dans un SharedTransitionLayout. Vous pouvez ensuite transmettre les SharedTransitionScope fournies 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 pour 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 de prévisualisation des gestes Retour dans les options pour les développeurs.
Si votre application cible Android 14 ou version antérieure, vous devez ajouter
android:enableOnBackInvokedCallback="true"aux éléments<application>ou<activity>spécifiques dans votre fichierAndroidManifest.xml. Vous n'avez pas besoin de cet indicateur si votre application cible Android 15 ou version ultérieure.<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application ... android:enableOnBackInvokedCallback="true"> </application> </manifest>