عناصر مشترک با ایجاد یک اتصال بصری که کاربر را راهنمایی میکند، انتقال بین صفحهها را روانتر و جذابتر میکنند. این راهنما نشان میدهد که چگونه از میاناهای برنامهسازی کاربردی عنصر مشترک با هر دو کتابخانه Jetpack Navigation 3 و Navigation 2 استفاده کنید.
قطعه کد زیر شامل ترکیبپذیرهای DetailsScreen و HomeScreen است که
بهعنوان مقصدهایی عمل میکنند که کاربران میتوانند بین آنها پیمایش کنند. در هر صفحه،
از اصلاحکننده sharedElement هم روی تصویر و هم روی نوشتار استفاده میشود تا
هریک از این عناصر بهطور مستقل بین صفحهها پویانمایی شوند.
@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، ابتدا باید
NavDisplay برنامهتان را در SharedTransitionLayout قرار دهید. سپس میتوانید
SharedTransitionScope ارائهشده را به composableهای صفحه ارسال کنید.
برای AnimatedVisibilityScope، از ترکیببندی محلی
LocalNavAnimatedContentScope استفاده کنید که
AnimatedContentScope را از AnimatedContent ارائه میدهد که
NavDisplay بهطور داخلی برای پویانمایی بین صحنهها استفاده میکند.
@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، ابتدا باید
NavHost برنامهتان را در SharedTransitionLayout بپیچید. سپس میتوانید
SharedTransitionScope ارائهشده را به composable صفحه ارسال کنید.
پارامتر content از سازنده composable از
AnimatedContentScope بهعنوان گیرنده استفاده میکند، بنابراین میتوانید از this@composable برای
ارجاع به آن دامنه استفاده کنید.
@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() } ) } } } }
اشاره برگشت پیشگویانه با عناصر مشترک
برای استفاده از بازگشت پیشبینانه با عناصر مشترک، این مراحل را دنبال کنید:
همه نسخههای Navigation 3 از برگشت پیشبینانه پشتیبانی میکنند. برای Navigation 2، از نسخه
2.8.0-alpha02ازnavigation-composeیا جدیدتر استفاده کنید:[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) }پویانماییهای پیشبینی برگشت بهطور پیشفرض در دستگاههای دارای Android 15 (سطح میانای برنامهسازی کاربردی ۳۵) یا بالاتر فعال است. برای دستگاههای دارای Android 14 (سطح میانای برنامهسازی کاربردی ۳۴)، باید تنظیم پیشبینی برگشت را در گزینههای توسعهدهندگان فعال کنید.
اگر برنامه شما Android 14 یا نسخههای پایینتر را هدف قرار میدهد، باید
android:enableOnBackInvokedCallback="true"را به<application>یا عناصر خاص<activity>در فایلAndroidManifest.xmlخود اضافه کنید. اگر برنامه شما Android 15 یا بالاتر را هدف قرار میدهد، به این پرچم نیاز ندارید.<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application ... android:enableOnBackInvokedCallback="true"> </application> </manifest>