โต้ตอบกับการ์ด

ไทล์ทําได้มากกว่าแค่แสดงข้อมูล แต่ยังโต้ตอบได้ด้วย หากต้องการให้องค์ประกอบ เช่น textButton() ตอบสนองต่อการแตะ ให้สร้างตัวแฮนเดิลการคลิกโดยใช้ clickable() และเชื่อมโยงกับองค์ประกอบเลย์เอาต์

คุณกําหนดค่า Clickable ให้ทริกเกอร์การดําเนินการได้ 2 วิธีหลัก ดังนี้

  1. เปิดกิจกรรมโดยตรง: ใช้ launchAction() ในกรณีที่คุณต้องเปิดกิจกรรมทันที
  2. มอบสิทธิ์ให้บริการไทล์: ใช้ loadAction() เพื่อเรียกใช้ตรรกะภายใน TileService วิธีนี้เป็นวิธีที่ยืดหยุ่นมากขึ้น ซึ่งช่วยให้คุณรีเฟรชเนื้อหาของการ์ด อัปเดตสถานะ หรือเปิดใช้งานกิจกรรมที่ซับซ้อนมากขึ้นได้

เปิดกิจกรรมที่ส่งออก

หากการแตะของผู้ใช้ควรเปิดใช้งานกิจกรรมทันที ให้ใช้ launchAction() ระบุ ComponentName เพื่อระบุกิจกรรม ต้องส่งออกกิจกรรม วิธีการนี้ช่วยให้คุณส่งข้อมูลเพิ่มเติม Intent รายการไปกับการดำเนินการได้ อย่างไรก็ตาม คุณจะตั้งค่า Flag Intent ที่กำหนดเองไม่ได้

ตัวอย่างต่อไปนี้แสดงวิธีสร้าง Clickable เพื่อเปิด TileActivity พร้อมด้วย Extra 2 รายการ ได้แก่ name และ age

textButton(
    labelContent = {
        text("launchAction()".layoutString, typography = BODY_LARGE)
    },
    onClick =
    clickable(
        action =
        launchAction(
            ComponentName(
                "com.example.wear",
                "com.example.wear.snippets.m3.tile.TileActivity",
            ),
            mapOf(
                "name" to ActionBuilders.stringExtra("Bartholomew"),
                "age" to ActionBuilders.intExtra(21),
            ),
        )
    ),
)

ในกิจกรรมที่เปิด ให้ดึงค่าจากข้อมูลเสริมของ Intent ดังนี้

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // When this activity is launched from the tile InteractionLaunchAction,
    // "name" will be "Bartholomew" and "age" will be 21
    val name = intent.getStringExtra("name")
    val age = intent.getStringExtra("age")

    // ...
}

จัดการการโต้ตอบในบริการข้อมูลแผนที่

หากต้องการการโต้ตอบที่ยืดหยุ่นมากขึ้น ให้ใช้ loadAction() เมื่อผู้ใช้แตะองค์ประกอบที่กําหนดค่าด้วย loadAction ระบบจะเรียกใช้ TileService.onTileRequest() อีกครั้ง ซึ่งจะช่วยให้คุณเรียกใช้ตรรกะในบริการเพื่ออัปเดตการ์ด เปลี่ยนสถานะ และทํางานที่ซับซ้อนมากขึ้นได้

รีเฟรชเนื้อหาของการ์ด

การใช้ loadAction ที่ง่ายที่สุดคือส่งสัญญาณการรีเฟรช เรียก loadAction โดยไม่มีอาร์กิวเมนต์ เมื่อแตะ ระบบจะเรียก onTileRequest() ซึ่งจะช่วยให้บริการแสดงเลย์เอาต์ใหม่ที่มีเนื้อหาที่อัปเดต

textButton(
    onClick = clickable(loadAction()),
    labelContent = { text("Refresh".layoutString) },
)

แยกแยะองค์ประกอบแบบอินเทอร์แอกทีฟหลายรายการ

หากการ์ดมีองค์ประกอบแบบอินเทอร์แอกทีฟหลายรายการ คุณสามารถเชื่อมโยงรหัสกับตัวแก้ไข Clickable ได้โดยทำดังนี้

