เริ่มต้นใช้งานการ์ด


หากต้องการเริ่มแสดงไทล์จากแอป ให้รวมทรัพยากร Dependency ต่อไปนี้ไว้ในไฟล์ build.gradle ของแอป

Groovy

dependencies {
    // Use to implement support for wear tiles
    implementation "androidx.wear.tiles:tiles:1.6.2"

    // Use to utilize standard components and layouts in your tiles
    implementation "androidx.wear.protolayout:protolayout:1.4.2"

    // Use to utilize components and layouts with Material Design in your tiles
    implementation "androidx.wear.protolayout:protolayout-material:1.4.2"

    // Use to include dynamic expressions in your tiles
    implementation "androidx.wear.protolayout:protolayout-expression:1.4.2"

    // Use to preview wear tiles in your own app
    debugImplementation "androidx.wear.tiles:tiles-renderer:1.6.2"

    // Use to fetch tiles from a tile provider in your tests
    testImplementation "androidx.wear.tiles:tiles-testing:1.6.2"
}

Kotlin

dependencies {
    // Use to implement support for wear tiles
    implementation("androidx.wear.tiles:tiles:1.6.2")

    // Use to utilize standard components and layouts in your tiles
    implementation("androidx.wear.protolayout:protolayout:1.4.2")

    // Use to utilize components and layouts with Material Design in your tiles
    implementation("androidx.wear.protolayout:protolayout-material:1.4.2")

    // Use to include dynamic expressions in your tiles
    implementation("androidx.wear.protolayout:protolayout-expression:1.4.2")

    // Use to preview wear tiles in your own app
    debugImplementation("androidx.wear.tiles:tiles-renderer:1.6.2")

    // Use to fetch tiles from a tile provider in your tests
    testImplementation("androidx.wear.tiles:tiles-testing:1.6.2")
}

หัวข้อสำคัญ

ไทล์ไม่ได้สร้างขึ้นในลักษณะเดียวกับแอป Android และใช้แนวคิดที่แตกต่างกัน ดังนี้

  • เทมเพลตเลย์เอาต์: กำหนดการจัดเรียงโดยรวมขององค์ประกอบภาพบน จอแสดงผล โดยใช้ฟังก์ชัน primaryLayout()
  • องค์ประกอบเลย์เอาต์: แสดงองค์ประกอบกราฟิกแต่ละรายการ เช่น ปุ่มหรือการ์ด หรือองค์ประกอบดังกล่าวหลายรายการที่จัดกลุ่มเข้าด้วยกันโดยใช้คอลัมน์ buttonGroup หรือองค์ประกอบที่คล้ายกัน ซึ่งจะฝังอยู่ในเทมเพลตเลย์เอาต์
  • ทรัพยากร: ออบเจ็กต์ ResourceBuilders.Resources ประกอบด้วยแผนที่ ของคู่คีย์-ค่าของทรัพยากร Android (รูปภาพ) ที่จำเป็นต่อการ แสดงผลเลย์เอาต์ และเวอร์ชัน
  • ไทม์ไลน์: ออบเจ็กต์ TimelineBuilders.Timeline คือรายการของอินสแตนซ์อย่างน้อย 1 รายการของออบเจ็กต์เลย์เอาต์ คุณสามารถระบุกลไกและ นิพจน์ต่างๆ เพื่อระบุเวลาที่โปรแกรมแสดงผลควรเปลี่ยนจากออบเจ็กต์เลย์เอาต์หนึ่ง ไปยังอีกออบเจ็กต์หนึ่ง เช่น เพื่อหยุดแสดงเลย์เอาต์ในเวลาที่เฉพาะเจาะจง
  • สถานะ: โครงสร้างข้อมูลประเภท StateBuilders.State ที่ส่งผ่านระหว่างไทล์กับแอป เพื่อให้คอมโพเนนต์ทั้ง 2 สื่อสารกันได้ เช่น หากมีการแตะปุ่มในไทล์ สถานะ จะมีรหัสของปุ่ม นอกจากนี้ คุณยังแลกเปลี่ยนประเภทข้อมูลโดยใช้แผนที่ได้ด้วย
  • ไทล์: ออบเจ็กต์ TileBuilders.Tile ที่แสดงถึงไทล์ ซึ่งประกอบด้วยไทม์ไลน์ รหัสเวอร์ชันของทรัพยากร ช่วงความสดใหม่ และสถานะ
  • Protolayout: คำนี้ปรากฏในชื่อของคลาสต่างๆ ที่เกี่ยวข้องกับไทล์ และหมายถึงไลบรารี Protolayout ของ Wear OS ซึ่งเป็นไลบรารีกราฟิก ที่ใช้ในแพลตฟอร์มต่างๆ ของ Wear OS

สร้างไทล์

ใช้ Material3TileService (แนะนำ)

