Dekoratory scen pozwalają modyfikować scenę obliczoną przez strategię scen aplikacji. Służą one do drugiej fazy tworzenia
treści wyświetlanych przez NavDisplay.
Dzięki temu podejściu możesz enkapsulować określone funkcje, takie jak wyświetlanie typowych komponentów interfejsu, w poszczególnych dekoratorach scen.
Załóżmy na przykład, że masz aplikację zwiększającą produktywność, która ma 3 trasy najwyższego poziomu: skrzynkę odbiorczą e-maili, skrzynkę odbiorczą wiadomości bezpośrednich i widok kalendarza. Taka aplikacja może używać 2 dekoratorów scen: jednego do dodawania górnego paska aplikacji, który wyświetla informacje i elementy sterujące dla bieżącej trasy najwyższego poziomu, oraz drugiego do dodawania trwałego paska nawigacyjnego lub szyny do przechodzenia między trasami.
Tworzenie strategii dekoratora scen
Dekoratory scen są podobne do strategii scen. Aby zdefiniować dekorator scen, zaimplementuj interfejs SceneDecoratorStrategy. Ten interfejs
ma metodę decorateScene, która jest analogiczna do metody
calculateScene interfejsu SceneStrategy.
decorateScene określa, czy może dekorować scenę:
- Jeśli strategia dekoratora scen nie powinna dekorować sceny wejściowej, zwraca ją w niezmienionej postaci.
- Jeśli powinna dekorować scenę wejściową, zwraca nową
Scene. Zwrócona scena przyjmuje scenę wejściową jako parametr i wywołuje metodęcontentsceny wejściowej w swojej własnej metodziecontent.
Aby określić, czy i jak należy dekorować scenę wejściową, strategia dekoratora scen może uwzględniać metadane zarówno sceny wejściowej Scene, jak i zawartych w niej wpisów.
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() } }
Używanie strategii dekoratora scen
Aby używać strategii dekoratora scen, podaj je w NavDisplay za pomocą parametru sceneDecoratorStrategies. Podczas dekorowania scen NavDisplay wywołuje kolejno metodę decorateScene każdej strategii, przekazując wynik każdego wywołania jako dane wejściowe do następnego.
NavDisplay( // ... sceneDecoratorStrategies = listOf(firstSceneDecoratorStrategy, secondSceneDecoratorStrategy) )
Typowe wzorce dekoratorów scen
Podczas implementowania dekoratorów scen warto pamiętać o tych typowych wzorcach:
Kopiowanie właściwości
W wielu przypadkach scena zwracana przez dekorowanie sceny powinna zawierać te same wpisy i mieć te same poprzednie wpisy co scena, którą dekoruje. Ponadto powinna ona prawdopodobnie dziedziczyć (lub modyfikować) metadane sceny którą dekoruje, zamiast używać domyślnego zachowania. Poniższy kod pokazuje, jak to zrobić:
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 // ... }
MyScene<T>(...) :
Scene<T> by scene
Zachowywanie animacji
Jak opisano w artykule Animowanie przejść między miejscami docelowymi, NavDisplay automatycznie
animuje przejścia między scenami, gdy zmieni się klucz pochodzący z klasy
bieżącej sceny i jej właściwości key.
Podczas wprowadzania dekoratorów scen do aplikacji klasa sceny zwracanej
po dekorowaniu sceny może pozostać taka sama, nawet jeśli zmieni się klasa sceny
zwracanej podczas obliczania sceny. Gdy tak się stanie, a dekorowanie scen bezpośrednio kopiuje key sceny, którą dekoruje, wbudowane animacje nie będą już działać, ponieważ klucz pochodny nie ulegnie zmianie.
Aby zachować obsługę wbudowanych animacji, dekorowanie scen powinno używać klucza pochodzącego z klasy i key sceny zwracanej przez calculateScene.
data class DerivedKeyScene<T : Any>( val scene: Scene<T> ) : Scene<T> { override val key = scene::class to scene.key // ... }