بین مقصدها متحرک شوید

NavDisplay قابلیت‌های انیمیشن داخلی را برای ایجاد انتقال‌های بصری روان هنگام پیمایش کاربران در برنامه شما فراهم می‌کند. می‌توانید این انیمیشن‌ها را به صورت سراسری برای NavDisplay یا در سطح Scene با استفاده از فراداده‌ها سفارشی کنید.

قابلیت‌های انیمیشن داخلی را درک کنید

NavDisplay از API ContentTransform برای تعریف نحوه‌ی انیمیشن محتوا در طول پیمایش استفاده می‌کند. NavDisplay به طور خودکار انتقال بین صحنه‌ها را هنگامی که یک کلید مشتق شده از کلاس صحنه‌ی فعلی و ویژگی key آن تغییر می‌کند، متحرک می‌کند. هنگامی که این کلید تغییر می‌کند، NavDisplay از ContentTransform برای نوع انتقال - به جلو، عقب یا پیش‌بینانه به عقب - از صحنه‌ی مناسب در انتقال استفاده می‌کند. اگر آن ContentTransform تعریف نشده باشد، NavDisplay به استفاده از انتقال پیش‌فرض مربوطه‌ی خود بازمی‌گردد.

نادیده گرفتن انتقال‌های پیش‌فرض

شما می‌توانید با ارائه پارامترهای انتقال به NavDisplay ، رفتارهای پیش‌فرض انیمیشن را لغو کنید.

  • transitionSpec : این پارامتر ContentTransform را تعریف می‌کند تا هنگام اضافه شدن محتوا به پشته پشتی (یعنی هنگام پیمایش به جلو) اعمال شود.
  • popTransitionSpec : این پارامتر ContentTransform را تعریف می‌کند تا هنگام حذف محتوا از پشته پشتی (یعنی هنگام پیمایش به عقب) اعمال شود.
  • predictivePopTransitionSpec : این پارامتر ContentTransform را تعریف می‌کند تا هنگام نمایش محتوا با استفاده از یک حرکت برگشت پیش‌بینی‌شده اعمال شود.

انتقال‌ها را در سطح Scene نادیده بگیرید

شما می‌توانید با استفاده از کلیدهای فراداده زیر که توسط NavDisplay تعریف شده‌اند، از فراداده‌ها برای تعریف انیمیشن‌های سفارشی برای صحنه‌های مجزا استفاده کنید:

در صورت ارائه، این انتقال‌های سطح صحنه به جای پیش‌فرض‌های مربوطه که در NavDisplay تنظیم شده‌اند، استفاده می‌شوند.

قطعه کد زیر هم انتقال‌های سراسری NavDisplay و هم یک override در سطح NavEntry منفرد را نشان می‌دهد:

@Serializable
data object ScreenA : NavKey

@Serializable
data object ScreenB : NavKey

@Serializable
data object ScreenC : NavKey

class AnimatedNavDisplayActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {

            Scaffold { paddingValues ->

                val backStack = rememberNavBackStack(ScreenA)

                NavDisplay(
                    backStack = backStack,
                    onBack = { backStack.removeLastOrNull() },
                    entryProvider = entryProvider {
                        entry<ScreenA> {
                            ContentOrange("This is Screen A") {
                                Button(onClick = { backStack.add(ScreenB) }) {
                                    Text("Go to Screen B")
                                }
                            }
                        }
                        entry<ScreenB> {
                            ContentMauve("This is Screen B") {
                                Button(onClick = { backStack.add(ScreenC) }) {
                                    Text("Go to Screen C")
                                }
                            }
                        }
                        entry<ScreenC>(
                            metadata = metadata {
                                put(NavDisplay.TransitionKey) {
                                    // Slide new content up, keeping the old content in place underneath
                                    slideInVertically(
                                        initialOffsetY = { it },
                                        animationSpec = tween(1000)
                                    ) togetherWith ExitTransition.KeepUntilTransitionsFinished
                                }
                                put(NavDisplay.PopTransitionKey) {
                                    // Slide old content down, revealing the new content in place underneath
                                    EnterTransition.None togetherWith
                                            slideOutVertically(
                                                targetOffsetY = { it },
                                                animationSpec = tween(1000)
                                            )
                                }
                                put(NavDisplay.PredictivePopTransitionKey) {
                                    // Slide old content down, revealing the new content in place underneath
                                    EnterTransition.None togetherWith
                                            slideOutVertically(
                                                targetOffsetY = { it },
                                                animationSpec = tween(1000)
                                            )
                                }
                            }
                        ) {
                            ContentGreen("This is Screen C")
                        }
                    },
                    transitionSpec = {
                        // Slide in from right when navigating forward
                        slideInHorizontally(initialOffsetX = { it }) togetherWith
                            slideOutHorizontally(targetOffsetX = { -it })
                    },
                    popTransitionSpec = {
                        // Slide in from left when navigating back
                        slideInHorizontally(initialOffsetX = { -it }) togetherWith
                            slideOutHorizontally(targetOffsetX = { it })
                    },
                    predictivePopTransitionSpec = {
                        // Slide in from left when navigating back
                        slideInHorizontally(initialOffsetX = { -it }) togetherWith
                            slideOutHorizontally(targetOffsetX = { it })
                    },
                    modifier = Modifier.padding(paddingValues)
                )
            }
        }
    }
}

شکل ۱. برنامه با انیمیشن‌های سفارشی.

ورودی‌های ناوبری انتقال بین صحنه‌ها

در برنامه‌هایی که با استفاده از sceneها طرح‌بندی‌های سفارشی ایجاد می‌کنند ، این امکان وجود دارد که یک NavEntry در طول یک گذار در ویژگی entries هر دو scene گنجانده شود. NavDisplay به صورت داخلی تأیید می‌کند که هر ورودی در هر زمان حداکثر در یک scene نمایش داده می‌شود، که می‌تواند منجر به گذارهای پرش‌دار هنگام رندر کردن یک NavEntry در صحنه شود. برای متحرک‌سازی روان ورودی‌ها بین sceneها، می‌توانید NavDisplay خود را در یک SharedTransitionLayout قرار دهید و SharedTransitionScope همانطور که در مثال زیر نشان داده شده است، به NavDisplay ارائه دهید:

SharedTransitionLayout {
    NavDisplay(
        // ...
        sharedTransitionScope = this
    )
}