Để 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" // Use to utilize standard components and layouts in your tiles implementation "androidx.wear.protolayout:protolayout:1.3.0" // Use to utilize components and layouts with Material Design in your tiles implementation "androidx.wear.protolayout:protolayout-material:1.3.0" // Use to include dynamic expressions in your tiles implementation "androidx.wear.protolayout:protolayout-expression:1.3.0" // Use to preview wear tiles in your own app debugImplementation "androidx.wear.tiles:tiles-renderer:1.5.0" // Use to fetch tiles from a tile provider in your tests testImplementation "androidx.wear.tiles:tiles-testing:1.5.0" }
Kotlin
dependencies { // Use to implement support for wear tiles implementation("androidx.wear.tiles:tiles:1.5.0") // Use to utilize standard components and layouts in your tiles implementation("androidx.wear.protolayout:protolayout:1.3.0") // Use to utilize components and layouts with Material Design in your tiles implementation("androidx.wear.protolayout:protolayout-material:1.3.0") // Use to include dynamic expressions in your tiles implementation("androidx.wear.protolayout:protolayout-expression:1.3.0") // Use to preview wear tiles in your own app debugImplementation("androidx.wear.tiles:tiles-renderer:1.5.0") // Use to fetch tiles from a tile provider in your tests testImplementation("androidx.wear.tiles:tiles-testing:1.5.0") }
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:
- Mẫu bố cục: Xác định cách sắp xếp tổng thể các phần tử trực quan trên màn hình. Bạn có thể thực hiện việc này bằng hàm
primaryLayout()
. - Phần tử bố cục: Biểu thị một phần tử đồ hoạ riêng lẻ, chẳng hạn như nút hoặc thẻ, hoặc một số phần tử như vậy được nhóm lại với nhau bằng cột, buttonGroup hoặc các phần tử 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 đồ các cặp khoá-giá trị của tài nguyên Android (hình ảnh) cần thiết để hiển thị một bố cục và một phiên bản. - Dòng thời gian: Đối tượng
TimelineBuilders.Timeline
là danh sách gồm một hoặc nhiều thực thể của đố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 sẽ chuyển từ mộ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ị một bố cục vào một thời điểm cụ thể. - Trạng thái: Một cấu trúc dữ liệu thuộc loại
StateBuilders.State
được truyền giữa ô và ứng dụng để cho phép hai thành phần giao tiếp với nhau. Ví dụ: nếu một nút được nhấn trên ô, thì trạng thái sẽ giữ 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 bản đồ. - Thẻ thông tin: Một đối tượng
TileBuilders.Tile
đại diện cho một thẻ thông tin, bao gồm dòng thời gian, mã nhận dạng 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 ô và đề cập đến thư viện Wear OS Protolayout, một thư viện đồ hoạ được 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 sẽ 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( 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() ) }
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.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>
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ồ. Xin lưu ý rằng tài nguyên xem trước hỗ trợ tất cả bộ định tính tài nguyên tiêu chuẩn của Android, vì vậy, bạn có thể thay đổi bản xem trước theo các yếu tố như kích thước màn hình và ngôn ngữ thiết bị. Hãy xem danh sách kiểm tra bản xem trước để biết thêm các đề xuất.
Triển khai ứng dụng của bạn và thêm Thẻ thông tin vào Băng chuyền thẻ thông tin (cũng có một cách thân thiện hơn với nhà phát triển để xem trước Thẻ thông tin, nhưng hiện tại, bạn chỉ cần thực hiện theo cách thủ công).