เมื่อสร้างไทล์ Material 3 (androidx.wear.tiles:tiles:1.6.0 ขึ้นไป) ให้ขยาย Material3TileService เสมอแทนที่จะใช้คลาส TileService ระดับล่าง Material3TileService มีสถาปัตยกรรมที่เน้น Kotlin เป็นหลัก ซึ่งช่วยลดความซับซ้อนในการพัฒนาไทล์

  • โครูทีน Kotlin ในตัว: ใช้ฟังก์ชัน MaterialScope.tileResponse(requestParams: TileRequest): Tileเดียวที่ระงับ แทนการใช้ ListenableFuture และการลบล้าง onTileRequest()
  • กำหนดค่าไว้ล่วงหน้า MaterialScope: tileResponse() ทำงานโดยมี MaterialScope เป็นตัวรับ (กำหนดค่าผ่านพารามิเตอร์ของตัวสร้าง เช่น allowDynamicTheme และ defaultColorScheme) คุณจึงไม่จำเป็นต้อง ห่อเลย์เอาต์ในการเรียก materialScope() ที่ซ้ำซ้อน
  • การลงทะเบียนทรัพยากรในการเรียกใช้ครั้งเดียว: รวมถึง ProtoLayoutScope เพื่อ ลงทะเบียนทรัพยากรรูปภาพในบรรทัดโดยอัตโนมัติ และแสดงทั้งเลย์เอาต์ไทล์ และทรัพยากรในการเรียกใช้ Binder ของระบบครั้งเดียว เนื่องจาก Material3TileService จัดการทรัพยากรโดยอัตโนมัติ (final onTileResourcesRequest()) จึงไม่ต้องลบล้าง onTileResourcesRequest()
class MyTileService : Material3TileService() {

    override suspend fun MaterialScope.tileResponse(requestParams: TileRequest): Tile =
        tile(
            timeline =
            Timeline.fromLayoutElement(
                primaryLayout(
                    mainSlot = {
                        text("Hello, World!".layoutString, typography = BODY_LARGE)
                    }
                )
            )
        )
}

TileService สถาปัตยกรรมพื้นฐาน

Material3TileService สร้างขึ้นบนคลาสพื้นฐาน TileService ซึ่งตัวอย่างที่เหลือในคู่มือนี้ใช้เพื่ออธิบายแนวคิดระดับต่ำ

หากต้องการระบุไทล์จากแอป ให้ใช้บริการประเภท TileService และลงทะเบียนในไฟล์ Manifest จากนั้นระบบจะขอไทล์ที่จำเป็นระหว่างการเรียกใช้ onTileRequest() และขอทรัพยากรระหว่างการเรียกใช้ onTileResourcesRequest()

class MyTileService : TileService() {

    override fun onTileRequest(requestParams: RequestBuilders.TileRequest) =
        Futures.immediateFuture(
            Tile.Builder()
                .setResourcesVersion(RESOURCES_VERSION)
                .setTileTimeline(
                    Timeline.fromLayoutElement(
                        materialScope(this, requestParams.deviceConfiguration) {
                            primaryLayout(
                                mainSlot = {
                                    text("Hello, World!".layoutString, typography = BODY_LARGE)
                                }
                            )
                        }
                    )
                )
                .build()
        )

    override fun onTileResourcesRequest(requestParams: ResourcesRequest) =
        Futures.immediateFuture(Resources.Builder().setVersion(RESOURCES_VERSION).build())
}

จากนั้นเพิ่มบริการภายในแท็ก <application> ของไฟล์ AndroidManifest.xml

<service
    android:name=".snippets.m3.tile.MyTileService"
    android:label="@string/tile_label"
    android:description="@string/tile_description"
    android:icon="@mipmap/ic_launcher"
    android:exported="true"
    android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
    <intent-filter>
        <action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
    </intent-filter>

    <meta-data android:name="androidx.wear.tiles.PREVIEW"
        android:resource="@drawable/tile_preview" />
</service>

สิทธิ์และตัวกรอง Intent จะลงทะเบียนบริการนี้เป็นผู้ให้บริการไทล์

ระบบจะแสดงไอคอน ป้ายกำกับ คำอธิบาย และแหล่งข้อมูลตัวอย่างต่อผู้ใช้เมื่อ ผู้ใช้กำหนดค่าการ์ดในโทรศัพท์หรือนาฬิกา โปรดทราบว่าแหล่งข้อมูลตัวอย่าง รองรับตัวระบุแหล่งข้อมูลมาตรฐานทั้งหมดของ Android จึงสามารถ ปรับเปลี่ยนตัวอย่างตามปัจจัยต่างๆ เช่น ขนาดหน้าจอและภาษาของอุปกรณ์ได้ ดูคำแนะนำเพิ่มเติมได้ในรายการตรวจสอบการแสดงตัวอย่าง

ติดตั้งใช้งานแอปและเพิ่มไทล์ลงในภาพหมุนของไทล์ (นอกจากนี้ยังมีวิธีแสดงตัวอย่างไทล์ที่เป็นมิตรกับนักพัฒนาแอปมากขึ้นด้วย แต่ตอนนี้ให้ทำด้วยตนเองก่อน)

