Sahne dekoratörleri, uygulamanızın sahne stratejisi tarafından hesaplanan sahneyi değiştirmenize olanak tanır. Aslında, NavDisplay tarafından görüntülenen içeriği oluşturmanın ikinci aşaması için kullanılırlar.
Bu yaklaşım, ortak kullanıcı arayüzü bileşenlerini görüntüleme gibi belirli işlevleri ayrı sahne dekoratörlerinde kapsüllemenize olanak tanır.
Örneğin, üç üst düzey rotası olan bir üretkenlik uygulaması düşünün: e-posta gelen kutusu, doğrudan mesaj gelen kutusu ve takvim görünümü. Böyle bir uygulama, iki sahne dekoratörü kullanabilir. Bunlardan biri, mevcut üst düzey rota için bilgileri ve kontrolleri gösteren bir üst uygulama çubuğu eklemek, diğeri ise rotalar arasında gezinmek için kalıcı bir gezinme çubuğu veya gezinme sütunu eklemek için kullanılabilir.
Sahne dekoratörü stratejisi oluşturma
Sahne dekoratörleri, sahne stratejilerine benzer bir kalıp izler. Sahne dekoratörü tanımlamak için SceneDecoratorStrategy arayüzünü uygulayın. Bu arayüzde, SceneStrategy arayüzünün calculateScene yöntemine benzer bir decorateScene yöntemi vardır.
decorateScene, sahneyi süsleyip süsleyemeyeceğini belirler:
- Sahne dekoratörü stratejiniz giriş sahnesini dekore etmemeliyse giriş sahnesini olduğu gibi döndürür.
- Giriş sahnesini süslemesi gerekiyorsa yeni bir
Scenedöndürür. Genel olarak, döndürülen sahne giriş sahnesini parametre olarak alır ve kendicontentyöntemi içinde giriş sahnesinincontentyöntemini çağırır.
Sahne dekoratörü stratejiniz, giriş sahnesinin dekore edilip edilmeyeceğini ve nasıl dekore edileceğini belirlemek için hem giriş Scene hem de bu sahnedeki girişlerin meta verilerini dikkate alabilir.
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() } }
Sahne dekoratörü stratejilerini kullanma
Sahne dekoratörü stratejilerini kullanmak için
sceneDecoratorStrategies parametresini kullanarak bunları NavDisplay öğenize sağlayın. Sahneleri dekore ederken NavDisplay, her stratejinin decorateScene yöntemini sırayla çağırır ve her çağrının çıkışını bir sonrakinin girişi olarak iletir.
NavDisplay( // ... sceneDecoratorStrategies = listOf(firstSceneDecoratorStrategy, secondSceneDecoratorStrategy) )
Sahne dekoratörleri için yaygın kalıplar
Sahne dekoratörlerini uygularken dikkat edilmesi gereken bazı yaygın kalıplar şunlardır:
Özellikleri kopyala
Çoğu durumda, bir sahneyi süsleyerek döndürülen sahne, süslediği sahneyle aynı girişleri içermeli ve aynı önceki girişlere sahip olmalıdır. Ayrıca, varsayılan davranışı kullanmak yerine, süslediği sahnenin meta verilerini devralması (veya değiştirmesi) gerekir. Aşağıdaki kodda bunun nasıl yapılacağına dair bir örnek verilmiştir:
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 // ... }
Animasyonları koruma
Hedefler arasında animasyon oluşturma bölümünde ayrıntılı olarak açıklandığı gibi, NavDisplay, geçerli sahnenin sınıfından türetilen bir anahtar ve key özelliği değiştiğinde sahneler arasındaki geçişleri otomatik olarak canlandırır.
Uygulamanıza sahne dekoratörleri eklerken, sahne hesaplama sırasında döndürülen sahnenin sınıfı değişse bile sahne dekorasyonundan sonra döndürülen sahnenin sınıfı aynı kalabilir. Bu durumda ve dekorasyon sahneleri, dekore ettikleri sahnenin key değerini doğrudan kopyaladığında, türetilmiş anahtar değişmediği için yerleşik animasyonlar artık gerçekleşmez.
Yerleşik animasyon desteğini sürdürmek için dekorasyon sahneleri, sınıftan türetilen bir anahtar ve calculateScene tarafından döndürülen sahnenin key değerini kullanmalıdır.
data class DerivedKeyScene<T : Any>( val scene: Scene<T> ) : Scene<T> { override val key = scene::class to scene.key // ... }