Szenen mit Szenen-Decorators anpassen

Mit Szenendekoratoren können Sie die von der Szenenstrategie Ihrer App berechnete Szene ändern. Sie werden für eine zweite Phase der Erstellung der Inhalte verwendet, die von einem NavDisplay angezeigt werden.

Mit diesem Ansatz können Sie bestimmte Funktionen wie die Anzeige allgemeiner UI-Komponenten in einzelnen Szenendekoratoren kapseln.

Nehmen wir als Beispiel eine Produktivitäts-App mit drei Routen der obersten 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, in der Informationen und Steuerelemente für die aktuelle Route der obersten Ebene angezeigt werden, und einen zum Hinzufügen einer dauerhaften Navigationsleiste oder ‑spalte zum Navigieren zwischen den Routen.

Strategie für die Szenendekoration erstellen

Szenen-Decorators folgen einem ähnlichen Muster wie Szenenstrategien. Wenn Sie einen Szenendekorator definieren möchten, implementieren Sie die SceneDecoratorStrategy-Schnittstelle. 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 Strategie für die Szenendekoration die Eingabeszenen nicht dekorieren soll, wird die Eingabeszenen unverändert zurückgegeben.
  • Wenn die Eingabeszenen dekoriert werden sollen, wird ein neues Scene zurückgegeben. Im Allgemeinen wird die zurückgegebene Szene mit der Eingabeszenen als Parameter aufgerufen und die content-Methode der Eingabeszenen wird in der eigenen content-Methode aufgerufen.

Um zu bestimmen, ob und wie die Eingabeszenen dekoriert werden sollen, kann Ihre Strategie zur Szenendekoration die Metadaten sowohl der Eingabe Scene als auch der Einträge in dieser Szene 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
        }
    }

}

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

    // ...

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

Strategien für Szenen-Decorators verwenden

Wenn Sie Strategien für die Dekoration von Szenen verwenden möchten, müssen Sie sie mit dem Parameter sceneDecoratorStrategies für NavDisplay angeben. Beim Dekorieren von Szenen ruft NavDisplay die Methode decorateScene jeder Strategie nacheinander auf und übergibt die Ausgabe jedes Aufrufs als Eingabe für den nächsten.

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

Häufig verwendete Muster für Szenendekoratoren

Bei der Implementierung von Szenendekoratoren sollten Sie die folgenden gängigen Muster beachten:

Attribute 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 Szene haben, die dekoriert wird. Außerdem sollten die Metadaten der Szene, die sie dekoriert, wahrscheinlich übernommen (oder geändert) werden, anstatt das Standardverhalten zu verwenden. Der folgende Code zeigt ein Beispiel dafür:

class CopyingScene<T : Any>(scene: Scene<T>) : Scene<T> {
    override val entries = scene.entries
    override val previousEntries = scene.previousEntries
    override val metadata = scene.metadata

    // ...
}

Animationen beibehalten

Wie unter Zwischen Zielen animieren beschrieben, werden Übergänge zwischen Szenen in NavDisplay automatisch animiert, wenn sich ein Schlüssel ändert, der von der Klasse der aktuellen Szene und ihrer key-Eigenschaft abgeleitet wird.

Wenn Sie Ihrer App Szenendekoratoren hinzufügen, kann die Klasse der Szene, die nach der Szenendekoration zurückgegeben wird, gleich bleiben, auch wenn sich die Klasse der Szene ändert, die während der Szenenberechnung zurückgegeben wird. Wenn das passiert und dekorierende Szenen direkt die key der Szene kopieren, die sie dekorieren, werden die integrierten Animationen nicht mehr ausgeführt, da sich der abgeleitete Schlüssel nicht ändert.

Um die integrierte Animationsunterstützung beizubehalten, sollte für das Dekorieren von Szenen ein Schlüssel verwendet werden, der von der Klasse und dem key der von calculateScene zurückgegebenen Szene abgeleitet wird.

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

    // ...
}