หากต้องการเริ่มแสดงการ์ดจากแอป ให้รวมทรัพยากร 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 รายการ คุณสามารถระบุกลไกและนิพจน์ต่างๆ เพื่อระบุว่าเมื่อใดที่โปรแกรมแสดงผลควรเปลี่ยนจากออบเจ็กต์เลย์เอาต์หนึ่งไปยังอีกออบเจ็กต์หนึ่ง เช่น เพื่อหยุดแสดงเลย์เอาต์ในเวลาที่เจาะจง - State: โครงสร้างข้อมูลประเภท
StateBuilders.Stateที่ส่งระหว่างการ์ดและแอป เพื่อให้คอมโพเนนต์ทั้ง 2 รายการสื่อสารกันได้ เช่น หากมีการแตะปุ่มบนการ์ด สถานะจะเก็บรหัสของปุ่มไว้ นอกจากนี้ คุณยังแลกเปลี่ยนประเภทข้อมูลโดยใช้แผนที่ได้ด้วย - ไทล์: ออบเจ็กต์
TileBuilders.Tileที่แสดงถึงไทล์ ซึ่งประกอบด้วยไทม์ไลน์ รหัสเวอร์ชันของทรัพยากร ช่วงเวลาความใหม่ และสถานะ - Protolayout: คำนี้ปรากฏในชื่อของคลาสต่างๆ ที่เกี่ยวข้องกับไทล์ และหมายถึงไลบรารี Wear OS Protolayout ซึ่งเป็นไลบรารีกราฟิกที่ใช้ในแพลตฟอร์ม 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จัดการทรัพยากรโดยอัตโนมัติ (finalonTileResourcesRequest()) โปรดอย่าลบล้าง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 จึงสามารถปรับเปลี่ยนตัวอย่างตามปัจจัยต่างๆ เช่น ขนาดหน้าจอและภาษาของอุปกรณ์ได้ ดูคำแนะนำเพิ่มเติมได้ที่รายการตรวจสอบตัวอย่าง
ทำให้แอปใช้งานได้ และเพิ่มการ์ดลงในภาพสไลด์ของการ์ด (มีวิธีแสดงตัวอย่างการ์ดที่เหมาะกับนักพัฒนาแอปมากกว่าด้วย แต่ตอนนี้ให้ทำด้วยตนเองไปก่อน)
ดูตัวอย่างที่เสร็จสมบูรณ์ได้ที่ตัวอย่างโค้ดใน GitHub หรือ Codelab
สร้าง UI สำหรับการ์ด
องค์ประกอบ UI ของ Material 3 Expressive สร้างขึ้นโดยใช้วิธีการที่มีโครงสร้างซึ่งขับเคลื่อนโดยรูปแบบเครื่องมือสร้างที่ปลอดภัยในการกำหนดประเภทของ Kotlin
การจัดวาง
ดูคำแนะนำเกี่ยวกับหลักการออกแบบที่อยู่เบื้องหลังการสร้างเลย์เอาต์การ์ดที่มีประสิทธิภาพและปรับเปลี่ยนตามพื้นที่โฆษณาได้ที่เลย์เอาต์ทั่วไปสำหรับการ์ด
หากต้องการสร้างเลย์เอาต์ ให้ทำดังนี้
เริ่มต้นขอบเขต Material Design: เรียกใช้ฟังก์ชัน
materialScope()โดยระบุcontextและdeviceConfigurationที่จำเป็น คุณสามารถรวมพารามิเตอร์ที่ไม่บังคับ เช่นallowDynamicThemeและdefaultColorSchemeallowDynamicThemeจะเป็นtrueโดยค่าเริ่มต้น และdefaultColorSchemeจะแสดงColorSchemeที่ใช้เมื่อสีแบบไดนามิกไม่พร้อมใช้งาน เช่น เมื่อผู้ใช้ปิดฟีเจอร์นี้ หรือเมื่ออุปกรณ์ไม่รองรับ หรือallowDynamicThemeเป็นfalse) เมื่อใช้ API ของImageResourceเช่นbackgroundImage()ในTileServiceที่กำหนดเอง ให้เรียกใช้materialScopeWithResources()แทนสร้าง UI ภายในขอบเขต: ต้องกำหนดคอมโพเนนต์ UI ทั้งหมดสำหรับเลย์เอาต์การ์ดหนึ่งๆ ภายใน Lambda ของการเรียก materialScope() ระดับบนสุดรายการเดียว ฟังก์ชันคอมโพเนนต์เหล่านี้ เช่น
primaryLayout()และtextEdgeButton()เป็นฟังก์ชันส่วนขยายในMaterialScopeและจะใช้ได้เมื่อเรียกใช้ในขอบเขต Receiver นี้เท่านั้น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 ช่อง โดยเรียงจากบนลงล่างดังนี้
titleSlotโดยปกติจะใช้สำหรับชื่อหรือส่วนหัวหลักmainSlotสำหรับเนื้อหาหลักbottomSlotซึ่งมักใช้สำหรับการดำเนินการหรือข้อมูลเสริม และปุ่มขอบจะปรากฏที่นี่ด้วย
เนื้อหาของแต่ละช่องมีดังนี้
titleSlot(ไม่บังคับ): โดยปกติแล้วจะเป็นคำไม่กี่คำที่สร้างโดยtext()mainSlot(บังคับ): คอมโพเนนต์ที่จัดระเบียบเป็นโครงสร้าง เช่น แถว คอลัมน์ และกลุ่มปุ่ม นอกจากนี้ยังฝังคอมโพเนนต์เหล่านี้ซ้อนกันได้ เช่น คอลัมน์สามารถมีแถวได้bottomSlot(ไม่บังคับ): โดยปกติแล้วจะใส่ปุ่มที่ชิดขอบหรือป้ายกำกับข้อความ
เนื่องจากไทล์เลื่อนไม่ได้ จึงไม่มีคอมโพเนนต์สำหรับการแบ่งหน้า การเลื่อน หรือการจัดการรายการเนื้อหาที่ยาว ตรวจสอบว่าเนื้อหายังคงมองเห็นได้เมื่อขนาดแบบอักษรเพิ่มขึ้นหรือข้อความยาวขึ้นเนื่องจากการแปล
คอมโพเนนต์ UI
ไลบรารี protolayout-material3 มีคอมโพเนนต์จำนวนมากที่ออกแบบตามข้อกำหนดเฉพาะของ Material 3 Expressive และคำแนะนำเกี่ยวกับอินเทอร์เฟซผู้ใช้
ปุ่ม
ปุ่มจะเน้นการดำเนินการเป็นหลัก โดยจะทำหน้าที่ทริกเกอร์การดำเนินการที่เฉพาะเจาะจง เนื้อหาของปุ่มแต่ละปุ่ม เช่น ไอคอนหรือข้อความสั้นๆ จะระบุการดำเนินการ
- textButton(): ปุ่มที่มีช่องเดียวสำหรับเนื้อหาข้อความ (สั้น)
- iconButton(): ปุ่มที่มีช่องเดียวเพื่อแสดงไอคอน
- avatarButton(): ปุ่มอวาตาร์รูปทรงแคปซูลที่มีช่องสูงสุด 3 ช่องสำหรับใส่เนื้อหาที่แสดงป้ายกำกับและป้ายกำกับรองที่ซ้อนกันในแนวตั้ง และรูปภาพ (อวาตาร์) ข้างๆ
- imageButton(): ปุ่มรูปภาพที่คลิกได้ซึ่งไม่มีช่องเพิ่มเติม มีเพียงรูปภาพ (เช่น
backgroundImageเป็นพื้นหลัง) - compactButton(): ปุ่มขนาดกะทัดรัดที่มีช่องให้เลือกสูงสุด 2 ช่องเพื่อใช้เนื้อหาที่ซ้อนกันในแนวนอนซึ่งแสดงไอคอนและข้อความข้างๆ
- button(): ปุ่มรูปทรงแคปซูลที่มีช่องให้ใส่เนื้อหาได้สูงสุด 3 ช่อง ซึ่งแสดงป้ายกำกับและป้ายกำกับรองที่ซ้อนกันในแนวตั้ง และไอคอนข้างๆ
ปุ่ม Edge
ปุ่มขอบเป็นปุ่มเฉพาะแบบเต็มความกว้างที่ยึดไว้ที่ด้านล่างของหน้าจอกลมของนาฬิกา ซึ่งแสดงถึงการดำเนินการที่สำคัญที่สุดที่ต้องทำจากหน้าจอการ์ดปัจจุบัน
- 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 และต้องสร้างคอมโพเนนต์ภายในนั้น คอมโพเนนต์จึงใช้สีจากรูปแบบโดยอัตโนมัติ วิธีนี้ช่วยให้องค์ประกอบ 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 หนึ่งใช้สีจากกลุ่ม "รอง" หรือ "ตติยภูมิ" แทน "หลัก" เพื่อให้โดดเด่นและมีคอนทราสต์ที่ดีขึ้น
คุณปรับแต่งสีของคอมโพเนนต์ได้หลายวิธี ดังนี้
ใช้ฟังก์ชันตัวช่วยสำหรับสีที่กำหนดไว้ล่วงหน้า ใช้ฟังก์ชันตัวช่วย เช่น
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.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: แสดงผลข้อความโค้งในส่วนโค้ง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()
Spannable
Spannable เป็นคอนเทนเนอร์ประเภทพิเศษที่จัดวางองค์ประกอบคล้ายกับข้อความ ซึ่งจะมีประโยชน์เมื่อคุณต้องการใช้รูปแบบที่แตกต่างกันกับสตริงย่อยเพียงรายการเดียวในบล็อกข้อความขนาดใหญ่ ซึ่งเป็นสิ่งที่ไม่สามารถทำได้ด้วยองค์ประกอบ Text
คอนเทนเนอร์ Spannable มีรายการย่อย Span รายการ ไม่อนุญาตให้มีองค์ประกอบย่อยอื่นๆ หรืออินสแตนซ์ Spannable ที่ซ้อนกัน
บุตรหลานใน Span มี 2 ประเภท ได้แก่
เช่น คุณสามารถทำให้คำว่า "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 และในแอปที่ใช้ร่วมกันของนาฬิกาในโทรศัพท์
โปรดตรวจสอบรายละเอียดต่อไปนี้เกี่ยวกับหน้าต่างของคุณเพื่อช่วยให้ผู้ใช้ได้รับประโยชน์สูงสุดจากรูปภาพตัวอย่างนี้
- แสดงการออกแบบล่าสุด ตัวอย่างควรแสดงการออกแบบล่าสุดของไทล์อย่างถูกต้อง
- ใช้มิติข้อมูลที่แนะนำ รูปภาพตัวอย่างควรมีขนาด 400 x 400 พิกเซลเพื่อให้ได้คุณภาพการแสดงผลที่ดีที่สุดและมอบประสบการณ์การใช้งานที่ดีแก่ผู้ใช้
- ใช้ธีมสีแบบคงที่ ใช้ธีมสีแบบคงที่ของการ์ด ไม่ใช่แบบไดนามิก
- มีไอคอนแอป ตรวจสอบว่าไอคอนของแอปปรากฏที่ด้านบนของรูปภาพตัวอย่าง
- แสดงสถานะโหลด/เข้าสู่ระบบ ตัวอย่างควรแสดงสถานะ "โหลดแล้ว" หรือ "เข้าสู่ระบบแล้ว" ที่ทำงานได้อย่างสมบูรณ์ โดยหลีกเลี่ยงเนื้อหาที่ว่างเปล่าหรือเนื้อหาตัวยึดตำแหน่ง
- ใช้ประโยชน์จากกฎการแก้ไขทรัพยากรเพื่อการปรับแต่ง (ไม่บังคับ) ลองใช้กฎการแก้ไขทรัพยากรของ Android เพื่อแสดงตัวอย่างที่ตรงกับการตั้งค่าขนาดการแสดงผล ภาษา หรือภาษาของอุปกรณ์ ซึ่งจะเป็นประโยชน์อย่างยิ่งหากลักษณะที่ปรากฏของไทล์แตกต่างกันไปในแต่ละอุปกรณ์