عناصر مشترک با ایجاد یک ارتباط بصری که کاربر را هدایت میکند، انتقال بین صفحات را روانتر و جذابتر میکنند. این راهنما نحوه استفاده از APIهای عناصر مشترک را با هر دو کتابخانه 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, ) ) } } } } }
ناوبری ۳
برای استفاده از APIهای عناصر مشترک با Navigation 3، ابتدا باید NavDisplay برنامه خود را در یک SharedTransitionLayout قرار دهید. سپس میتوانید SharedTransitionScope ارائه شده را به اجزای قابل ترکیب صفحه نمایش (screen composables) منتقل کنید.
برای 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() }, ) } }) } }
ناوبری ۲
برای استفاده از APIهای عناصر مشترک با Navigation 2، ابتدا باید NavHost برنامه خود را در یک SharedTransitionLayout قرار دهید. سپس میتوانید SharedTransitionScope ارائه شده را به اجزای قابل ترکیب صفحه نمایش (screen composables) منتقل کنید.
پارامتر content در سازندهی composable از AnimatedContentScope به عنوان گیرنده استفاده میکند، بنابراین میتوانید this@composable برای ارجاع به آن scope استفاده کنید.
@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) }انیمیشنهای پیشبینیکنندهی بازگشت به عقب به طور پیشفرض در دستگاههایی که اندروید ۱۵ (سطح API ۳۵) یا بالاتر را اجرا میکنند فعال هستند. برای دستگاههایی که اندروید ۱۴ (سطح API ۳۴) را اجرا میکنند، باید تنظیمات پیشبینیکنندهی بازگشت به عقب را در گزینههای توسعهدهنده فعال کنید.
اگر برنامه شما برای اندروید ۱۴ یا پایینتر طراحی شده است، باید
android:enableOnBackInvokedCallback="true"را به عناصر<application>یا<activity>خاص در فایلAndroidManifest.xmlخود اضافه کنید. اگر برنامه شما برای اندروید ۱۵ یا بالاتر طراحی شده است، به این پرچم نیازی ندارید.<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application ... android:enableOnBackInvokedCallback="true"> </application> </manifest>