การ์ด Wear OS ที่สร้างด้วย Material 3 ซึ่งแสดงข้อความ &quot;Hello World&quot;
รูปที่ 1 ไทล์ "Hello World"

ดูตัวอย่างที่สมบูรณ์ได้ในตัวอย่างโค้ดใน GitHub หรือโค้ดแล็บ

สร้าง UI สำหรับการ์ด

องค์ประกอบ UI ที่สื่ออารมณ์ของ Material 3 สร้างขึ้นโดยใช้แนวทางที่มีโครงสร้าง ซึ่งขับเคลื่อนโดยรูปแบบตัวสร้างที่ปลอดภัยด้านประเภทของ Kotlin

การจัดวาง

ดูคำแนะนำเกี่ยวกับหลักการออกแบบเบื้องหลังการสร้างเลย์เอาต์การ์ดที่มีประสิทธิภาพและปรับเปลี่ยนตามพื้นที่โฆษณาได้ในเลย์เอาต์ทั่วไปสำหรับการ์ด

หากต้องการสร้างเลย์เอาต์ ให้ทำดังนี้

  1. เริ่มต้นขอบเขต Material Design: เรียกใช้ฟังก์ชัน materialScope() โดยระบุ context และ deviceConfiguration ที่จำเป็น คุณ สามารถใส่พารามิเตอร์ที่ไม่บังคับ เช่น allowDynamicTheme และ defaultColorScheme allowDynamicTheme จะเป็น true โดยค่าเริ่มต้น และ defaultColorScheme จะแสดงถึง ColorScheme ที่ใช้เมื่อไม่มีสีแบบไดนามิก เช่น เมื่อผู้ใช้ปิดฟีเจอร์นี้ หรือ เมื่ออุปกรณ์ไม่รองรับ หรือ allowDynamicTheme เป็น false)

  2. สร้าง UI ภายในขอบเขต: ต้องกำหนดคอมโพเนนต์ UI ทั้งหมดสำหรับเลย์เอาต์ไทล์ที่กำหนดไว้ภายใน Lambda ของการเรียก materialScope() ระดับบนสุดรายการเดียว ฟังก์ชันของคอมโพเนนต์เหล่านี้ เช่น primaryLayout() และ textEdgeButton() เป็นฟังก์ชันส่วนขยายใน MaterialScope และจะใช้ได้ก็ต่อเมื่อมีการเรียกใช้ในขอบเขตของตัวรับนี้เท่านั้น

    materialScope(
        context = context,
        deviceConfiguration =
        requestParams.deviceConfiguration, // requestParams is passed to onTileRequest
        defaultColorScheme = myFallbackColorScheme
    ) {
        // inside the MaterialScope, you can call functions like primaryLayout()
        primaryLayout(
            titleSlot = { text(text = "Title".layoutString) },
            mainSlot = { text(text = "Main Content".layoutString) },
            bottomSlot = {
                textEdgeButton(
                    labelContent = { text("Action".layoutString) },
                    onClick = clickable()
                )
            }
        )
    }

สล็อต

ใน M3 เลย์เอาต์ไทล์จะใช้แนวทางที่ได้แรงบันดาลใจจาก Compose ซึ่งใช้ช่องที่แตกต่างกัน 3 ช่อง โดยจากบนลงล่างจะมีดังนี้

  1. titleSlot โดยปกติจะใช้กับชื่อหรือส่วนหัวหลัก
  2. mainSlot สำหรับเนื้อหาหลัก
  3. bottomSlot มักใช้สำหรับการดำเนินการหรือข้อมูลเพิ่มเติม นอกจากนี้ ปุ่มขอบจะปรากฏที่นี่ด้วย
เลย์เอาต์การ์ดที่แสดง titleSlot, mainSlot และ bottomSlot
รูปที่ 2. titleSlot, mainSlot และ bottomSlot

เนื้อหาของแต่ละช่องมีดังนี้

  • titleSlot (ไม่บังคับ): โดยปกติจะเป็นคำ 2-3 คำที่สร้างโดย text()
  • mainSlot (ต้องระบุ): คอมโพเนนต์ที่จัดระเบียบเป็นโครงสร้าง เช่น แถว คอลัมน์ และกลุ่มปุ่ม นอกจากนี้ คอมโพเนนต์เหล่านี้ยังฝังซ้อนกันได้ด้วย เช่น คอลัมน์อาจมีแถว
  • bottomSlot (ไม่บังคับ): โดยปกติจะใส่ปุ่มที่ติดขอบหรือป้ายกำกับข้อความ

เนื่องจากเลื่อนไทล์ไม่ได้ จึงไม่มีคอมโพเนนต์สำหรับการแบ่งหน้า การเลื่อน หรือการจัดการรายการเนื้อหาที่ยาว โปรดตรวจสอบว่าเนื้อหายังคงมองเห็นได้เมื่อขนาดแบบอักษรเพิ่มขึ้นหรือข้อความยาวขึ้นเนื่องจากการแปล

