หากต้องการเริ่มให้บริการการ์ดจากแอป ให้รวมไลบรารีต่อไปนี้ไว้ในไฟล์ build.gradle
ของแอป
Groovy
dependencies { // Use to implement support for wear tiles implementation "androidx.wear.tiles:tiles:1.4.1" // Use to utilize standard components and layouts in your tiles implementation "androidx.wear.protolayout:protolayout:1.2.1" // Use to utilize components and layouts with Material Design in your tiles implementation "androidx.wear.protolayout:protolayout-material:1.2.1" // Use to include dynamic expressions in your tiles implementation "androidx.wear.protolayout:protolayout-expression:1.2.1" // Use to preview wear tiles in your own app debugImplementation "androidx.wear.tiles:tiles-renderer:1.4.1" // Use to fetch tiles from a tile provider in your tests testImplementation "androidx.wear.tiles:tiles-testing:1.4.1" }
Kotlin
dependencies { // Use to implement support for wear tiles implementation("androidx.wear.tiles:tiles:1.4.1") // Use to utilize standard components and layouts in your tiles implementation("androidx.wear.protolayout:protolayout:1.2.1") // Use to utilize components and layouts with Material Design in your tiles implementation("androidx.wear.protolayout:protolayout-material:1.2.1") // Use to include dynamic expressions in your tiles implementation("androidx.wear.protolayout:protolayout-expression:1.2.1") // Use to preview wear tiles in your own app debugImplementation("androidx.wear.tiles:tiles-renderer:1.4.1") // Use to fetch tiles from a tile provider in your tests testImplementation("androidx.wear.tiles:tiles-testing:1.4.1") }
หัวข้อสำคัญ
ไทล์ไม่ได้สร้างขึ้นในลักษณะเดียวกับแอป 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 คุณจึงปรับเปลี่ยนตัวอย่างได้ตามปัจจัยต่างๆ เช่น ขนาดหน้าจอและภาษาของอุปกรณ์ ดูคำแนะนำเพิ่มเติมได้ในรายการตรวจสอบตัวอย่าง
เผยแพร่แอปและเพิ่มการ์ดลงในภาพสไลด์ของการ์ด (มีวิธีแสดงตัวอย่างการ์ดที่นักพัฒนาแอปใช้งานได้ง่ายขึ้นด้วย แต่ตอนนี้ให้ดำเนินการด้วยตนเอง)

ดูตัวอย่างที่สมบูรณ์ได้ที่ตัวอย่างโค้ดใน GitHub หรือ codelab
สร้าง UI สำหรับการ์ด
องค์ประกอบ UI แบบสื่อความหมายของ Material 3 สร้างขึ้นโดยใช้แนวทางแบบมีโครงสร้างซึ่งขับเคลื่อนโดยรูปแบบตัวสร้างที่ปลอดภัยต่อประเภทของ Kotlin
เลย์เอาต์
วิธีสร้างเลย์เอาต์มีดังนี้
เริ่มขอบเขต Material Design: เรียกใช้ฟังก์ชัน
materialScope()
โดยระบุcontext
และdeviceConfiguration
ที่จำเป็น คุณรวมพารามิเตอร์ที่ไม่บังคับได้ เช่นallowDynamicTheme
และdefaultColorScheme
allowDynamicTheme
เป็นtrue
โดยค่าเริ่มต้น และdefaultColorScheme
แสดงถึงColorScheme
ที่ใช้เมื่อสีแบบไดนามิกไม่พร้อมใช้งาน เช่น เมื่อผู้ใช้ปิดฟีเจอร์นี้ หรือเมื่ออุปกรณ์ไม่รองรับ หรือallowDynamicTheme
เป็นfalse
)สร้าง 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 ช่อง โดยเริ่มจากด้านบนลงล่าง
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(): ปุ่มขอบที่มีช่องเดียวสำหรับถ่ายภาพข้อความหรือเนื้อหาที่ยาวและกว้างคล้ายกัน
บัตรต่างๆ
- titleCard(): การ์ดชื่อที่มีช่อง 1-3 ช่อง โดยปกติแล้วจะเป็นแบบข้อความ
- appCard(): การ์ดแอปที่มีช่องสูงสุด 5 ช่อง โดยปกติจะเป็นแบบข้อความ
- textDataCard(): การ์ดข้อมูลที่มีช่องซ้อนกันแนวตั้งได้สูงสุด 3 ช่อง โดยปกติแล้วจะเป็นข้อความหรือตัวเลข
- iconDataCard(): การ์ดข้อมูลที่มีช่องซ้อนกันตามแนวตั้งได้สูงสุด 3 ช่อง โดยปกติแล้วจะเป็นข้อความหรือตัวเลขที่มีไอคอน
- graphicDataCard(): การ์ดข้อมูลกราฟิกที่มีช่องสำหรับข้อมูลกราฟิก เช่น ตัวบ่งชี้ความคืบหน้า และช่องซ้อนกันสูงสุด 2 ช่องในแนวตั้ง ซึ่งมักใช้สำหรับคำอธิบายที่เป็นข้อความ
สัญญาณบอกสถานะความคืบหน้า
- circularProgressIndicator(): ระบุความคืบหน้าสู่เป้าหมายโดยใช้องค์ประกอบแบบรัศมี
- segmentedCircularProgressIndicator(): ระบุความคืบหน้าในการบรรลุเป้าหมายโดยใช้องค์ประกอบวงกลมที่มีระยะต่างๆ
การจัดกลุ่มองค์ประกอบเลย์เอาต์
- buttonGroup(): เลย์เอาต์คอมโพเนนต์ที่วางคอมโพเนนต์ย่อยตามลำดับแนวนอน
- primaryLayout(): เลย์เอาต์แบบเต็มหน้าจอที่แสดงสไตล์เลย์เอาต์ M3 ที่แนะนําซึ่งปรับเปลี่ยนตามอุปกรณ์และดูแลการจัดวางองค์ประกอบต่างๆ พร้อมทั้งใช้ระยะขอบและระยะห่างจากขอบที่แนะนํา
ธีม
ใน Material 3 Expressive ระบบสีจะกำหนดโดยบทบาทสีมาตรฐาน 29 บทบาท ซึ่งจัดเป็น 6 กลุ่ม ได้แก่ หลัก รอง สามรอง ข้อผิดพลาด พื้นผิว และขอบ

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) |
คุณอาจต้องเปลี่ยนโทนสีเริ่มต้นสำหรับองค์ประกอบ UI บางรายการ เช่น คุณอาจต้องการให้ textEdgeButton
รายการหนึ่งใช้สีจากกลุ่ม "รอง" หรือ "รองลงมา" แทน "หลัก" เพื่อให้โดดเด่นและคอนทราสต์กันมากขึ้น
คุณปรับแต่งสีของคอมโพเนนต์ได้หลายวิธี ดังนี้
ใช้ฟังก์ชันตัวช่วยสำหรับสีที่กำหนดไว้ล่วงหน้า ใช้ฟังก์ชันตัวช่วย เช่น
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 )
ระบุบทบาทสีทดแทนอย่างชัดเจน สร้างออบเจ็กต์
ButtonColors
ของคุณเอง แล้วส่งไปยังคอมโพเนนต์ สำหรับการ์ด ให้ใช้ออบเจ็กต์CardColors
ที่เทียบเท่าtextEdgeButton( colors = ButtonColors( // the materialScope makes colorScheme available containerColor = colorScheme.secondary, iconColor = colorScheme.secondaryDim, labelColor = colorScheme.onSecondary, secondaryLabelColor = colorScheme.onSecondary ) // ... other parameters )
ระบุสีคงที่ (ใช้อย่างระมัดระวัง) แม้ว่าโดยทั่วไปแล้วเราจะแนะนำให้ระบุสีตามบทบาทเชิงความหมาย (เช่น
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
: แสดงผลข้อความโค้งในอาร์ค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(); }
เนื้อหาที่ขยายได้
Spannable
คือคอนเทนเนอร์ประเภทพิเศษที่จัดวางองค์ประกอบคล้ายกับข้อความ ซึ่งมีประโยชน์เมื่อคุณต้องการใช้รูปแบบอื่นกับสตริงย่อยเพียงรายการเดียวในบล็อกข้อความขนาดใหญ่ ซึ่งใช้ไม่ได้กับองค์ประกอบ Text
คอนเทนเนอร์ Spannable
เต็มไปด้วยรายการย่อย Span
ไม่อนุญาตให้มีองค์ประกอบย่อยอื่นๆ หรืออินสแตนซ์ Spannable
ที่ฝังอยู่
Span
ย่อยมี 2 ประเภทดังนี้
เช่น คุณอาจทำให้ "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 และในแอปที่ใช้ร่วมกันของนาฬิกาในโทรศัพท์
โปรดยืนยันรายละเอียดต่อไปนี้เกี่ยวกับการ์ดเพื่อช่วยให้ผู้ใช้ได้รับประโยชน์สูงสุดจากรูปภาพตัวอย่างนี้
- แสดงการออกแบบล่าสุด ตัวอย่างควรแสดงการออกแบบล่าสุดของการ์ดอย่างถูกต้อง
- ใช้ธีมสีแบบคงที่ ใช้ธีมสีแบบคงที่ของการ์ด ไม่ใช่ธีมแบบไดนามิก
- มีไอคอนแอป ตรวจสอบว่าไอคอนของแอปปรากฏที่ด้านบนของรูปภาพตัวอย่าง
- แสดงสถานะโหลด/เข้าสู่ระบบ ตัวอย่างควรแสดงสถานะ "โหลด" หรือ "เข้าสู่ระบบ" ที่ใช้งานได้อย่างเต็มรูปแบบ โดยหลีกเลี่ยงเนื้อหาที่ว่างเปล่าหรือเป็นตัวยึดตำแหน่ง
- ใช้ประโยชน์จากกฎการแก้ไขทรัพยากรเพื่อการปรับแต่ง (ไม่บังคับ) ลองใช้กฎความละเอียดของทรัพยากรของ Android เพื่อแสดงตัวอย่างที่ตรงกับการตั้งค่าขนาดการแสดงผล ภาษา หรือภาษาท้องถิ่นของอุปกรณ์ ซึ่งจะเป็นประโยชน์อย่างยิ่งหากลักษณะที่ปรากฏของการ์ดแตกต่างกันไปตามอุปกรณ์