Gemeinsame Elemente machen Übergänge zwischen Bildschirmen flüssiger und ansprechender, da sie eine visuelle Verbindung herstellen, die den Nutzer leitet. In diesem Leitfaden wird gezeigt, wie Sie die APIs für freigegebene Elemente sowohl mit der Jetpack-Bibliothek Navigation 3 als auch mit Navigation 2 verwenden.
Das folgende Snippet enthält die Composables DetailsScreen und HomeScreen, die als Ziele dienen, zwischen denen Nutzer wechseln können. Auf jedem Bildschirm wird der Modifikator sharedElement sowohl für das Bild als auch für den Text verwendet, sodass jedes dieser Elemente unabhängig voneinander zwischen den Bildschirmen animiert wird.
@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
Wenn Sie die APIs für freigegebene Elemente mit Navigation 3 verwenden möchten, müssen Sie zuerst das NavDisplay Ihrer App in ein SharedTransitionLayout einbinden. Anschließend kannst du das bereitgestellte SharedTransitionScope an die Composables des Bildschirms übergeben.
Verwenden Sie für AnimatedVisibilityScope das CompositionLocal LocalNavAnimatedContentScope, das die AnimatedContentScope aus der AnimatedContent bereitstellt, die NavDisplay intern für die Animation zwischen Szenen verwendet.
@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
Wenn Sie die APIs für freigegebene Elemente mit Navigation 2 verwenden möchten, müssen Sie zuerst das NavHost Ihrer App in ein SharedTransitionLayout einbinden. Anschließend können Sie die bereitgestellte SharedTransitionScope an die Composables des Bildschirms übergeben.
Der Parameter content des Builders composable verwendet AnimatedContentScope als Empfänger, sodass Sie mit this@composable auf diesen Bereich verweisen können.
@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() } ) } } } }
Intelligente „Zurück“-Geste mit freigegebenen Elementen
So verwenden Sie die intelligente „Zurück“-Geste mit freigegebenen Elementen:
Alle Versionen von Navigation 3 unterstützen die intelligente „Zurück“-Geste. Verwenden Sie für Navigation 2 die
2.8.0-alpha02-Version vonnavigation-composeoder höher:[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) }Animationen für die intelligente „Zurück“-Geste sind auf Geräten mit Android 15 (API-Level 35) oder höher standardmäßig aktiviert. Auf Geräten mit Android 14 (API-Level 34) müssen Sie in den Entwickleroptionen die Einstellung für die intelligente „Zurück“-Geste aktivieren.
Wenn Ihre App auf Android 14 oder niedriger ausgerichtet ist, müssen Sie
android:enableOnBackInvokedCallback="true"in der DateiAndroidManifest.xmldem Element<application>oder bestimmten<activity>-Elementen hinzufügen. Sie benötigen dieses Flag nicht, wenn Ihre App auf Android 15 oder höher ausgerichtet ist.<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application ... android:enableOnBackInvokedCallback="true"> </application> </manifest>