Mit Szenendekoratoren können Sie die Szene ändern, die von der Szenenstrategie Ihrer App berechnet wird. Sie werden für eine zweite Phase der Erstellung des Inhalts verwendet, der von einem NavDisplay angezeigt wird.
Mit diesem Ansatz können Sie bestimmte Funktionen, z. B. die Anzeige gängiger UI-Komponenten, in einzelnen Szenendekoratoren kapseln.
Angenommen, Sie haben eine Produktivitäts-App mit drei Routen auf oberster Ebene: einen E‑Mail-Posteingang, einen Posteingang für Direktnachrichten und eine Kalenderansicht. Eine solche App könnte zwei Szenendekoratoren verwenden: einen zum Hinzufügen einer oberen App-Leiste, die Informationen und Steuerelemente für die aktuelle Route auf oberster Ebene anzeigt, und einen weiteren zum Hinzufügen einer dauerhaften Navigationsleiste oder -leiste, um zwischen den Routen zu navigieren.
Strategie für Szenendekorateur erstellen
Szenendekoratoren folgen einem ähnlichen Muster wie Szenenstrategien. Wenn Sie einen Szenendekorator definieren möchten, implementieren Sie die Schnittstelle SceneDecoratorStrategy. Diese Schnittstelle hat eine Methode, decorateScene, die analog zur Methode calculateScene der Schnittstelle SceneStrategy ist.
decorateScene bestimmt, ob die Szene dekoriert werden kann:
- Wenn die Eingabeszene nicht mit der SceneDecorator-Strategie dekoriert werden soll, wird die Eingabeszene unverändert zurückgegeben.
- Wenn die Eingabeszene dekoriert werden sollte, wird ein neues
Scenezurückgegeben. Im Allgemeinen verwendet die zurückgegebene Szene die Eingabeszene als Parameter und ruft die Methodecontentder Eingabeszene innerhalb ihrer eigenen Methodecontentauf.
Um festzustellen, ob und wie die Eingabeszene dekoriert werden soll, kann Ihre Szenendekorationsstrategie die Metadaten sowohl der Eingabe-Scene als auch der in dieser Szene enthaltenen Einträge berücksichtigen.
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() } }
Strategien für Szenendekoratoren verwenden
Wenn Sie Strategien für Szenendekoratoren verwenden möchten, geben Sie sie mit dem Parameter sceneDecoratorStrategies an Ihre NavDisplay weiter. Beim Dekorieren von Szenen ruft NavDisplay die Methode decorateScene jeder Strategie nacheinander auf und übergibt die Ausgabe jedes Aufrufs als Eingabe an den nächsten.
NavDisplay( // ... sceneDecoratorStrategies = listOf(firstSceneDecoratorStrategy, secondSceneDecoratorStrategy) )
Gängige Muster für Szenendekoratoren
Bei der Implementierung von Szenendekoratoren sollten Sie die folgenden gängigen Muster beachten:
Eigenschaften kopieren
In vielen Fällen sollte die Szene, die durch das Dekorieren einer Szene zurückgegeben wird, dieselben Einträge und dieselben vorherigen Einträge wie die dekorierte Szene enthalten. Außerdem sollte sie wahrscheinlich die Metadaten der Szene, die sie dekoriert, übernehmen (oder ändern), anstatt das Standardverhalten zu verwenden. Der folgende Code zeigt ein Beispiel dafür:
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 // ... }
Animationen beibehalten
Wie unter Animationen zwischen Zielen beschrieben, animiert NavDisplay automatisch Übergänge zwischen Szenen, wenn sich ein Schlüssel ändert, der von der Klasse der aktuellen Szene und ihrer key-Property abgeleitet ist.
Wenn Sie Szenendekoratoren in Ihrer App einführen, kann die Klasse der Szene, die nach der Szenendekoration zurückgegeben wird, gleich bleiben, auch wenn sich die Klasse der Szene, die während der Szenenberechnung zurückgegeben wird, ändert. Wenn dies geschieht und dekorierende Szenen den key der Szene, die sie dekorieren, direkt kopieren, werden die integrierten Animationen nicht mehr ausgeführt, da sich der abgeleitete Schlüssel nicht ändert.
Damit die integrierte Animationsunterstützung erhalten bleibt, sollten dekorierende Szenen einen Schlüssel verwenden, der von der Klasse und dem key der Szene abgeleitet ist, die von calculateScene zurückgegeben wird.
data class DerivedKeyScene<T : Any>( val scene: Scene<T> ) : Scene<T> { override val key = scene::class to scene.key // ... }