Để 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
Các phần tử giao diện người dùng biểu cảm của Material 3 được tạo bằng cách sử dụng một phương pháp có cấu trúc dựa trên mẫu trình tạo an toàn về kiểu của Kotlin.
Bố cục
Để biết hướng dẫn về các nguyên tắc thiết kế khi tạo bố cục thẻ thông tin hiệu quả và thích ứng, hãy xem phần Bố cục thẻ thông tin thường gặp.
Để tạo bố cục, hãy làm như sau:
Khởi tạo một phạm vi Material Design: Gọi hàm
materialScope()
, cung cấpcontext
vàdeviceConfiguration
bắt buộc. Bạn có thể thêm các tham số không bắt buộc, chẳng hạn nhưallowDynamicTheme
vàdefaultColorScheme
.allowDynamicTheme
mặc định làtrue
vàdefaultColorScheme
đại diện choColorScheme
được dùng khi không có màu động (chẳng hạn như khi người dùng đã tắt tính năng này) hoặc khi thiết bị không hỗ trợ hoặcallowDynamicTheme
làfalse
).Tạo giao diện người dùng trong phạm vi: Tất cả thành phần giao diện người dùng cho một bố cục Ô nhất định phải được xác định trong lambda của một lệnh gọi materialScope() cấp cao nhất. Các hàm thành phần này, chẳng hạn như
primaryLayout()
vàtextEdgeButton()
, là các hàm mở rộng trênMaterialScope
và chỉ có sẵn khi được gọi trên phạm vi của receiver này.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) } ) }
Máy đánh bạc
Trong M3, bố cục ô sử dụng một phương pháp lấy cảm hứng từ Compose, tận dụng 3 vị trí riêng biệt. Từ trên xuống dưới, các nút này là:
titleSlot
, thường dùng cho tiêu đề hoặc tiêu đề chính.mainSlot
, đối với nội dung cốt lõi.bottomSlot
, thường được dùng cho các thao tác hoặc thông tin bổ sung. Đây cũng là nơi xuất hiện nút cạnh.

Nội dung của mỗi vị trí như sau:
titleSlot
(không bắt buộc): Thường là một vài từ dotext()
tạo ra.mainSlot
(bắt buộc): Các thành phần được sắp xếp thành các cấu trúc như hàng, cột và nhóm nút. Các thành phần này cũng có thể được nhúng đệ quy vào bên trong nhau; ví dụ: một cột có thể chứa các hàng.bottomSlot
(không bắt buộc): Thường được điền bằng nút ôm viền hoặc nhãn văn bản.
Vì không thể cuộn các ô, nên không có thành phần nào để phân trang, cuộn hoặc xử lý danh sách nội dung dài. Hãy đảm bảo nội dung vẫn hiển thị khi cỡ chữ tăng lên hoặc văn bản dài hơn do bản dịch.
Thành phần giao diện người dùng
Thư viện protolayout-material3
cung cấp một số lượng lớn các thành phần được thiết kế theo quy cách Expressive của Material 3 và các đề xuất về giao diện người dùng.
Nút
Nút chủ yếu hướng đến hành động. Chúng có chức năng kích hoạt các hành động cụ thể. Nội dung của mỗi nút (chẳng hạn như biểu tượng hoặc văn bản ngắn) sẽ xác định thao tác.
- textButton(): nút có một khe duy nhất cho nội dung văn bản (ngắn)
- iconButton(): nút có một khe duy nhất để biểu thị một biểu tượng
- avatarButton(): nút hình đại diện có hình dạng viên thuốc cung cấp tối đa 3 vị trí để lấy nội dung đại diện cho nhãn và nhãn phụ xếp chồng theo chiều dọc, cũng như một hình ảnh (hình đại diện) bên cạnh
- imageButton(): nút có hình ảnh có thể nhấp và không có thêm các khe cắm, chỉ có hình ảnh (ví dụ: backgroundImage làm nền)
- compactButton(): nút thu gọn cung cấp tối đa 2 khe để lấy nội dung xếp chồng theo chiều ngang, đại diện cho một biểu tượng và văn bản bên cạnh
- button(): nút có hình dạng viên thuốc cung cấp tối đa 3 khe để lấy nội dung đại diện cho nhãn và nhãn phụ được xếp chồng theo chiều dọc, cùng một biểu tượng bên cạnh
Nút cạnh
Nút cạnh là một nút chuyên dụng, có chiều rộng tối đa, được cố định ở cuối màn hình tròn của đồng hồ, thể hiện hành động quan trọng nhất cần thực hiện trên màn hình ô hiện tại.
- iconEdgeButton(): nút cạnh cung cấp một khe duy nhất để chụp biểu tượng hoặc nội dung nhỏ có hình tròn tương tự
- textEdgeButton(): nút cạnh cung cấp một khe duy nhất để lấy văn bản hoặc nội dung có độ dài và chiều rộng tương tự
Thẻ
Thẻ chủ yếu dựa trên thông tin. Chúng hiển thị các bộ sưu tập dữ liệu có cấu trúc liên quan. Mặc dù bạn có thể tạo thẻ tương tác, nhưng thẻ này thường cho thấy thông tin tóm tắt mà người dùng có thể nhấn vào để xem thêm thông tin chi tiết hoặc thực hiện một hành động liên quan.
- titleCard(): thẻ tiêu đề có từ 1 đến 3 vị trí, thường dựa trên văn bản
- appCard(): thẻ ứng dụng cung cấp tối đa 5 vị trí, thường dựa trên văn bản
- textDataCard(): thẻ dữ liệu cung cấp tối đa 3 vị trí xếp chồng theo chiều dọc, thường dựa trên văn bản hoặc chữ số
- iconDataCard(): thẻ dữ liệu cung cấp tối đa 3 vị trí xếp chồng theo chiều dọc, thường dựa trên văn bản hoặc chữ số, có biểu tượng
- graphicDataCard(): thẻ dữ liệu đồ hoạ cung cấp một vị trí cho dữ liệu đồ hoạ (chẳng hạn như chỉ báo tiến trình) và tối đa 2 vị trí xếp chồng theo chiều dọc, thường dùng cho nội dung mô tả bằng văn bản
Chỉ báo tiến trình
- circularProgressIndicator(): cho biết tiến trình đạt được mục tiêu bằng cách sử dụng một phần tử hướng tâm
- segmentedCircularProgressIndicator(): cho biết tiến trình hướng tới một mục tiêu bằng cách sử dụng một phần tử xuyên tâm với các giai đoạn riêng biệt
Nhóm các phần tử bố cục
- buttonGroup(): bố cục thành phần đặt các phần tử con theo trình tự ngang
- primaryLayout(): bố cục toàn màn hình thể hiện kiểu bố cục M3 được đề xuất, có khả năng thích ứng và đảm bảo vị trí của các phần tử, cùng với khoảng lề và khoảng đệm được đề xuất đã áp dụng
Giao diện
Trong Material 3 Expressive, hệ thống màu được xác định bằng 29 vai trò màu tiêu chuẩn, được sắp xếp thành 6 nhóm: chính, phụ, thứ ba, lỗi, bề mặt và đường viền.

