场景修饰器可让您修改由应用场景策略计算出的场景。实际上,它们用于构建 NavDisplay 所显示内容的第二阶段。
通过这种方法,您可以将特定功能(例如显示常见界面组件)封装到各个场景修饰器中。
例如,假设有一个效率提升应用,它有三个顶级路由:电子邮件收件箱、私信收件箱和日历视图。此类应用可以使用两个场景装饰器,一个用于添加顶部应用栏,以显示当前顶级路线的信息和控件;另一个用于添加常驻导航栏或侧边导航栏,以便在路线之间导航。
创建场景装饰器策略
场景修饰器遵循与场景策略类似的模式。如需定义场景装饰器,请实现 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 } } } data class MyDecoratingScene<T : Any>( val scene: Scene<T> ) : Scene<T> { // ... override val content = @Composable { scene.content() } }
使用场景装饰器策略
如需使用场景修饰器策略,请使用 sceneDecoratorStrategies 参数将其提供给 NavDisplay。在装饰场景时,NavDisplay 会依次调用每个策略的 decorateScene 方法,并将每次调用的输出作为下一次调用的输入。
NavDisplay( // ... sceneDecoratorStrategies = listOf(firstSceneDecoratorStrategy, secondSceneDecoratorStrategy) )
场景装饰器的常见模式
实现场景装饰器时,请注意以下一些常见模式:
复制属性
在许多情况下,通过修饰场景返回的场景应包含与所修饰场景相同的条目,并具有相同的先前条目。此外,它可能应该继承(或修改)其装饰场景的元数据,而不是使用默认行为。以下代码演示了如何执行此操作:
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 // ... }
维护动画
如在目的地之间添加动画效果中所详述,当派生自当前场景的类及其 key 属性的键发生更改时,NavDisplay 会自动为场景之间的过渡添加动画效果。
在应用中引入场景修饰器后,即使在场景计算期间返回的场景类发生变化,场景修饰后返回的场景类也可以保持不变。发生这种情况时,如果修饰场景直接复制其修饰场景的 key,则内置动画将不再发生,因为派生键不会更改。
为了保持内置动画支持,装饰场景应使用派生自 calculateScene 返回的场景的类和 key 的键。
data class DerivedKeyScene<T : Any>( val scene: Scene<T> ) : Scene<T> { override val key = scene::class to scene.key // ... }