คอมโพเนนต์ UI

ไลบรารี protolayout-material3 มีคอมโพเนนต์จำนวนมาก ซึ่งออกแบบตามข้อกำหนดของ Material 3 Expressive และคำแนะนำเกี่ยวกับอินเทอร์เฟซผู้ใช้

ปุ่ม

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

  • textButton(): ปุ่มที่มีช่องเดียวสำหรับเนื้อหาข้อความ (สั้น)
  • iconButton(): ปุ่มที่มีช่องเดียวเพื่อแสดงไอคอน
  • avatarButton(): ปุ่มรูปโปรไฟล์ทรงเม็ดยาที่มีช่องสูงสุด 3 ช่องสำหรับใส่เนื้อหาที่แสดงป้ายกำกับและป้ายกำกับรองที่ซ้อนกันในแนวตั้ง รวมถึงรูปภาพ (รูปโปรไฟล์) ที่อยู่ข้างๆ
  • imageButton(): ปุ่มรูปภาพที่คลิกได้ซึ่งไม่มีช่องเพิ่มเติม มีเฉพาะรูปภาพ (เช่น backgroundImage เป็นพื้นหลัง)
  • compactButton(): ปุ่มขนาดกะทัดรัดที่มีช่องสูงสุด 2 ช่องสำหรับวาง เนื้อหาที่ซ้อนกันในแนวนอนซึ่งแสดงไอคอนและข้อความข้างๆ
  • button(): ปุ่มรูปแคปซูลที่มีช่องสูงสุด 3 ช่องสำหรับใส่ เนื้อหาที่แสดงป้ายกำกับและป้ายกำกับรองที่ซ้อนกันในแนวตั้ง รวมถึง ไอคอนที่อยู่ถัดจากปุ่ม

ปุ่มขอบ

ปุ่มขอบเป็นปุ่มแบบเต็มความกว้างเฉพาะที่ยึดไว้ที่ด้านล่างของ หน้าจอกลมของนาฬิกา ซึ่งแสดงการดำเนินการที่สำคัญที่สุดที่ต้องทำจาก หน้าจอการ์ดปัจจุบัน

  • iconEdgeButton(): ปุ่มขอบที่มีช่องเดียวสำหรับใส่ไอคอนหรือเนื้อหาขนาดเล็กที่มีลักษณะกลมคล้ายกัน
  • textEdgeButton(): ปุ่มขอบที่ให้ช่องเดียวสำหรับใส่ข้อความหรือเนื้อหาที่ยาวและกว้างคล้ายกัน

การ์ด

การ์ดส่วนใหญ่มุ่งเน้นข้อมูล โดยจะแสดงคอลเล็กชันของ Structured Data ที่เกี่ยวข้อง แม้ว่าคุณจะสร้างการ์ดแบบอินเทอร์แอกทีฟได้ แต่โดยปกติแล้วการ์ดจะแสดงข้อมูลสรุป ซึ่งผู้ใช้สามารถแตะเพื่อดูรายละเอียดเพิ่มเติมหรือดำเนินการที่เกี่ยวข้องได้

  • titleCard(): การ์ดไตเติ้ลที่มีช่อง 1-3 ช่อง ซึ่งมักจะเป็นข้อความ
  • appCard(): การ์ดแอปที่มีช่องสูงสุด 5 ช่อง ซึ่งมักจะเป็นข้อความ
  • textDataCard(): การ์ดข้อมูลที่แสดงช่องซ้อนกันในแนวตั้งได้สูงสุด 3 ช่อง โดยปกติจะเป็นข้อความหรือตัวเลข
  • iconDataCard(): การ์ดข้อมูลที่มีไอคอนซึ่งมีช่องซ้อนกันในแนวตั้งสูงสุด 3 ช่อง โดยปกติจะเป็นข้อความหรือตัวเลข
  • graphicDataCard(): การ์ดข้อมูลกราฟิกที่มีช่องสำหรับข้อมูลกราฟิก เช่น ตัวบ่งชี้ความคืบหน้า และช่องที่ซ้อนกันในแนวตั้งสูงสุด 2 ช่อง ซึ่งมักใช้สำหรับคำอธิบายข้อความ

ตัวบอกสถานะความคืบหน้า

  • circularProgressIndicator(): แสดงความคืบหน้าสู่เป้าหมายโดยใช้ องค์ประกอบรัศมี
  • segmentedCircularProgressIndicator(): แสดงความคืบหน้าในการบรรลุเป้าหมายโดยใช้องค์ประกอบรัศมีที่มีขั้นตอนที่แตกต่างกัน

องค์ประกอบเลย์เอาต์ของกลุ่ม

  • buttonGroup(): คอมโพเนนต์เลย์เอาต์ที่วางองค์ประกอบย่อยในลำดับแนวนอน
  • primaryLayout(): เลย์เอาต์แบบเต็มหน้าจอที่แสดงถึงเลย์เอาต์ M3 ที่แนะนำ ซึ่งเป็นเลย์เอาต์ที่ตอบสนองตามอุปกรณ์และดูแลการจัดวางองค์ประกอบ พร้อมกับระยะขอบและระยะเว้นที่แนะนำ

