پیمایش با عناصر مشترک

شکل ۱. پیمایش با عناصر مشترک.

عناصر مشترک با ایجاد یک اتصال بصری که کاربر را راهنمایی می‌کند، انتقال بین صفحه‌ها را روان‌تر و جذاب‌تر می‌کنند. این راهنما نشان می‌دهد که چگونه از میاناهای برنامه‌سازی کاربردی عنصر مشترک با هر دو کتابخانه 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()
                    }
                )
            }
        }
    }
}

اشاره برگشت پیش‌گویانه با عناصر مشترک

برای استفاده از بازگشت پیش‌بینانه با عناصر مشترک، این مراحل را دنبال کنید:

  1. همه نسخه‌های 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)
    }
    
  2. پویانمایی‌های پیش‌بینی برگشت به‌طور پیش‌فرض در دستگاه‌های دارای Android 15 (سطح میانای برنامه‌سازی کاربردی ۳۵) یا بالاتر فعال است. برای دستگاه‌های دارای Android 14 (سطح میانای برنامه‌سازی کاربردی ۳۴)، باید تنظیم پیش‌بینی برگشت را در گزینه‌های توسعه‌دهندگان فعال کنید.

  3. اگر برنامه شما 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>
    
شکل ۲. عناصر هم‌رسانی‌شده با اشاره برگشت پیش‌گویانه.