หากต้องการเริ่มให้บริการการ์ดจากแอป ให้รวมไลบรารีต่อไปนี้ไว้ในไฟล์ build.gradle
ของแอป
Groovy
dependencies { // Use to implement support for wear tiles implementation "androidx.wear.tiles:tiles:1.5.0-alpha04" // Use to utilize standard components and layouts in your tiles implementation "androidx.wear.protolayout:protolayout:1.3.0-alpha04" // Use to utilize components and layouts with Material Design in your tiles implementation "androidx.wear.protolayout:protolayout-material:1.3.0-alpha04" // Use to include dynamic expressions in your tiles implementation "androidx.wear.protolayout:protolayout-expression:1.3.0-alpha04" // Use to preview wear tiles in your own app debugImplementation "androidx.wear.tiles:tiles-renderer:1.5.0-alpha04" // Use to fetch tiles from a tile provider in your tests testImplementation "androidx.wear.tiles:tiles-testing:1.5.0-alpha04" }
Kotlin
dependencies { // Use to implement support for wear tiles implementation("androidx.wear.tiles:tiles:1.5.0-alpha04") // Use to utilize standard components and layouts in your tiles implementation("androidx.wear.protolayout:protolayout:1.3.0-alpha04") // Use to utilize components and layouts with Material Design in your tiles implementation("androidx.wear.protolayout:protolayout-material:1.3.0-alpha04") // Use to include dynamic expressions in your tiles implementation("androidx.wear.protolayout:protolayout-expression:1.3.0-alpha04") // Use to preview wear tiles in your own app debugImplementation("androidx.wear.tiles:tiles-renderer:1.5.0-alpha04") // Use to fetch tiles from a tile provider in your tests testImplementation("androidx.wear.tiles:tiles-testing:1.5.0-alpha04") }
สร้างการ์ด
หากต้องการระบุการ์ดจากแอปพลิเคชัน ให้สร้างคลาสที่ขยายจาก TileService
และใช้เมธอดตามที่แสดงในตัวอย่างโค้ดต่อไปนี้
class MyTileService : TileService() { override fun onTileRequest(requestParams: RequestBuilders.TileRequest) = Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, "Hello World!") .setTypography(Typography.TYPOGRAPHY_BODY1) .setColor(argb(0xFFFFFFFF.toInt())) .build() ) ) .build() ) override fun onTileResourcesRequest(requestParams: ResourcesRequest) = Futures.immediateFuture( Resources.Builder() .setVersion(RESOURCES_VERSION) .build() ) }
ถัดไป ให้เพิ่มบริการภายในแท็ก <application>
ของไฟล์ AndroidManifest.xml
<service android:name=".snippets.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 จะลงทะเบียนบริการนี้ในฐานะผู้ให้บริการไทล์
ไอคอน ป้ายกำกับ และคำอธิบายจะแสดงต่อผู้ใช้เมื่อกำหนดค่าการ์ดในโทรศัพท์หรือนาฬิกา
ใช้แท็กข้อมูลเมตาของตัวอย่างเพื่อแสดงตัวอย่างการ์ดเมื่อกําหนดค่าในโทรศัพท์
ภาพรวมวงจรชีวิตของบริการแผนที่ย่อย
เมื่อสร้างและประกาศ TileService
ในไฟล์ Manifest ของแอปแล้ว คุณจะตอบสนองต่อการเปลี่ยนแปลงสถานะของบริการการ์ดได้
TileService
เป็นบริการที่มีผลผูกพัน TileService
ของคุณจะได้รับการเชื่อมโยงเนื่องจากคำขอแอปหรือในกรณีที่ระบบต้องสื่อสารกับ TileService
วงจรชีวิตของบริการที่เชื่อมโยงโดยทั่วไปจะมีเมธอดการเรียกกลับ 4 รายการ ได้แก่ onCreate()
, onBind()
, onUnbind()
และ onDestroy()
ระบบจะเรียกใช้เมธอดเหล่านี้ทุกครั้งที่บริการเข้าสู่ระยะวงจรใหม่
นอกจากการเรียกกลับที่ควบคุมวงจรบริการที่เชื่อมโยงแล้ว คุณยังใช้เมธอดอื่นๆ สำหรับวงจร TileService
โดยเฉพาะได้ด้วย บริการการ์ดทั้งหมดต้องใช้ onTileRequest()
และ onTileResourcesRequest()
เพื่อตอบสนองคำขออัปเดตจากระบบ
onTileAddEvent()
: ระบบจะเรียกใช้เมธอดนี้เฉพาะเมื่อผู้ใช้เพิ่มการ์ดของคุณเป็นครั้งแรก และในกรณีที่ผู้ใช้นำการ์ดออกและเพิ่มการ์ดอีกครั้ง นี่เป็นเวลาที่เหมาะที่สุดในการเริ่มต้นใช้งานแบบครั้งเดียวonTileAddEvent()
จะเรียกใช้เฉพาะเมื่อมีการกำหนดค่าชุดการ์ดใหม่เท่านั้น ไม่ใช่ทุกครั้งที่ระบบสร้างการ์ด ตัวอย่างเช่น เมื่อรีบูตหรือเปิดอุปกรณ์ ระบบจะไม่เรียกใช้onTileAddEvent()
สำหรับการ์ดที่เพิ่มไว้แล้ว คุณใช้getActiveTilesAsync()
แทนได้เพื่อดูภาพรวมของการ์ดที่เป็นของคุณซึ่งใช้งานอยู่onTileRemoveEvent()
: ระบบจะเรียกใช้เมธอดนี้เฉพาะในกรณีที่ผู้ใช้นำการ์ดของคุณออกonTileEnterEvent()
: ระบบจะเรียกใช้เมธอดนี้เมื่อการ์ดที่ผู้ให้บริการรายนี้ระบุปรากฏบนหน้าจอonTileLeaveEvent()
: ระบบจะเรียกใช้เมธอดนี้เมื่อการ์ดที่ผู้ให้บริการรายนี้ระบุไม่อยู่ในมุมมองบนหน้าจอonTileRequest()
: ระบบจะเรียกใช้เมธอดนี้เมื่อระบบขอไทม์ไลน์ใหม่จากผู้ให้บริการรายนี้onTileResourcesRequest()
: ระบบจะเรียกใช้เมธอดนี้เมื่อระบบขอแพ็กเกจทรัพยากรจากผู้ให้บริการรายนี้ กรณีนี้อาจเกิดขึ้นเมื่อโหลดไทล์เป็นครั้งแรกหรือเมื่อใดก็ตามที่เวอร์ชันทรัพยากรมีการเปลี่ยนแปลง
ค้นหาว่าการ์ดใดที่ใช้งานอยู่
การ์ดที่ใช้งานอยู่คือการ์ดที่เพิ่มไว้เพื่อแสดงบนนาฬิกา ใช้เมธอดแบบคงที่ getActiveTilesAsync()
ของ TileService
เพื่อค้นหาว่าการ์ดใดของแอปคุณที่ใช้งานอยู่
สร้าง UI สำหรับการ์ด
เลย์เอาต์ของการ์ดเขียนโดยใช้รูปแบบ Builder เลย์เอาต์ของการ์ดจะสร้างขึ้นเหมือนต้นไม้ที่ประกอบด้วยคอนเทนเนอร์เลย์เอาต์และองค์ประกอบเลย์เอาต์พื้นฐาน องค์ประกอบเลย์เอาต์แต่ละรายการมีพร็อพเพอร์ตี้ ซึ่งคุณตั้งค่าได้ผ่านเมธอด setter ต่างๆ
องค์ประกอบเลย์เอาต์พื้นฐาน
ระบบรองรับองค์ประกอบภาพต่อไปนี้จากคลัง protolayout
พร้อมกับคอมโพเนนต์ Material
Text
: แสดงผลสตริงข้อความโดยตัดขึ้นบรรทัดใหม่หรือไม่ก็ได้Image
: แสดงผลรูปภาพSpacer
: ให้ระยะห่างจากขอบระหว่างองค์ประกอบหรือทำหน้าที่เป็นตัวแบ่งเมื่อคุณตั้งค่าสีพื้นหลัง
คอมโพเนนต์ของ Material
นอกจากองค์ประกอบพื้นฐานแล้ว ไลบรารี protolayout-material
ยังมีคอมโพเนนต์ที่ช่วยให้การออกแบบการ์ดสอดคล้องกับคําแนะนําของอินเทอร์เฟซผู้ใช้ Material Design
Button
: คลิกได้ คอมโพเนนต์วงกลมที่ออกแบบมาเพื่อใส่ไอคอนChip
: คอมโพเนนต์รูปทรงสนามกีฬาที่คลิกได้ซึ่งออกแบบมาเพื่อใส่ข้อความได้สูงสุด 2 บรรทัดและมีไอคอน (ไม่บังคับ)CompactChip
: คอมโพเนนต์รูปทรงสนามกีฬาที่คลิกได้ซึ่งออกแบบมาเพื่อใส่บรรทัดข้อความTitleChip
: คอมโพเนนต์รูปทรงสนามกีฬาที่คลิกได้ ซึ่งคล้ายกับChip
แต่มีความสูงมากกว่าเพื่อให้รองรับข้อความชื่อCircularProgressIndicator
: สัญญาณบอกสถานะความคืบหน้าแบบวงกลมที่สามารถวางไว้ในEdgeContentLayout
เพื่อแสดงความคืบหน้ารอบขอบของหน้าจอ
คอนเทนเนอร์เลย์เอาต์
ระบบรองรับคอนเทนเนอร์ต่อไปนี้พร้อมกับเลย์เอาต์ Material
Row
: จัดเรียงองค์ประกอบย่อยในแนวนอนทีละรายการColumn
: จัดวางองค์ประกอบย่อยในแนวตั้งทีละรายการBox
: วางซ้อน องค์ประกอบย่อยทับกันArc
: จัดวางองค์ประกอบย่อยเป็นวงกลมSpannable
: ใช้รูปแบบที่เฉพาะเจาะจงFontStyles
กับส่วนของข้อความพร้อมกับการแทรกข้อความและรูปภาพ ดูข้อมูลเพิ่มเติมได้ที่Spannables
คอนเทนเนอร์ทุกรายการมีคอนเทนเนอร์ย่อยได้อย่างน้อย 1 รายการ ซึ่งคอนเทนเนอร์ย่อยเองก็เป็นคอนเทนเนอร์ได้เช่นกัน เช่น Column
อาจมีองค์ประกอบ Row
หลายรายการเป็นองค์ประกอบย่อย ซึ่งส่งผลให้มีเลย์เอาต์คล้ายตารางกริด
ตัวอย่างเช่น ไทล์ที่มีเลย์เอาต์คอนเทนเนอร์และองค์ประกอบเลย์เอาต์ย่อย 2 รายการอาจมีลักษณะดังนี้
Kotlin
private fun myLayout(): LayoutElement = Row.Builder() .setWidth(wrap()) .setHeight(expand()) .setVerticalAlignment(VALIGN_BOTTOM) .addContent(Text.Builder() .setText("Hello world") .build() ) .addContent(Image.Builder() .setResourceId("image_id") .setWidth(dp(24f)) .setHeight(dp(24f)) .build() ).build()
Java
private LayoutElement myLayout() { return new Row.Builder() .setWidth(wrap()) .setHeight(expand()) .setVerticalAlignment(VALIGN_BOTTOM) .addContent(new Text.Builder() .setText("Hello world") .build() ) .addContent(new Image.Builder() .setResourceId("image_id") .setWidth(dp(24f)) .setHeight(dp(24f)) .build() ).build(); }
เลย์เอาต์ของวัสดุ
นอกจากเลย์เอาต์พื้นฐานแล้ว คลัง protolayout-material
ยังมีเลย์เอาต์ที่เน้นการแสดงผลตามแนวคิดบางอย่างซึ่งออกแบบมาเพื่อรองรับองค์ประกอบใน "ช่อง" ที่เฉพาะเจาะจง
PrimaryLayout
: จัดตําแหน่งการดําเนินการหลักCompactChip
รายการเดียวที่ด้านล่างโดยมีเนื้อหาอยู่ตรงกลางด้านบนMultiSlotLayout
: วางป้ายกำกับหลักและรองโดยมีเนื้อหาที่ไม่บังคับคั่นอยู่ตรงกลาง และCompactChip
ที่ไม่บังคับที่ด้านล่างMultiButtonLayout
: จัดตำแหน่งชุดปุ่มที่จัดเรียงตามหลักเกณฑ์ของ Material DesignEdgeContentLayout
: จัดวางเนื้อหาไว้รอบๆ ขอบของหน้าจอ เช่นCircularProgressIndicator
เมื่อใช้เลย์เอาต์นี้ เนื้อหาภายในจะมีระยะขอบและระยะห่างจากขอบที่เหมาะสมโดยอัตโนมัติ
ส่วนโค้ง
ระบบรองรับ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() ); }
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ย้ายข้อมูลไปยังเนมสเปซ ProtoLayout
ConstraintLayout
ในเขียน- สร้างการ์ดการตั้งค่าด่วนที่กำหนดเองสำหรับแอป