ใน onTileRequest() คุณสามารถตรวจสอบรหัสนี้โดยใช้ requestParams.currentState.lastClickableId เพื่อตัดสินใจว่าจะดำเนินการใดต่อไป

ตัวอย่าง: การเริ่มกิจกรรมด้วย Deep Link

รูปแบบนี้เหมาะสําหรับการเปิดใช้งานกิจกรรมด้วย Deep Link ผู้ใช้แตะโหลดการ์ดอีกครั้ง บริการจะตรวจสอบรหัส แล้วเปิดกิจกรรมใหม่ หากต้องการควบคุมกองซ้อนที่ย้อนกลับ ให้ใช้ TaskStackBuilder เพื่อให้ผู้ใช้ได้รับประสบการณ์การนําทางที่ดียิ่งขึ้น เมื่อผู้ใช้แตะองค์ประกอบ ระบบจะนำผู้ใช้ไปยังหน้าจอที่ทำ Deep Link โดยตรง (หน้าจอ message_detail/1 จากตัวอย่าง) เนื่องจากมีการใช้ .addNextIntentWithParentStack() ระบบจึงเพิ่มกิจกรรมหลักลงในกองซ้อนที่ซ้อนกันด้วย ซึ่งหมายความว่าหากผู้ใช้ปัดย้อนกลับ ระบบจะนําทางผู้ใช้ไปยังหน้าจอหลักของแอป (MessageList ในตัวอย่าง) แทนที่จะออกจากการ์ดทันที การปัดกลับครั้งที่ 2 จะส่งผู้ใช้กลับไปที่การ์ด

จากนั้นใน TileActivity ให้กําหนดค่าการนําทางให้ตรงกับรูปแบบ googleandroidsnippets://app/message_detail/{id}

ใช้ TaskStackBuilder เพื่อให้ผู้ใช้ได้รับประสบการณ์การนําทางที่ดียิ่งขึ้น เมื่อผู้ใช้แตะองค์ประกอบ ระบบจะนำผู้ใช้ไปยังหน้าจอที่ทำ Deep Link โดยตรง ซึ่งในตัวอย่างนี้คือหน้าจอ message_detail/1 เนื่องจากมีการใช้ .addNextIntentWithParentStack() ระบบจึงเพิ่มกิจกรรมหลักลงในกองซ้อนด้านหลังด้วย ซึ่งหมายความว่าหากผู้ใช้ปัดกลับ ระบบจะนําทางผู้ใช้ขึ้นไปยังหน้าจอหลักของแอป (MessageList ในตัวอย่าง) แทนที่จะออกจากการ์ดทันที การปัดกลับครั้งที่ 2 จะส่งผู้ใช้กลับไปที่การ์ด

อัปเดตสถานะภายในการ์ด

ไทล์ของคุณมีออบเจ็กต์ StateBuilders.State ที่เก็บคู่คีย์-ค่าไว้และจะยังคงอยู่หลังจากการโหลดซ้ำ คุณสามารถใช้ loadAction() เพื่ออัปเดตสถานะนี้เมื่อผู้ใช้โต้ตอบกับการ์ด

โดยส่ง DynamicDataMap ไปยัง loadAction() ที่มีค่าสถานะใหม่

textButton(
    labelContent = {
        text("loadAction()".layoutString, typography = BODY_LARGE)
    },
    onClick =
    clickable(
        action =
        loadAction(
            dynamicDataMapOf(
                stringAppDataKey("name") mapTo "Javier",
                intAppDataKey("age") mapTo 37,
            )
        )
    ),
)

เมื่อ onTileRequest() เรียกให้ดำเนินการนี้ คุณจะอ่านข้อมูลที่อัปเดตแล้วจาก requestParams.currentState.stateMap ได้ ซึ่งมีประโยชน์สำหรับการโต้ตอบที่แก้ไขข้อมูลในการ์ดโดยตรง เช่น การเพิ่มตัวนับหรือสลับการตั้งค่า

override fun onTileRequest(
    requestParams: RequestBuilders.TileRequest
): ListenableFuture<Tile> {

    // When triggered by loadAction(), "name" will be "Javier", and "age" will
    // be 37.
    with(requestParams.currentState.stateMap) {
        val name = this[stringAppDataKey("name")]
        val age = this[intAppDataKey("age")]
    }

    // ...
}