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


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

Groovy

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

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

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

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

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

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

Kotlin

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

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

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

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

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

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

หัวข้อสำคัญ

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

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

สร้างไทล์

หากต้องการระบุไทล์จากแอป ให้ใช้บริการประเภท 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 ดังนั้นจึงสามารถปรับเปลี่ยนตัวอย่างตามปัจจัยต่างๆ เช่น ขนาดหน้าจอและภาษาของอุปกรณ์ ดูคำแนะนำเพิ่มเติมได้ในรายการตรวจสอบก่อนเผยแพร่

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

ไทล์ &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(text = "Action".layoutString) }
        )
    }
    

สล็อต

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

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

val myColorScheme =
    ColorScheme(
        primary = ...
        onPrimary = ...
        // 27 more
    )

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

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

materialScope(
  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.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 ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้

Kotlin

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

Java

private LayoutElement myImage() {
   return new Image.Builder()
           .setWidth(dp(24f))
           .setHeight(dp(24f))
           .setResourceId("image_id")
           .setModifiers(new Modifiers.Builder()
                   .setBackground(new Background.Builder().setColor(argb(0xFFFF0000)).build())
                   .setPadding(new Padding.Builder().setStart(dp(12f)).build())
                   .setSemantics(new Semantics.Builder()
                           .setContentDescription("Image description")
                           .build()
                   ).build()
           ).build();
}

Spannables

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

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

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

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

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

Kotlin

private fun mySpannable(): LayoutElement =
    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()

Java

private LayoutElement mySpannable() {
   return new Spannable.Builder()
        .addSpan(new SpanText.Builder()
            .setText("Hello ")
            .build()
        )
        .addSpan(new SpanImage.Builder()
            .setWidth(dp(24f))
            .setHeight(dp(24f))
            .setResourceId("image_id")
            .build()
        )
        .addSpan(new SpanText.Builder()
            .setText("world")
            .setFontStyle(newFontStyle.Builder()
                .setItalic(true)
                .build())
            .build()
        ).build();
}

ทำงานกับทรัพยากร

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

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

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

Kotlin

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

Java

@Override
protected ListenableFuture<Resources> onTileResourcesRequest(
       @NonNull ResourcesRequest requestParams
) {
return Futures.immediateFuture(
    new Resources.Builder()
        .setVersion("1")
        .addIdToImageMapping("image_from_resource", new ImageResource.Builder()
            .setAndroidResourceByResId(new AndroidImageResourceByResId.Builder()
                .setResourceId(R.drawable.image_id)
                .build()
            ).build()
        )
        .addIdToImageMapping("image_inline", new ImageResource.Builder()
            .setInlineResource(new InlineImageResource.Builder()
                .setData(imageAsByteArray)
                .setWidthPx(48)
                .setHeightPx(48)
                .setFormat(ResourceBuilders.IMAGE_FORMAT_RGB_565)
                .build()
            ).build()
        ).build()
);
}

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

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

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

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