ใช้ธีม

ใน Material 3 Expressive ระบบสีจะกำหนดโดยบทบาทสีมาตรฐาน 29 บทบาท ซึ่งจัดเป็น 6 กลุ่ม ได้แก่ สีหลัก สีรอง สีเสริม สีข้อผิดพลาด สีพื้นผิว และสีเส้นขอบ

ระบบสี Material 3 Expressive ซึ่งแสดงบทบาทของสีที่จัดระเบียบเป็นกลุ่มต่างๆ เช่น สีหลัก สีรอง สีเสริม สีข้อผิดพลาด สีพื้นผิว และสีเส้นขอบ
รูปที่ 3 ระบบสี Material 3 Expressive

ColorScheme จะแมปบทบาททั้ง 29 บทบาทนี้กับสีที่เกี่ยวข้อง และ เนื่องจากเป็นส่วนหนึ่งของ MaterialScope และต้องสร้างคอมโพเนนต์ภายใน คอมโพเนนต์จึงใช้สีจากรูปแบบโดยอัตโนมัติ วิธีนี้ช่วยให้องค์ประกอบ UI ทั้งหมดเป็นไปตามมาตรฐาน Material Design โดยอัตโนมัติ

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

val myColorScheme =
    ColorScheme(
        primary = Color.rgb(0, 0, 255).argb, // Blue
        onPrimary = Color.rgb(255, 255, 255).argb, // White
        // 27 more
    )

materialScope(
    context = context,
    deviceConfiguration = requestParams.deviceConfiguration,
    defaultColorScheme = myColorScheme
) {
    // If the user selects "no theme" in settings, myColorScheme is used.
    // Otherwise, the system-provided theme is used.
}

หากเลือกตัวเลือกนี้ ให้ระบุไอคอนไทล์ขาวดำเพื่อให้ ระบบสามารถปรับสีได้อย่างถูกต้องเพื่อให้มองเห็นได้ชัดเจนที่สุดเมื่อใช้กับธีมใดก็ตาม

หากต้องการบังคับให้หน้าต่างปรากฏในรูปแบบสีที่คุณระบุ ให้ปิดใช้การรองรับ การกำหนดธีมแบบไดนามิกโดยตั้งค่า allowDynamicTheme เป็น false

materialScope(
    context = context,
    deviceConfiguration = requestParams.deviceConfiguration,
    allowDynamicTheme = false,
    defaultColorScheme = myColorScheme
) {
    // myColorScheme is *always* used.
}

สี

คอมโพเนนต์แต่ละรายการใช้ชุดย่อยของบทบาทสี 29 บทบาทที่กำหนดโดย ColorScheme ตัวอย่างเช่น ปุ่มจะใช้สีได้สูงสุด 4 สี ซึ่งโดยค่าเริ่มต้นจะ นำมาจากกลุ่ม "หลัก" ของ ColorScheme ที่ใช้งานอยู่

โทเค็นคอมโพเนนต์ ButtonColors บทบาท ColorScheme
containerColor หลัก
iconColor onPrimary
labelColor onPrimary
secondaryLabelColor onPrimary (ความทึบแสง 0.8)

ดูคำแนะนำโดยละเอียดเกี่ยวกับการใช้สีกับการออกแบบ Wear OS ได้ที่คู่มือ การออกแบบสี

คุณอาจต้องเบี่ยงเบนจากโทเค็นสีเริ่มต้นสำหรับองค์ประกอบ UI บางอย่าง เช่น คุณอาจต้องการให้ textEdgeButton ใช้ สีจากกลุ่ม "รอง" หรือ "ลำดับที่ 3" แทน "หลัก" เพื่อให้ โดดเด่นและมีคอนทราสต์ที่ดีขึ้น