ColorScheme
ánh xạ từng vai trò trong số 29 vai trò này với một màu sắc tương ứng và vì đây là một phần của MaterialScope
và các thành phần phải được tạo trong đó, nên chúng sẽ tự động lấy màu từ bảng phối màu. Phương pháp này cho phép tất cả các phần tử giao diện người dùng tự động tuân thủ các tiêu chuẩn của Material Design.
Để cho phép người dùng chọn giữa một bảng phối màu mà bạn xác định (chẳng hạn như bảng phối màu phản ánh màu thương hiệu của bạn) và một bảng phối màu do hệ thống cung cấp (lấy từ mặt đồng hồ hiện tại của người dùng hoặc do người dùng chọn), hãy khởi động MaterialScope
như sau:
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.
}
Để buộc các ô xuất hiện trong bảng phối màu mà bạn cung cấp, hãy tắt tính năng hỗ trợ tạo giao diện linh động bằng cách đặt allowDynamicTheme
thành false
:
materialScope(
allowDynamicTheme = false,
defaultColorScheme = myColorScheme
) {
// myColorScheme is *always* used.
}
Màu
Mỗi thành phần riêng lẻ sử dụng một tập hợp con gồm 29 vai trò màu sắc do ColorScheme
xác định. Ví dụ: các nút sử dụng tối đa 4 màu, theo mặc định, các màu này được lấy từ nhóm "chính" của ColorScheme
đang hoạt động:
Mã thông báo thành phần ButtonColors |
Vai trò ColorScheme |
---|---|
containerColor | chính |
iconColor | onPrimary |
labelColor | onPrimary |
secondaryLabelColor | onPrimary (độ mờ 0,8) |
Để biết hướng dẫn chi tiết về cách áp dụng màu sắc cho các thiết kế Wear OS, hãy xem hướng dẫn thiết kế màu sắc.
Bạn có thể cần phải thay đổi mã hiệu màu mặc định cho các phần tử giao diện người dùng cụ thể. Ví dụ: bạn có thể muốn một textEdgeButton
sử dụng màu sắc trong nhóm "thứ cấp" hoặc "bậc ba" thay vì "chính" để nổi bật và mang lại độ tương phản tốt hơn.
Bạn có thể tuỳ chỉnh màu sắc của thành phần theo nhiều cách:
Sử dụng hàm trợ giúp cho các màu được xác định trước. Sử dụng các hàm trợ giúp như
filledTonalButtonColors()
để áp dụng các kiểu nút tiêu chuẩn cho Material 3 Expressive. Các hàm này tạo ra các thực thểButtonColors
được định cấu hình sẵn, ánh xạ các kiểu phổ biến như kiểu tô màu, kiểu tông màu hoặc kiểu đường viền với các vai trò thích hợp từColorScheme
đang hoạt động trongMaterialScope
. Điều này cho phép bạn áp dụng các kiểu nhất quán mà không cần xác định từng màu theo cách thủ công cho các loại nút thông thường.textEdgeButton( colors = filledButtonColors() // default /* OR colors = filledTonalButtonColors() */ /* OR colors = filledVariantButtonColors() */ // ... other parameters )
Đối với thẻ, hãy dùng họ hàm
filledCardColors()
tương đương.Bạn cũng có thể sửa đổi đối tượng
ButtonColors
do các hàm trợ giúp trả về bằng phương thứccopy()
nếu chỉ cần thay đổi một hoặc hai mã thông báo:textEdgeButton( colors = filledButtonColors() .copy( containerColor = colorScheme.tertiary, labelColor = colorScheme.onTertiary ) // ... other parameters )
Cung cấp rõ ràng các vai trò màu thay thế. Tạo đối tượng
ButtonColors
của riêng bạn và truyền đối tượng đó đến thành phần. Đối với thẻ, hãy sử dụng đối tượngCardColors
tương đương.textEdgeButton( colors = ButtonColors( // the materialScope makes colorScheme available containerColor = colorScheme.secondary, iconColor = colorScheme.secondaryDim, labelColor = colorScheme.onSecondary, secondaryLabelColor = colorScheme.onSecondary ) // ... other parameters )
Chỉ định màu cố định (hãy thận trọng khi sử dụng). Mặc dù bạn nên chỉ định màu theo vai trò ngữ nghĩa (ví dụ:
colorScheme.primary
), bạn cũng có thể cung cấp các giá trị màu trực tiếp. Bạn nên hạn chế sử dụng phương pháp này vì có thể dẫn đến sự không nhất quán với giao diện tổng thể, đặc biệt là nếu giao diện thay đổi linh hoạt.textEdgeButton( colors = filledButtonColors().copy( containerColor = android.graphics.Color.RED.argb, // Using named colors labelColor = 0xFFFFFF00.argb // Using a hex code for yellow ) // ... other parameters )
Kiểu chữ
Để biết thêm thông tin về cách sử dụng kiểu chữ một cách hiệu quả trong thiết kế của bạn, hãy xem hướng dẫn thiết kế kiểu chữ.
Để tạo sự nhất quán về hình ảnh trên nền tảng Wear OS và tối ưu hoá hiệu suất, tất cả văn bản trên thẻ thông tin đều được hiển thị bằng phông chữ do hệ thống cung cấp. Tức là các ô không hỗ trợ kiểu chữ tuỳ chỉnh. Trên Wear OS 6 trở lên, đây là một phông chữ dành riêng cho OEM. Trong hầu hết các trường hợp, đó sẽ là một phông chữ có thể thay đổi, mang đến trải nghiệm biểu cảm hơn và khả năng kiểm soát chi tiết hơn.
Để tạo kiểu văn bản, bạn thường dùng phương thức text()
kết hợp với các hằng số kiểu chữ. Thành phần này cho phép bạn sử dụng các vai trò kiểu chữ được xác định trước trong Material 3 Expressive, giúp thẻ thông tin của bạn tuân thủ các phương pháp hay nhất đã được thiết lập về kiểu chữ để đảm bảo khả năng đọc và hệ phân cấp.
Thư viện này cung cấp một bộ gồm 18 hằng số kiểu chữ ngữ nghĩa, chẳng hạn như BODY_MEDIUM. Các hằng số này cũng ảnh hưởng đến các trục phông chữ khác ngoài kích thước.
text(
text = "Hello, World!".layoutString,
typography = BODY_MEDIUM,
)
Để có thêm quyền kiểm soát, bạn có thể cung cấp thêm chế độ cài đặt. Trên Wear OS 6 trở lên, có thể bạn sẽ dùng một phông chữ biến đổi. Bạn có thể sửa đổi phông chữ này theo các trục in nghiêng, độ đậm, chiều rộng và độ tròn. Bạn có thể kiểm soát các trục này bằng tham số 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)),
)
Cuối cùng, nếu bạn cần kiểm soát kích thước hoặc khoảng cách giữa các chữ cái (không nên dùng), hãy sử dụng basicText() thay vì text() và tạo một giá trị cho thuộc tính fontStyle
bằng cách sử dụng fontStyle()).
Hình dạng và lề
Bạn có thể thay đổi bán kính góc của hầu hết mọi thành phần bằng cách sử dụng thuộc tính shape
của thành phần đó. Các giá trị của thuộc tính MaterialScope
shapes
:
textButton(
height = expand(),
width = expand(),
shape = shapes.medium, // OR another value like shapes.full
colors = filledVariantButtonColors(),
labelContent = { text("Hello, World!".layoutString) },
)
Sau khi bạn thay đổi hình dạng của một thành phần, nếu bạn cho rằng thành phần đó để lại quá nhiều hoặc quá ít khoảng trống xung quanh cạnh của màn hình, hãy điều chỉnh lề bằng cách sử dụng tham số margin
của primaryLayout()
:
primaryLayout(
mainSlot = {
textButton(
shape = shapes.small,
/* ... */
)
},
// margin constants defined in androidx.wear.protolayout.material3.PrimaryLayoutMargins
margins = MAX_PRIMARY_LAYOUT_MARGIN,
)
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 một 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 đối tượng sửa đổi có thể nhấp để thẻ thông tin 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 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 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() ); }
Danh sách kiểm tra hình ảnh xem trước ô
Hệ thống sẽ hiển thị hình ảnh xem trước thẻ thông tin (được tham chiếu trong tệp kê khai ứng dụng Android) trong trình chỉnh sửa băng chuyền thẻ thông tin để thêm một thẻ thông tin mới. Trình chỉnh sửa này xuất hiện trên cả thiết bị Wear OS và trong ứng dụng đồng hành trên điện thoại.
Để giúp người dùng khai thác tối đa hình ảnh xem trước này, hãy xác minh những thông tin sau về ô của bạn:
- Phản ánh thiết kế mới nhất. Bản xem trước phải thể hiện chính xác thiết kế mới nhất của ô.
- Sử dụng phương diện được đề xuất. Để mang lại chất lượng hiển thị tốt nhất có thể và trải nghiệm người dùng tốt, hình ảnh xem trước phải có kích thước 400px x 400px.
- Sử dụng một giao diện màu tĩnh. Sử dụng giao diện màu tĩnh của ô, chứ không phải giao diện màu động.
- Bao gồm biểu tượng ứng dụng. Xác nhận rằng biểu tượng ứng dụng của bạn xuất hiện ở đầu hình ảnh xem trước.
- Cho biết trạng thái đã tải/đã đăng nhập. Bản xem trước phải hiển thị trạng thái "đã tải" hoặc "đã đăng nhập" có đầy đủ chức năng, tránh mọi nội dung trống hoặc nội dung giữ chỗ.
- Tận dụng các quy tắc phân giải tài nguyên để tuỳ chỉnh (không bắt buộc). Hãy cân nhắc sử dụng các quy tắc phân giải tài nguyên của Android để cung cấp bản xem trước phù hợp với kích thước màn hình, ngôn ngữ hoặc chế độ cài đặt ngôn ngữ của thiết bị. Điều này đặc biệt hữu ích nếu giao diện của ô thay đổi trên các thiết bị.