Декораторы сцены позволяют изменять сцену, вычисленную стратегией сцены вашего приложения. По сути, они используются на втором этапе построения контента, отображаемого элементом NavDisplay .
Такой подход позволяет инкапсулировать определённую функциональность, например, отображение общих компонентов пользовательского интерфейса, в отдельные декораторы сцены.
Например, рассмотрим приложение для повышения производительности, имеющее три основных интерфейса: почтовый ящик, почтовый ящик личных сообщений и календарь. Такое приложение может использовать два декоратора сцены: один для добавления верхней панели приложения, отображающей информацию и элементы управления для текущего основного интерфейса, и другой для добавления постоянной панели навигации или направляющей для перемещения между интерфейсами.
Разработайте стратегию оформления сцены.
Декораторы сцен следуют аналогичной схеме, что и стратегии сцен. Для определения декоратора сцены необходимо реализовать интерфейс SceneDecoratorStrategy . Этот интерфейс имеет метод decorateScene , аналогичный методу calculateScene интерфейса SceneStrategy . 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 с помощью параметра 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 декорируемой сцены, встроенные анимации больше не будут выполняться, поскольку производный ключ не изменится.
Для сохранения встроенной поддержки анимации при оформлении сцен следует использовать ключ, производный от класса и key сцены, возвращаемого функцией calculateScene .
class DerivedKeyScene<T : Any>(scene: Scene<T>) : Scene<T> { override val key = scene::class to scene.key // ... }