使用場景修飾符修改場景

場景裝飾器可讓您修改應用程式場景策略計算出的場景。實際上,這些函式可用於建構 NavDisplay 顯示的內容,屬於第二階段。

這個方法可讓您將特定功能 (例如顯示常見的 UI 元件) 封裝到個別場景裝飾器中。

舉例來說,假設某個生產力應用程式有三個頂層路徑:電子郵件收件匣、即時訊息收件匣和日曆檢視畫面。這類應用程式可以使用兩個場景裝飾器,一個用於新增頂端應用程式列,顯示目前頂層路徑的資訊和控制項,另一個用於新增持續顯示的導覽列或導覽窗格,在路徑之間導覽。

建立場景裝飾器策略

場景裝飾器的模式與場景策略類似。如要定義場景裝飾器,請實作 SceneDecoratorStrategy 介面。這個介面有一個方法 decorateScene,類似於 SceneStrategy 介面的 calculateScene 方法。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()
    }
}

使用場景裝飾器策略

如要使用場景修飾符策略,請使用 sceneDecoratorStrategies 參數將策略提供給 NavDisplay。裝飾場景時,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

    // ...
}

維持動畫效果

如「為目的地之間的轉場加上動畫效果」一文所述,當衍生自目前場景類別及其 key 屬性的鍵變更時,NavDisplay 會自動為場景之間的轉場加上動畫效果。

在應用程式中導入場景裝飾器時,即使場景計算期間傳回的場景類別有所變更,場景裝飾後傳回的場景類別仍可維持不變。如果發生這種情況,且裝飾場景直接複製裝飾場景的 key,由於衍生金鑰不會變更,內建動畫就不會再發生。

如要維持內建動畫支援,裝飾場景應使用從類別和 calculateScene 傳回的場景 key 衍生而來的鍵。

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

    // ...
}

sceneDecoratorStrategies