تساهم العناصر المشترَكة في جعل عمليات الانتقال بين الشاشات أكثر سلاسة وجاذبية من خلال إنشاء رابط مرئي يرشد المستخدم. يوضّح هذا الدليل كيفية استخدام واجهات برمجة التطبيقات للعناصر المشترَكة مع كلٍّ من مكتبتَي Navigation 3 وNavigation 2 من Jetpack.
يتضمّن المقتطف التالي الدالتَين المركّبتَين 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
لاستخدام واجهات برمجة التطبيقات الخاصة بالعناصر المشترَكة مع الإصدار 3 من Navigation، عليك أولاً تضمين NavDisplay في تطبيقك ضمن SharedTransitionLayout. يمكنك بعد ذلك تمرير SharedTransitionScope المقدَّم إلى عناصر واجهة المستخدم القابلة للإنشاء على الشاشة.
بالنسبة إلى 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() }, ) } }) } }
شريط التنقّل 2
لاستخدام واجهات برمجة التطبيقات للعناصر المشترَكة مع Navigation 2، عليك أولاً تضمين NavHost في تطبيقك ضمن SharedTransitionLayout. يمكنك بعد ذلك تمرير
SharedTransitionScope إلى عناصر واجهة المستخدم القابلة للإنشاء الخاصة بالشاشة.
تستخدِم المَعلمة 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) }يتم تفعيل الرسوم المتحركة الخاصة بميزة "إيماءة إظهار شاشة الرجوع" تلقائيًا على الأجهزة التي تعمل بالإصدار 15 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 35) أو الإصدارات الأحدث. بالنسبة إلى الأجهزة التي تعمل بالإصدار 14 من Android (المستوى 34 لواجهة برمجة التطبيقات)، عليك تفعيل إعداد "إيماءة إظهار شاشة الرجوع" في خيارات المطوّرين.
إذا كان تطبيقك يستهدف الإصدار 14 من نظام التشغيل Android أو الإصدارات الأقدم، عليك إضافة
android:enableOnBackInvokedCallback="true"إلى<application>أو عناصر<activity>معيّنة في ملفAndroidManifest.xml. لا تحتاج إلى هذه العلامة إذا كان تطبيقك يستهدف الإصدار 15 من نظام التشغيل Android أو الإصدارات الأحدث.<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application ... android:enableOnBackInvokedCallback="true"> </application> </manifest>