Để bắt đầu cung cấp thẻ thông tin từ ứng dụng, hãy đưa các phần phụ thuộc sau đây vào tệp build.gradle
của ứng dụng.
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") }
Khái niệm chính
Thẻ thông tin không được tạo theo cách tương tự như ứng dụng Android và sử dụng các khái niệm khác nhau:
- Mẫu bố cục: Xác định cách sắp xếp tổng thể các thành phần hình ảnh trên màn hình. Thẻ thông tin sử dụng mẫu bố cục
EdgeContentLayout
, bao gồm chỉ báo tiến trình xung quanh cạnh màn hình hoặcPrimaryLayout
không hiển thị chỉ báo này. - Thành phần bố cục: Biểu thị một thành phần đồ hoạ riêng lẻ, chẳng hạn như
Button
hoặcChip
, hoặc một số thành phần như vậy được nhóm lại với nhau bằngColumn
,MultiButtonLayout
,MultiSlotLayout
hoặc tương tự. Các thành phần này được nhúng trong một mẫu bố cục. - Tài nguyên: Các đối tượng
ResourceBuilders.Resources
bao gồm một bản đồ gồm các cặp khoá-giá trị của tài nguyên Android (hình ảnh) cần thiết để hiển thị bố cục và một phiên bản. - Dòng thời gian: Đối tượng
TimelineBuilders.Timeline
là danh sách một hoặc nhiều thực thể của một đối tượng bố cục. Bạn có thể cung cấp nhiều cơ chế và biểu thức để cho biết thời điểm trình kết xuất nên chuyển đổi từ đối tượng bố cục này sang đối tượng bố cục khác, chẳng hạn như để ngừng hiển thị bố cục tại một thời điểm cụ thể. - Trạng thái: Cấu trúc dữ liệu thuộc loại
StateBuilders.State
được truyền giữa thẻ thông tin và ứng dụng để cho phép hai thành phần này giao tiếp với nhau. Ví dụ: nếu người dùng nhấn vào một nút trên thẻ thông tin, thì trạng thái sẽ chứa mã nhận dạng của nút đó. Bạn cũng có thể trao đổi các loại dữ liệu bằng cách sử dụng bản đồ. - Thẻ thông tin: Đối tượng
TileBuilders.Tile
đại diện cho một thẻ thông tin, bao gồm tiến trình, mã phiên bản tài nguyên, khoảng thời gian làm mới và trạng thái. - Protolayout: Thuật ngữ này xuất hiện trong tên của nhiều lớp liên quan đến thẻ thông tin và đề cập đến thư viện Wear OS Protolayout, một thư viện đồ hoạ được sử dụng trên nhiều nền tảng Wear OS.
Tạo ô
Để cung cấp thẻ thông tin từ ứng dụng, hãy triển khai một dịch vụ thuộc loại TileService
và đăng ký dịch vụ đó trong tệp kê khai. Từ đó, hệ thống yêu cầu các thẻ thông tin cần thiết trong các lệnh gọi đến onTileRequest()
và tài nguyên trong các lệnh gọi đến onTileResourcesRequest()
.
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() ) }
Tiếp theo, hãy thêm một dịch vụ bên trong thẻ <application>
của tệp 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>
Bộ lọc quyền và ý định sẽ đăng ký dịch vụ này làm trình cung cấp thẻ thông tin.
Người dùng sẽ thấy biểu tượng, nhãn, nội dung mô tả và tài nguyên xem trước khi định cấu hình thẻ thông tin trên điện thoại hoặc đồng hồ.
Triển khai ứng dụng và thêm Thẻ thông tin vào Băng chuyền thẻ thông tin (cũng có cách xem trước Thẻ thông tin phù hợp hơn với nhà phát triển, nhưng hiện tại, bạn chỉ cần làm theo cách thủ công).
Hình 1. Thẻ thông tin "Hello World" (Xin chào thế giới).
Để xem ví dụ đầy đủ, hãy xem mã mẫu trên GitHub hoặc lớp học lập trình.
Tạo giao diện người dùng cho thẻ thông tin
Bố cục của thẻ thông tin được viết bằng mẫu trình tạo. Bố cục của thẻ thông tin được thiết kế giống một cây bao gồm các vùng chứa bố cục và các phần tử của bố cục cơ bản. Mỗi phần tử của bố cục có các thuộc tính mà bạn có thể thiết lập thông qua nhiều phương thức setter.
Phần tử của bố cục cơ bản
Dưới đây là các phần tử hình ảnh từ thư viện protolayout
được hỗ trợ, cùng với các thành phần Material:
Text
: hiển thị một chuỗi văn bản (không bắt buộc phải gói văn bản đó).Image
: hiển thị một hình ảnh.Spacer
: cung cấp khoảng đệm giữa các phần tử hoặc có thể hoạt động như một đường phân chia khi bạn đặt màu nền.
Thành phần Material
Ngoài các phần tử cơ bản, thư viện protolayout-material
còn cung cấp các thành phần đảm bảo thiết kế thẻ thông tin phù hợp với các đề xuất về giao diện người dùng của Material Design.
Button
: thành phần hình tròn có thể nhấp vào, được thiết kế để chứa một biểu tượng.Chip
: thành phần có hình dạng sân vận động có thể nhấp vào, được thiết kế để chứa tối đa 2 dòng văn bản và một biểu tượng không bắt buộc.CompactChip
: thành phần có hình dạng sân vận động có thể nhấp vào, được thiết kế để chứa một dòng văn bản.TitleChip
: thành phần có hình dạng sân vận động có thể nhấp vào, tương tự nhưChip
nhưng có chiều cao lớn hơn để chứa đủ văn bản tiêu đề.CircularProgressIndicator
: chỉ báo tiến trình hình tròn có thể đặt vào bên trongEdgeContentLayout
để hiển thị tiến trình xung quanh các cạnh của màn hình.
Vùng chứa bố cục
Các vùng chứa sau đây được hỗ trợ, cùng với Bố cục Material:
Row
: sắp xếp lần lượt từng phần tử con theo chiều ngang.Column
: sắp xếp lần lượt từng phần tử con theo chiều dọc.Box
: xếp chồng các phần tử con lên nhau.Arc
: sắp xếp các phần tử con trong một hình tròn.Spannable
: áp dụngFontStyles
cụ thể cho các phần văn bản cùng với văn bản và hình ảnh xen kẽ. Để biết thêm thông tin, hãy xem phần Spannable.
Mỗi vùng chứa có thể chứa một hoặc nhiều phần tử con, mà chính các phần tử đó cũng có thể là vùng chứa. Ví dụ: Column
có thể chứa nhiều phần tử Row
dưới dạng phần tử con, từ đó tạo ra một bố cục giống như lưới.
Ví dụ: thẻ thông tin có 1 bố cục vùng chứa và 2 phần tử bố cục con có thể có dạng như sau:
Kotlin
private fun myLayout(): LayoutElement = Row.Builder() .setWidth(wrap()) .setHeight(expand()) .setVerticalAlignment(VERTICAL_ALIGN_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(); }
Bố cục Material
Ngoài bố cục cơ bản, thư viện protolayout-material
còn cung cấp một số bố cục ổn định để giữ những phần tử trong các "khung" cụ thể.
PrimaryLayout
: đặt một hành động chínhCompactChip
ở dưới cùng với nội dung nằm ở giữa phía trên.MultiSlotLayout
: đặt nhãn chính và nhãn phụ có nội dung không bắt buộc nằm ở giữa vàCompactChip
không bắt buộc ở dưới cùng.MultiButtonLayout
: đặt một nhóm các nút được sắp xếp theo nguyên tắc Material.EdgeContentLayout
: đặt nội dung xung quanh cạnh màn hình, chẳng hạn nhưCircularProgressIndicator
. Khi dùng bố cục này, nội dung trong bố cục sẽ tự động có lề và khoảng đệm thích hợp.
Vòng cung
Dưới đây là các vùng chứa con Arc
được hỗ trợ:
ArcLine
: hiển thị một đường cong xung quanh Vòng cung.ArcText
: hiển thị văn bản cong trong Vòng cung.ArcAdapter
: hiển thị một phần tử bố cục cơ bản trong vòng cung, được vẽ tại tiếp tuyến của vòng cung.
Để biết thêm thông tin, hãy xem tài liệu tham khảo cho từng loại phần tử.
Đối tượng sửa đổi
Bạn có thể tuỳ ý áp dụng các công cụ sửa đổi cho mỗi phần tử bố cục có sẵn. Hãy sử dụng các công cụ sửa đổi này cho những mục đích sau:
- Thay đổi giao diện hình ảnh của bố cục. Ví dụ: thêm nền, đường viền hoặc khoảng đệm vào phần tử bố cục.
- Thêm siêu dữ liệu về bố cục. Ví dụ: thêm một đối tượng sửa đổi ngữ nghĩa vào phần tử bố cục để sử dụng với trình đọc màn hình.
- Thêm chức năng. Ví dụ: thêm vào phần tử bố cục một công cụ sửa đổi có thể nhấp để ô có khả năng tương tác. Để biết thêm thông tin, hãy xem bài viết Tương tác với thẻ thông tin.
Ví dụ: chúng ta có thể tuỳ chỉnh giao diện và siêu dữ liệu mặc định của Image
, như trong mã mẫu sau:
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
Spannable
là loại vùng chứa đặc biệt có nhiệm vụ sắp xếp các phần tử tương tự như văn bản. Vùng chứa này hữu ích khi bạn muốn áp dụng kiểu khác cho duy nhất một chuỗi con trong khối văn bản lớn hơn – đây là điều không thể áp dụng với phần tử Text
.
Vùng chứa Spannable
chứa phần tử con Span
. Bạn không được phép dùng các phần tử con khác hoặc các thực thể Spannable
lồng nhau.
Có hai loại phần tử con Span
:
Ví dụ: bạn có thể in nghiêng từ "world" (mọi người) trong thẻ thông tin "Hello world" (Chào mọi người) và chèn một hình ảnh giữa các từ, như trong mã mẫu sau đây:
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(); }
Làm việc với các tài nguyên
Ô không có quyền truy cập vào bất kỳ tài nguyên nào trong ứng dụng của bạn. Điều này có nghĩa là bạn không thể chuyển mã nhận dạng hình ảnh Android vào phần tử bố cục Image
và kỳ vọng nó sẽ thực hiện phân giải. Thay vào đó, hãy ghi đè phương thức onTileResourcesRequest()
và cung cấp mọi tài nguyên theo cách thủ công.
Có 2 cách để cung cấp hình ảnh trong phương thức onTileResourcesRequest()
:
- Cung cấp tài nguyên có thể vẽ bằng cách sử dụng
setAndroidResourceByResId()
. - Cung cấp hình ảnh động dưới dạng
ByteArray
bằng cách dùngsetInlineResource()
.
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() ); }
Đề xuất cho bạn
- Lưu ý: văn bản có đường liên kết sẽ hiện khi JavaScript tắt
- Di chuyển sang không gian tên ProtoLayout
ConstraintLayout
trong Compose- Tạo ô Cài đặt nhanh tuỳ chỉnh cho ứng dụng