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

सीन डेकोरेटर की मदद से, ऐप्लिकेशन की सीन रणनीति के हिसाब से कैलकुलेट किए गए सीन में बदलाव किया जा सकता है. इनका इस्तेमाल, 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
        }
    }

}

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

    // ...

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

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

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

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

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

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

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

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

class CopyingScene<T : Any>(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 का इस्तेमाल करना चाहिए.

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

    // ...
}