দুটি গন্তব্যের মধ্যে অ্যানিমেশন তৈরি করা

NavDisplay-এ বিল্ট-ইন অ্যানিমেশন ক্ষমতা আছে যা ব্যবহারকারীরা আপনার অ্যাপ নেভিগেট করার সময় মসৃণ ভিজ্যুয়াল ট্রানজিশন তৈরি করে। আপনি মেটাডেটা ব্যবহার করে NavDisplay-এর জন্য অথবা Scene লেভেলে এই অ্যানিমেশনগুলি গ্লোবালি কাস্টমাইজ করতে পারবেন।

বিল্ট-ইন অ্যানিমেশন ক্ষমতা সম্পর্কে বোঝা

নেভিগেশনের সময় কন্টেন্ট কীভাবে অ্যানিমেট করবে তা নির্ধারণ করতে NavDisplay ContentTransform API ব্যবহার করে। বর্তমান দৃশ্যের ক্লাস ও এর key প্রপার্টি থেকে প্রাপ্ত কী পরিবর্তন হলে, NavDisplay অটোমেটিক দৃশ্যগুলির মধ্যে ট্রানজিশন অ্যানিমেট করে। এই কী পরিবর্তন হলে, NavDisplay ট্রানজিশনের ধরন—ফরোয়ার্ড, ব্যাক বা প্রেডিক্টিভ ব্যাক—এর জন্য ContentTransform ট্রানজিশনের উপযুক্ত সিন থেকে ব্যবহার করে। ContentTransform সেটি নির্দিষ্ট করা না থাকলে, NavDisplay এর সংশ্লিষ্ট ডিফল্ট ট্রানজিশন ব্যবহার করে।

ডিফল্ট ট্রানজিশন ওভাররাইড করা

NavDisplay-এ ট্রানজিশন প্যারামিটার প্রদান করে আপনি ডিফল্ট অ্যানিমেশন আচরণ ওভাররাইড করতে পারবেন।

  • transitionSpec: এই প্যারামিটারটি ব্যাক স্ট্যাকে কন্টেন্ট যোগ করা হলে (অর্থাৎ, সামনের দিকে নেভিগেট করার সময়) ContentTransform প্রয়োগ করার জন্য নির্ধারণ করে।
  • popTransitionSpec: ব্যাক স্ট্যাক থেকে কন্টেন্ট সরিয়ে দেওয়া হলে (অর্থাৎ, নেভিগেট করে ফিরে এলে) এই প্যারামিটার ContentTransform প্রয়োগ করার কথা বলে।
  • predictivePopTransitionSpec: এই প্যারামিটারটি ContentTransform নির্ধারণ করে যা কন্টেন্ট পপ করার সময় প্রয়োগ করা হয়, এটি একটি পূর্বাভাসমূলক ব্যাক জেসচার।

Scene লেভেলে ট্রানজিশন ওভাররাইড করা

NavDisplay-এর দ্বারা সংজ্ঞায়িত নিম্নলিখিত মেটাডেটা কী ব্যবহার করে আপনি স্বতন্ত্র দৃশ্যের জন্য কাস্টম অ্যানিমেশন সংজ্ঞায়িত করতে মেটাডেটা ব্যবহার করতে পারেন:

প্রদান করা হলে, NavDisplay-এ সেট করা সংশ্লিষ্ট ডিফল্টের পরিবর্তে এই সিন-লেভেল ট্রানজিশন ব্যবহার করা হয়।

নিম্নলিখিত স্নিপেটে গ্লোবাল NavDisplay ট্রানজিশন ও স্বতন্ত্র 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)
                )
            }
        }
    }
}

ছবি ১. কাস্টম অ্যানিমেশন সহ অ্যাপ।

দুটি দৃশ্যের মধ্যে নেভিগেশন এন্ট্রি ট্রানজিশন করা

সিন ব্যবহার করে কাস্টম লেআউট তৈরি করে এমন অ্যাপে, ট্রানজিশনের সময় NavEntry দু'টি সিনের entries প্রপার্টিতে অন্তর্ভুক্ত থাকতে পারে। ইন্টার্নালি, NavDisplay যাচাই করে যে প্রতিটি এন্ট্রি যেকোনও সময় সর্বাধিক একটি সিনে দেখানো হয়েছে কিনা, যা NavEntry রেন্ডার করা সিন পরিবর্তন হলে জাম্পি ট্রানজিশনের কারণ হতে পারে। সিনগুলির মধ্যে মসৃণভাবে এন্ট্রি অ্যানিমেট করতে, আপনি NavDisplay-কে SharedTransitionLayout-এর মধ্যে র‍্যাপ করতে পারেন এবং NavDisplay-কে SharedTransitionScope প্রদান করতে পারেন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

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

ছবি ২। SharedTransitionScope থেকে NavDisplay-এ পাস না করলে ট্রানজিশন জাম্প করে।
ছবি ৩। SharedTransitionScope থেকে NavDisplay-এ যাওয়ার সময় সাবলীল ট্রানজিশন।