คุณปรับแต่งสีของคอมโพเนนต์ได้หลายวิธี ดังนี้

  1. ใช้ฟังก์ชันตัวช่วยสำหรับสีที่กำหนดไว้ล่วงหน้า ใช้ฟังก์ชันช่วย เช่น filledTonalButtonColors() เพื่อใช้รูปแบบปุ่มมาตรฐานสำหรับ Material 3 Expressive ฟังก์ชันเหล่านี้สร้างอินสแตนซ์ ButtonColors ที่กำหนดค่าไว้ล่วงหน้า ซึ่งจะแมปรูปแบบทั่วไป เช่น แบบทึบ แบบโทนสี หรือแบบร่าง กับ บทบาทที่เหมาะสมจาก ColorScheme ที่ใช้งานอยู่ภายใน MaterialScope ซึ่งจะช่วยให้คุณใช้รูปแบบที่สอดคล้องกันได้โดยไม่ต้องกำหนดสีแต่ละสีด้วยตนเอง สำหรับปุ่มประเภททั่วไป

    textEdgeButton(
        colors = filledButtonColors(), // default
        /* OR colors = filledTonalButtonColors() */
        /* OR colors = filledVariantButtonColors() */
        // ... other parameters
    )

    สำหรับไพ่ ให้ใช้ฟังก์ชันในตระกูล filledCardColors() ที่เทียบเท่ากัน

    นอกจากนี้ คุณยังแก้ไขButtonColorsออบเจ็กต์ที่ฟังก์ชันตัวช่วยส่งคืน โดยใช้เมธอด copy() ได้หากต้องการเปลี่ยนโทเค็นเพียง 1 หรือ 2 รายการ

    textEdgeButton(
        colors =
        filledButtonColors()
            .copy(
                containerColor = colorScheme.tertiary,
                labelColor = colorScheme.onTertiary
            ),
        // ... other parameters
    )

  2. ระบุบทบาทสีแทนที่อย่างชัดเจน สร้างออบเจ็กต์ ButtonColors ของคุณเอง แล้วส่งไปยังคอมโพเนนต์ สำหรับบัตร ให้ใช้ออบเจ็กต์ CardColors ที่เทียบเท่า

    textEdgeButton(
        colors =
        ButtonColors(
            // the materialScope makes colorScheme available
            containerColor = colorScheme.secondary,
            iconColor = colorScheme.secondaryDim,
            labelColor = colorScheme.onSecondary,
            secondaryLabelColor = colorScheme.onSecondary
        ),
        // ... other parameters
    )

  3. ระบุสีคงที่ (ใช้อย่างระมัดระวัง) แม้ว่าโดยทั่วไปเราจะแนะนำให้ระบุสีตามบทบาทเชิงความหมาย (เช่น colorScheme.primary) แต่คุณก็ระบุค่าสีโดยตรงได้เช่นกัน คุณควรใช้วิธีนี้อย่างระมัดระวัง เนื่องจากอาจทำให้ธีมโดยรวมไม่สอดคล้องกัน โดยเฉพาะอย่างยิ่งหากธีมมีการเปลี่ยนแปลงแบบไดนามิก

    textEdgeButton(
        colors = filledButtonColors().copy(
            containerColor = android.graphics.Color.RED.argb, // Using named colors
            labelColor = 0xFFFFFF00.toInt().argb // Using a hex code for yellow
        ),
        // ... other parameters
    )

การพิมพ์

ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้การพิมพ์อย่างมีประสิทธิภาพในการออกแบบได้ที่ คู่มือการออกแบบการพิมพ์

ข้อความทั้งหมดในการ์ดจะแสดงผลโดยใช้แบบอักษรที่ระบบจัดเตรียมไว้ให้ เพื่อสร้างความสอดคล้องด้านภาพในแพลตฟอร์ม Wear OS และเพื่อเพิ่มประสิทธิภาพ กล่าวคือ หน้าต่างไม่รองรับแบบอักษรที่กำหนดเอง ใน Wear OS 6 ขึ้นไป แบบอักษรนี้จะเป็นแบบอักษรเฉพาะ OEM ในกรณีส่วนใหญ่จะเป็นแบบอักษรแบบแปรผัน ซึ่งจะมอบประสบการณ์ที่สื่ออารมณ์ได้มากขึ้นและควบคุมได้ละเอียดยิ่งขึ้น

โดยปกติแล้ว หากต้องการสร้างรูปแบบข้อความ คุณมักจะใช้วิธี text() ร่วมกับค่าคงที่ทางอักขระศาสตร์ คอมโพเนนต์นี้ช่วยให้คุณใช้ประโยชน์จาก บทบาทการพิมพ์ที่กําหนดไว้ล่วงหน้าใน Material 3 Expressive ซึ่งจะช่วยให้ไทล์ เป็นไปตามแนวทางปฏิบัติแนะนําด้านการพิมพ์ที่กำหนดไว้เพื่อให้อ่านง่ายและมีลำดับชั้น ไลบรารีมีค่าคงที่ของแบบอักษรเชิงความหมาย 18 รายการ เช่น BODY_MEDIUM ค่าคงที่เหล่านี้ยังส่งผลต่อแกนแบบอักษรอื่นๆ นอกเหนือจากขนาดด้วย

text(
    text = "Hello, World!".layoutString,
    typography = BODY_MEDIUM,
)

หากต้องการควบคุมเพิ่มเติม คุณสามารถระบุการตั้งค่าเพิ่มเติมได้ ใน Wear OS 6 ขึ้นไป ระบบน่าจะใช้แบบอักษรแบบแปรผัน ซึ่งคุณสามารถแก้ไขตามแกนตัวเอียง น้ำหนัก ความกว้าง และความกลม คุณควบคุมแกนเหล่านี้ได้ โดยใช้พารามิเตอร์ settings

