แก้ไขฉากด้วย Scene Decorator

ตัวตกแต่งฉากช่วยให้คุณแก้ไขฉากที่คำนวณโดยกลยุทธ์ ฉากของแอปได้ โดยมีผลเป็นการใช้สำหรับเฟสที่ 2 ของการสร้าง เนื้อหาที่แสดงโดย NavDisplay

แนวทางนี้ช่วยให้คุณห่อหุ้มฟังก์ชันการทำงานที่เฉพาะเจาะจง เช่น การแสดงคอมโพเนนต์ UI ทั่วไป ไว้ในตัวตกแต่งฉากแต่ละรายการได้

ตัวอย่างเช่น ลองนึกถึงแอปเพิ่มประสิทธิภาพที่มีเส้นทางระดับบนสุด 3 เส้นทาง ได้แก่ กล่องจดหมายอีเมล กล่องจดหมายข้อความส่วนตัว และมุมมองปฏิทิน แอปดังกล่าวอาจใช้ตัวตกแต่งฉาก 2 รายการ รายการหนึ่งสำหรับเพิ่มแถบแอปด้านบนที่แสดงข้อมูลและการควบคุมสำหรับเส้นทางระดับบนสุดปัจจุบัน และอีกรายการหนึ่งสำหรับเพิ่มแถบนำทางหรือแถบด้านข้างแบบถาวรเพื่อนำทางระหว่างเส้นทาง

สร้างกลยุทธ์ตัวตกแต่งฉาก

ตัวตกแต่งฉากมีรูปแบบคล้ายกับกลยุทธ์ฉาก หากต้องการกำหนดตัวตกแต่งฉาก ให้ใช้อินเทอร์เฟซ 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
        }
    }

}

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

    // ...

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

ใช้กลยุทธ์ตัวตกแต่งฉาก

หากต้องการใช้กลยุทธ์ตัวตกแต่งฉาก ให้ระบุกลยุทธ์เหล่านั้นใน NavDisplay โดยใช้พารามิเตอร์ sceneDecoratorStrategies เมื่อตกแต่งฉาก 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

    // ...
}

MyScene<T>(...) : Scene<T> by scene

รักษาภาพเคลื่อนไหว

ตามที่ระบุไว้โดยละเอียดในหัวข้อ ทำภาพเคลื่อนไหวระหว่างปลายทาง, NavDisplay จะทำภาพเคลื่อนไหวการเปลี่ยนระหว่างฉากโดยอัตโนมัติ เมื่อคีย์ที่ได้จากคลาสของฉากปัจจุบัน และพร็อพเพอร์ตี้ key เปลี่ยนไป

เมื่อนำตัวตกแต่งฉากมาใช้ในแอป คลาสของฉากที่แสดง หลังจากการตกแต่งฉากอาจยังคงเหมือนเดิม แม้ว่าคลาสของฉากที่แสดง ระหว่างการคำนวณฉากจะเปลี่ยนไปก็ตาม เมื่อเกิดกรณีนี้และฉากที่ตกแต่งคัดลอก key ของฉากที่กำลังตกแต่งโดยตรง ภาพเคลื่อนไหวในตัวจะไม่เกิดขึ้นอีกต่อไปเนื่องจากคีย์ที่ได้มาไม่เปลี่ยนแปลง

หากต้องการคงการรองรับภาพเคลื่อนไหวในตัวไว้ ฉากที่ตกแต่งควรใช้คีย์ที่ได้จากคลาสและ key ของฉากที่แสดงโดย calculateScene

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

    // ...
}