सीन डेकोरेटर की मदद से सीन में बदलाव करना

सीन डेकोरेटर की मदद से, ऐप्लिकेशन की सीन रणनीति से कैलकुलेट किए गए सीन में बदलाव किया जा सकता है. असल में, इनका इस्तेमाल NavDisplay पर दिखने वाले कॉन्टेंट को बनाने के दूसरे चरण में किया जाता है.

इस तरीके से, खास फ़ंक्शन को अलग-अलग सीन डेकोरेटर में शामिल किया जा सकता है. जैसे, सामान्य यूआई कॉम्पोनेंट दिखाना.

उदाहरण के लिए, समय की बचत करके काम करने वाले किसी ऐसे ऐप्लिकेशन के बारे में सोचें जिसमें तीन टॉप-लेवल रूट हैं: ईमेल इनबॉक्स, डायरेक्ट मैसेज इनबॉक्स, और कैलेंडर व्यू. इस तरह का ऐप्लिकेशन, दो सीन डेकोरेटर का इस्तेमाल कर सकता है. एक का इस्तेमाल, टॉप ऐप्लिकेशन बार जोड़ने के लिए किया जाता है. यह बार, मौजूदा टॉप-लेवल रूट के लिए जानकारी और कंट्रोल दिखाता है. वहीं, दूसरे का इस्तेमाल, लगातार दिखने वाला नेविगेशन बार या रेल जोड़ने के लिए किया जाता है, ताकि रूट के बीच नेविगेट किया जा सके.

सीन डेकोरेटर की रणनीति बनाना

सीन डेकोरेटर, सीन की रणनीतियों की तरह ही काम करते हैं. सीन डेकोरेटर तय करने के लिए, SceneDecoratorStrategy इंटरफ़ेस लागू करें. इस इंटरफ़ेस में एक तरीका है, decorateScene, जो SceneStrategy इंटरफ़ेस के calculateScene तरीके के जैसा है. decorateScene यह तय करता है कि सीन को डेकोरेट किया जा सकता है या नहीं:

  • अगर आपकी सीन डेकोरेटर रणनीति को इनपुट सीन को डेकोरेट नहीं करना चाहिए, तो यह इनपुट सीन को पहले जैसा ही दिखाती है.
  • अगर इसे इनपुट सीन को डेकोरेट करना चाहिए, तो यह एक नया Scene दिखाता है. आम तौर पर, लौटाया गया सीन, इनपुट सीन को पैरामीटर के तौर पर लेता है. साथ ही, अपने content मेथड में, इनपुट सीन के content मेथड को कॉल करता है.

इनपुट सीन को सजाने के लिए, आपकी सीन डेकोरेटर स्ट्रैटजी यह तय कर सकती है कि इनपुट Scene और उस सीन में मौजूद एंट्री, दोनों के मेटाडेटा का इस्तेमाल किया जाए या नहीं.

class MySceneDecoratorStrategy<T : Any> : SceneDecoratorStrategy<T> {


    override fun SceneDecoratorStrategyScope<T>.decorateScene(scene: Scene<T>): Scene<T> {
        // `shouldDecorate` determines if the scene should be decorated based on scene.metadata,
        // scene.entries.metadata, or any other relevant state.
        return if (shouldDecorate(scene)) {
            MyDecoratingScene(scene)
        } else {
            scene
        }
    }

}

data class MyDecoratingScene<T : Any>(
    val scene: Scene<T>
) : Scene<T> {

    // ...

    override val content = @Composable {
        scene.content()
    }
}

सीन डेकोरेटर की रणनीतियों का इस्तेमाल करना

सीन डेकोरेटर की रणनीतियों का इस्तेमाल करने के लिए, उन्हें NavDisplay पैरामीटर का इस्तेमाल करके, अपने NavDisplay में शामिल करें.sceneDecoratorStrategies सीन को सजाते समय, NavDisplay हर रणनीति के decorateScene तरीके को क्रम से कॉल करता है. साथ ही, हर कॉल के आउटपुट को अगले कॉल के इनपुट के तौर पर पास करता है.

NavDisplay(
    // ...
    sceneDecoratorStrategies = listOf(firstSceneDecoratorStrategy, secondSceneDecoratorStrategy)
)

सीन डेकोरेटर के सामान्य पैटर्न

सीन डेकोरेटर लागू करते समय, इन सामान्य पैटर्न के बारे में पता होना चाहिए:

प्रॉपर्टी कॉपी करना

कई मामलों में, सीन को डेकोरेट करने पर मिले सीन में वही एंट्री होनी चाहिए जो डेकोरेट किए जा रहे सीन में हैं. साथ ही, इसमें पिछली एंट्री भी वही होनी चाहिए. इसके अलावा, इसे डिफ़ॉल्ट व्यवहार का इस्तेमाल करने के बजाय, उस सीन के मेटाडेटा को इनहेरिट (या उसमें बदलाव) करना चाहिए जिसे यह सजा रहा है. नीचे दिए गए कोड में, ऐसा करने का एक उदाहरण दिखाया गया है:

data class CopyingScene<T : Any>(
    val scene: Scene<T>
) : Scene<T> {
    override val entries = scene.entries
    override val previousEntries = scene.previousEntries
    override val metadata = scene.metadata

    // ...
}

ऐनिमेशन बनाए रखना

एक डेस्टिनेशन से दूसरे डेस्टिनेशन के बीच ऐनिमेशन में दी गई जानकारी के मुताबिक, NavDisplay, मौजूदा सीन की क्लास और उसकी key प्रॉपर्टी से मिले किसी मुख्य कॉम्पोनेंट में बदलाव होने पर, सीन के बीच ट्रांज़िशन को अपने-आप ऐनिमेट करता है.

अपने ऐप्लिकेशन में सीन डेकोरेटर जोड़ने पर, सीन डेकोरेशन के बाद सीन की क्लास वही बनी रह सकती है. भले ही, सीन कैलकुलेशन के दौरान सीन की क्लास बदल गई हो. ऐसा होने पर, सीन को सजाने वाले ऑब्जेक्ट, सीन के key को सीधे तौर पर कॉपी करते हैं. इस वजह से, पहले से मौजूद ऐनिमेशन काम नहीं करते, क्योंकि डिराइव की गई कुंजी में बदलाव नहीं होता.

पहले से मौजूद ऐनिमेशन की सुविधा को बनाए रखने के लिए, डेकोरेटिंग सीन को क्लास से मिली कुंजी और calculateScene से मिले सीन के key का इस्तेमाल करना चाहिए.

data class DerivedKeyScene<T : Any>(
    val scene: Scene<T>
) : Scene<T> {
    override val key = scene::class to scene.key

    // ...
}