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

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

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

برای استفاده از میاناهای برنامه‌سازی کاربردی عنصر مشترک با «پیمایش ۳»، ابتدا باید 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()
                        },
                    )
                }
            })
    }
}

برای استفاده از میاناهای برنامه‌سازی کاربردی عنصر هم‌رسانی‌شده با «پیمایش ۲»، ابتدا باید 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()
                    }
                )
            }
        }
    }
}

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

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

  1. همه نسخه‌های «پیمایش ۳» از «برگشت پیش‌گویانه» پشتیبانی می‌کنند. برای «پیمایش ۲»، از نسخه پخش 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>
    
شکل ۲. عناصر هم‌رسانی‌شده با اشاره برگشت پیش‌گویانه.