Để bắt đầu cung cấp ô 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.1.0" // Use to utilize components and layouts with Material Design in your tiles implementation "androidx.wear.tiles:tiles-material:1.1.0" // Use to preview wear tiles in your own app debugImplementation "androidx.wear.tiles:tiles-renderer:1.1.0" // Use to fetch tiles from a tile provider in your tests testImplementation "androidx.wear.tiles:tiles-testing:1.1.0" }
Kotlin
dependencies { // Use to implement support for wear tiles implementation("androidx.wear.tiles:tiles:1.1.0") // Use to utilize components and layouts with Material design in your tiles implementation("androidx.wear.tiles:tiles-material:1.1.0") // Use to preview wear tiles in your own app debugImplementation("androidx.wear.tiles:tiles-renderer:1.1.0") // Use to fetch tiles from a tile provider in your tests testImplementation("androidx.wear.tiles:tiles-testing:1.1.0") }
Tạo ô
Để cung cấp ô từ ứng dụng, hãy tạo một class (lớp) giúp mở rộng TileService
và triển khai các phương thức, như trong mã mẫu sau:
Kotlin
private val RESOURCES_VERSION = "1" class MyTileService : TileService() { override fun onTileRequest(requestParams: RequestBuilders.TileRequest) = Futures.immediateFuture(Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTimeline(Timeline.Builder().addTimelineEntry( TimelineEntry.Builder().setLayout( Layout.Builder().setRoot( Text.Builder().setText("Hello world!").setFontStyle( FontStyle.Builder().setColor(argb(0xFF000000)).build() ).build() ).build() ).build() ).build() ).build()) override fun onResourcesRequest(requestParams: ResourcesRequest) = Futures.immediateFuture(Resources.Builder() .setVersion(RESOURCES_VERSION) .build() ) }
Java
public class MyTileService extends TileService { private static final String RESOURCES_VERSION = "1"; @NonNull @Override protected ListenableFuture<Tile> onTileRequest( @NonNull TileRequest requestParams ) { return Futures.immediateFuture(new Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTimeline(new Timeline.Builder() .addTimelineEntry(new TimelineEntry.Builder() .setLayout(new Layout.Builder() .setRoot(new Text.Builder() .setText("Hello world!") .setFontStyle(new FontStyle.Builder() .setColor(argb(0xFF000000)).build() ).build() ).build() ).build() ).build() ).build() ); } @NonNull @Override protected ListenableFuture<Resources> onResourcesRequest( @NonNull ResourcesRequest requestParams ) { return Futures.immediateFuture(new 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=".MyTileService" android:label="@string/tile_label" android:description="@string/tile_description" 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 ô.
Người dùng sẽ thấy biểu tượng, nhãn và nội dung mô tả khi định cấu hình ô trên điện thoại hoặc đồng hồ.
Hãy dùng thẻ siêu dữ liệu xem trước để hiển thị bản xem trước của ô khi bạn định cấu hình ô trên điện thoại.
Tạo giao diện người dùng cho ô
Bố cục của ô được viết bằng mẫu trình tạo. Bố cục của ô đượ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
Sau đây là các phần tử hình ảnh được hỗ trợ:
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 tiles-material
còn cung cấp các thành phần đảm bảo thiết kế ô phù hợp với các đề xuất về giao diện người dùng 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, giống 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 trongProgressIndicatorLayout
để 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
Sau đây là các vùng chứa được hỗ trợ:
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ụ: ô 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(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(); }
Bố cục Material
Ngoài bố cục cơ bản, thư viện tiles-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.ProgressIndicatorLayout
: đặtCircularProgressIndicator
xung quanh các cạnh của màn hình và đặt nội dung đã cho vào bên trong.
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ử.
Công cụ 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 công cụ 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 ô.
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 ô "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:
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 onResourcesRequest()
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 onResourcesRequest()
:
- Cung cấp tài nguyên có thể vẽ bằng cách dùng
setAndroidResourceByResId()
. - Cung cấp hình ảnh linh hoạt dưới dạng
ByteArray
bằng cách dùngsetInlineResource()
.
Kotlin
override fun onResourcesRequest( 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> onResourcesRequest( @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() ); }