text(
    text = "Hello, World".layoutString,
    italic = true,

    // Use elements defined in androidx.wear.protolayout.LayoutElementBuilders.FontSetting
    settings =
    listOf(
        weight(500),
        width(100F),
        roundness(100)
    ),
)

สุดท้ายนี้ หากต้องการควบคุมขนาดหรือระยะห่างระหว่างตัวอักษร (ไม่แนะนำ) ให้ใช้ basicText() แทน text() และสร้างค่าสำหรับ พร็อพเพอร์ตี้ fontStyle โดยใช้ fontStyle())

รูปร่างและขอบ

คุณเปลี่ยนรัศมีมุมของคอมโพเนนต์เกือบทุกรายการได้โดยใช้พร็อพเพอร์ตี้shape ของคอมโพเนนต์นั้น ค่ามาจากพร็อพเพอร์ตี้ MaterialScope shapes ดังนี้

textButton(
    height = expand(),
    width = expand(),
    shape = shapes.medium, // OR another value like shapes.full
    colors = filledVariantButtonColors(),
    labelContent = { text("Hello, World!".layoutString) },
)

หลังจากเปลี่ยนรูปร่างของคอมโพเนนต์แล้ว หากคิดว่ามีพื้นที่มากเกินไปหรือน้อยเกินไปรอบขอบของจอแสดงผล ให้ปรับขอบโดยใช้พารามิเตอร์ margin ของ primaryLayout() ดังนี้

primaryLayout(
    mainSlot = {
        textButton(
            shape = shapes.small,
            /* ... */
        )
    },
    // margin constants defined in androidx.wear.protolayout.material3.PrimaryLayoutMargins
    margins = MAX_PRIMARY_LAYOUT_MARGIN,
)

เส้นโค้ง

ระบบรองรับองค์ประกอบย่อยของคอนเทนเนอร์ Arc ต่อไปนี้

  • ArcLine: แสดงเส้นโค้งรอบอาร์ค
  • ArcText: แสดงข้อความโค้งใน Arc
  • ArcAdapter: แสดงผลองค์ประกอบเลย์เอาต์พื้นฐานในส่วนโค้ง โดยวาดที่เส้นสัมผัสของส่วนโค้ง

ดูข้อมูลเพิ่มเติมได้ที่เอกสารอ้างอิงสำหรับองค์ประกอบแต่ละประเภท

คีย์ตัวปรับแต่ง

องค์ประกอบเลย์เอาต์ที่มีอยู่ทุกรายการสามารถเลือกใช้ตัวแก้ไขได้ ใช้ ตัวแก้ไขเหล่านี้เพื่อวัตถุประสงค์ต่อไปนี้

  • เปลี่ยนลักษณะที่ปรากฏของเลย์เอาต์ เช่น เพิ่มพื้นหลัง เส้นขอบ หรือระยะห่างจากขอบให้กับองค์ประกอบเลย์เอาต์
  • เพิ่มข้อมูลเมตาเกี่ยวกับเลย์เอาต์ เช่น เพิ่มตัวแก้ไขความหมายลงในองค์ประกอบ เลย์เอาต์เพื่อใช้กับโปรแกรมอ่านหน้าจอ
  • เพิ่มฟังก์ชันการทำงาน เช่น เพิ่มตัวแก้ไขที่คลิกได้ลงในเลย์เอาต์ องค์ประกอบเพื่อให้ไทล์โต้ตอบได้ ดูข้อมูลเพิ่มเติมได้ที่ โต้ตอบกับไทล์

ตัวอย่างเช่น เราสามารถปรับแต่งรูปลักษณ์และข้อมูลเมตาเริ่มต้นของ Image ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้

private fun myImage(): LayoutElement =
    Image.Builder()
        .setWidth(dp(24f))
        .setHeight(dp(24f))
        .setResourceId("image_id")
        .setModifiers(
            Modifiers.Builder()
                .setBackground(Background.Builder().setColor(argb(0xFFFF0000.toInt())).build())
                .setPadding(ModifiersBuilders.Padding.Builder().setStart(dp(12f)).build())
                .setSemantics(Semantics.Builder().setContentDescription("Image description").build())
                .build()
        )
        .build()

Spannables

Spannable เป็นคอนเทนเนอร์ประเภทพิเศษที่จัดวางองค์ประกอบคล้ายกับข้อความ ซึ่งจะมีประโยชน์เมื่อคุณต้องการใช้สไตล์ที่แตกต่างกันกับสตริงย่อยเพียงสตริงเดียวในบล็อกข้อความขนาดใหญ่ ซึ่งเป็นสิ่งที่ทำไม่ได้ด้วยองค์ประกอบ Text

Spannable คอนเทนเนอร์เต็มไปด้วยรายการย่อย Span ไม่อนุญาตให้ใช้เด็กคนอื่นๆ หรืออินสแตนซ์ Spannable ที่ซ้อนกัน

Span เด็กมี 2 ประเภท ได้แก่

  • SpanText: แสดงข้อความด้วยสไตล์ที่เฉพาะเจาะจง
  • SpanImage: แสดงรูปภาพในบรรทัดเดียวกับข้อความ

เช่น คุณอาจทำให้คำว่า "world" ในไทล์ "Hello world" เป็นตัวเอียงและแทรกรูปภาพระหว่างคำ ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้

private fun mySpannable(): LayoutElement =
    LayoutElementBuilders.Spannable.Builder()
        .addSpan(SpanText.Builder().setText("Hello ").build())
        .addSpan(SpanImage.Builder().setWidth(dp(24f)).setHeight(dp(24f)).setResourceId("image_id").build())
        .addSpan(
            SpanText.Builder()
                .setText("world")
                .setFontStyle(FontStyle.Builder().setItalic(true).build())
                .build()
        )
        .build()

ใช้งานกับทรัพยากร

ไทล์ไม่มีสิทธิ์เข้าถึงทรัพยากรใดๆ ของแอป ซึ่งหมายความว่าคุณไม่สามารถส่งรหัสรูปภาพ Android ไปยังองค์ประกอบเลย์เอาต์ Image และคาดหวังให้ระบบ แก้ไขได้ ให้ลบล้างเมธอด onTileResourcesRequest() และ ระบุทรัพยากรด้วยตนเองแทน

คุณระบุรูปภาพภายในเมธอด onTileResourcesRequest() ได้ 2 วิธี ดังนี้

  • ระบุทรัพยากรที่วาดได้โดยใช้ setAndroidResourceByResId()
  • ระบุรูปภาพแบบไดนามิกเป็น ByteArray โดยใช้ setInlineResource()

override fun onTileResourcesRequest(
    requestParams: ResourcesRequest
) = Futures.immediateFuture(
    Resources.Builder()
        .setVersion("1")
        .addIdToImageMapping(
            "image_from_resource",
            ResourceBuilders.ImageResource.Builder()
                .setAndroidResourceByResId(
                    ResourceBuilders.AndroidImageResourceByResId.Builder()
                        .setResourceId(R.drawable.ic_walk)
                        .build()
                ).build()
        )
        .addIdToImageMapping(
            "image_inline",
            ResourceBuilders.ImageResource.Builder()
                .setInlineResource(
                    ResourceBuilders.InlineImageResource.Builder()
                        .setData(imageAsByteArray)
                        .setWidthPx(48)
                        .setHeightPx(48)
                        .setFormat(ResourceBuilders.IMAGE_FORMAT_RGB_565)
                        .build()
                ).build()
        ).build()
)

รายการตรวจสอบรูปภาพตัวอย่างการ์ด

ระบบจะแสดงรูปภาพตัวอย่างของการ์ดที่อ้างอิงในไฟล์ Manifest ของแอป Android ในเครื่องมือแก้ไขภาพสไลด์ของการ์ดเพื่อเพิ่มการ์ดใหม่ โดยตัวแก้ไขนี้จะปรากฏทั้งในอุปกรณ์ Wear OS และในแอปที่ใช้ร่วมกันของนาฬิกาในโทรศัพท์

โปรดตรวจสอบรายละเอียดต่อไปนี้เกี่ยวกับไทล์เพื่อช่วยให้ผู้ใช้ได้รับประโยชน์สูงสุดจากรูปภาพตัวอย่างนี้

  • แสดงการออกแบบล่าสุด ตัวอย่างควรแสดงการออกแบบล่าสุดของไทล์อย่างถูกต้อง
  • ใช้ขนาดที่แนะนำ รูปภาพตัวอย่างควรมีขนาด 400x400 พิกเซล เพื่อให้แสดงผลได้ดีที่สุดและมอบประสบการณ์การใช้งานที่ดีแก่ผู้ใช้
  • ใช้ธีมสีแบบคงที่ ใช้ธีมสีแบบคงที่ของไทล์ ไม่ใช่ธีมสีแบบไดนามิก
  • รวมไอคอนแอป ยืนยันว่าไอคอนของแอปปรากฏที่ด้านบนของ รูปภาพตัวอย่าง
  • แสดงสถานะที่โหลด/เข้าสู่ระบบแล้ว ตัวอย่างควรแสดงสถานะ "โหลดแล้ว" หรือ "เข้าสู่ระบบแล้ว" ที่ทำงานได้อย่างสมบูรณ์ โดยหลีกเลี่ยงเนื้อหาที่ว่างเปล่าหรือตัวยึดตำแหน่ง
  • ใช้ประโยชน์จากกฎการแก้ปัญหาทรัพยากรเพื่อการปรับแต่ง (ไม่บังคับ) ลองใช้กฎความละเอียดของทรัพยากรของ Android เพื่อแสดงตัวอย่าง ที่ตรงกับการตั้งค่าขนาดการแสดงผล ภาษา หรือภาษาของอุปกรณ์ ซึ่งจะเป็นประโยชน์อย่างยิ่งหากลักษณะที่ปรากฏของไทล์แตกต่างกันไปในแต่ละอุปกรณ์