Trên thiết bị Wear OS, các ô được kết xuất bằng 2 thành phần chính có tính lập phiên bản độc lập. Để đảm bảo các ô ứng dụng của bạn hoạt động chính xác trên mọi thiết bị, bạn cần hiểu rõ cấu trúc cơ bản này.
- Các thư viện liên quan đến thẻ thông tin Jetpack: Các thư viện này (bao gồm cả Thẻ thông tin Wear và Wear ProtoLayout) được nhúng trong ứng dụng của bạn và bạn (với tư cách là nhà phát triển) sẽ kiểm soát các phiên bản của chúng. Ứng dụng của bạn sử dụng các thư viện này để tạo một đối tượng
TileBuilder.Tile
(cấu trúc dữ liệu đại diện cho Tile của bạn) để phản hồi lệnh gọionTileRequest()
của hệ thống. - Trình kết xuất ProtoLayout: Thành phần hệ thống này chịu trách nhiệm kết xuất đối tượng
Tile
trên màn hình và xử lý các hoạt động tương tác của người dùng. Phiên bản của trình kết xuất không do nhà phát triển ứng dụng kiểm soát và có thể khác nhau giữa các thiết bị, ngay cả những thiết bị có phần cứng giống hệt nhau.
Giao diện hoặc hành vi của Ô có thể thay đổi dựa trên cả phiên bản thư viện Jetpack Tiles của ứng dụng và phiên bản ProtoLayout Renderer trên thiết bị của người dùng. Ví dụ: một thiết bị có thể hỗ trợ xoay hoặc hiển thị dữ liệu nhịp tim, còn thiết bị khác thì không.
Tài liệu này giải thích cách đảm bảo ứng dụng của bạn tương thích với các phiên bản khác nhau của thư viện Tiles và Trình kết xuất ProtoLayout, cũng như cách di chuyển sang các phiên bản thư viện Jetpack cao hơn.
Cân nhắc khả năng tương thích
Để tạo một Thẻ thông tin hoạt động chính xác trên nhiều thiết bị, hãy cân nhắc việc tính đến khả năng hỗ trợ tính năng khác nhau. Bạn có thể thực hiện việc này thông qua 2 chiến lược chính: phát hiện các chức năng của trình kết xuất trong thời gian chạy và cung cấp các giải pháp dự phòng tích hợp.
Phát hiện các chức năng của trình kết xuất
Bạn có thể thay đổi bố cục của ô một cách linh hoạt dựa trên các tính năng có trên một thiết bị nhất định.
Phát hiện phiên bản trình kết xuất
- Sử dụng phương thức
getRendererSchemaVersion()
của đối tượngDeviceParameters
được truyền đến phương thức onTileRequest(). Phương thức này trả về số phiên bản chính và phụ của ProtoLayoutRenderer trên thiết bị. - Sau đó, bạn có thể sử dụng logic có điều kiện trong quá trình triển khai
onTileRequest()
để điều chỉnh thiết kế hoặc hành vi của Ô dựa trên phiên bản trình kết xuất được phát hiện.
Chú thích @RequiresSchemaVersion
- Chú giải
@RequiresSchemaVersion
trên các phương thức ProtoLayout cho biết phiên bản giản đồ trình kết xuất tối thiểu cần thiết để phương thức đó hoạt động như được ghi lại (ví dụ).- Mặc dù việc gọi một phương thức yêu cầu phiên bản trình kết xuất cao hơn phiên bản có trên thiết bị sẽ không khiến ứng dụng của bạn gặp sự cố, nhưng điều này có thể dẫn đến việc nội dung không hiển thị hoặc tính năng bị bỏ qua.
Ví dụ về tính năng phát hiện phiên bản
val rendererVersion = requestParams.deviceConfiguration.rendererSchemaVersion val arcElement = // DashedArcLine has the annotation @RequiresSchemaVersion(major = 1, minor = 500) // and so is supported by renderer versions 1.500 and greater if ( rendererVersion.major > 1 || (rendererVersion.major == 1 && rendererVersion.minor >= 500) ) { // Use DashedArcLine if the renderer supports it … DashedArcLine.Builder() .setLength(degrees(270f)) .setThickness(8f) .setLinePattern( LayoutElementBuilders.DashedLinePattern.Builder() .setGapSize(8f) .setGapInterval(10f) .build() ) .build() } else { // … otherwise use ArcLine. ArcLine.Builder().setLength(degrees(270f)).setThickness(dp(8f)).build() }
Cung cấp các bản dự phòng
Một số tài nguyên cho phép bạn xác định một phương án dự phòng ngay trong trình tạo. Cách này thường đơn giản hơn so với việc kiểm tra phiên bản trình kết xuất và là phương pháp được ưu tiên khi có sẵn.
Một trường hợp sử dụng phổ biến là cung cấp hình ảnh tĩnh làm phương án dự phòng cho ảnh động Lottie. Nếu không hỗ trợ ảnh động Lottie, thiết bị sẽ hiển thị hình ảnh tĩnh.
val lottieImage = ResourceBuilders.ImageResource.Builder() .setAndroidLottieResourceByResId( ResourceBuilders.AndroidLottieResourceByResId.Builder(R.raw.lottie) .setStartTrigger(createOnVisibleTrigger()) .build() ) // Fallback if lottie is not supported .setAndroidResourceByResId( ResourceBuilders.AndroidImageResourceByResId.Builder() .setResourceId(R.drawable.lottie_fallback) .build() ) .build()
Kiểm thử với nhiều phiên bản trình kết xuất
Để kiểm thử các ô của bạn dựa trên nhiều phiên bản trình kết xuất, hãy triển khai các ô đó cho nhiều phiên bản trình mô phỏng Wear OS. (Trên thiết bị thực, các bản cập nhật ProtoLayout Renderer được cung cấp thông qua Cửa hàng Play hoặc bản cập nhật hệ thống. Không thể buộc cài đặt một phiên bản trình kết xuất cụ thể.)
Tính năng Xem trước ô của Android Studio sử dụng một trình kết xuất được nhúng trong thư viện Jetpack ProtoLayout mà mã của bạn phụ thuộc vào. Vì vậy, một cách khác là phụ thuộc vào các phiên bản thư viện Jetpack khác nhau khi kiểm thử các ô.
Di chuyển sang Thẻ thông tin 1.5 / ProtoLayout 1.3 (Material 3 Expressive)
Cập nhật các thư viện Tile của Jetpack để tận dụng những điểm cải tiến mới nhất, bao gồm cả những thay đổi về giao diện người dùng để các Tile của bạn tích hợp liền mạch với hệ thống.
Jetpack Tiles 1.5 và Jetpack ProtoLayout 1.3 có một số điểm cải tiến và thay đổi đáng chú ý. bao gồm:
- Một API tương tự như Compose để mô tả giao diện người dùng.
- Các thành phần Material 3 Expressive, bao gồm cả nút cạnh ôm sát phía dưới và hỗ trợ hình ảnh nâng cao: ảnh động Lottie, nhiều loại chuyển màu hơn và kiểu đường cong mới. – Lưu ý: bạn cũng có thể dùng một số tính năng này mà không cần di chuyển sang API mới.
Đề xuất
- Di chuyển tất cả các ô cùng một lúc. Tránh kết hợp các phiên bản ô trong ứng dụng. Mặc dù các thành phần Material 3 nằm trong một cấu phần phần mềm riêng biệt (
androidx.wear.protolayout:protolayout-material3
) – giúp bạn có thể sử dụng cả Ô M2.5 và M3 trong cùng một ứng dụng – nhưng bạn không nên sử dụng phương pháp này trừ phi thực sự cần thiết (ví dụ: nếu ứng dụng của bạn có nhiều ô mà bạn không thể di chuyển tất cả cùng một lúc). - Áp dụng hướng dẫn về trải nghiệm người dùng của Thẻ thông tin. Vì thẻ thông tin có cấu trúc và mẫu rất rõ ràng, hãy sử dụng các thiết kế trong các mẫu hiện có làm điểm bắt đầu cho thiết kế của riêng bạn.
- Kiểm thử trên nhiều kích thước màn hình và phông chữ. Các ô thường chứa nhiều thông tin, khiến văn bản (đặc biệt là khi được đặt trên các nút) dễ bị tràn và cắt bớt. Để giảm thiểu điều này, hãy sử dụng các thành phần dựng sẵn và tránh tuỳ chỉnh quá nhiều. Kiểm thử bằng tính năng xem trước ô của Android Studio cũng như trên nhiều thiết bị thực.
Quá trình di chuyển
Cập nhật phần phụ thuộc
Trước tiên, hãy cập nhật tệp build.gradle.kts
. Cập nhật các phiên bản và thay đổi phần phụ thuộc protolayout-material
thành protolayout-material3
, như minh hoạ:
// In build.gradle.kts
//val tilesVersion = "1.4.1"
//val protoLayoutVersion = "1.2.1"
// Use these versions for M3.
val tilesVersion = "1.5.0-rc01"
val protoLayoutVersion = "1.3.0-rc01"
dependencies {
// Use to implement support for wear tiles
implementation("androidx.wear.tiles:tiles:$tilesVersion")
// Use to utilize standard components and layouts in your tiles
implementation("androidx.wear.protolayout:protolayout:$protoLayoutVersion")
// Use to utilize components and layouts with Material Design in your tiles
// implementation("androidx.wear.protolayout:protolayout-material:$protoLayoutVersion")
implementation("androidx.wear.protolayout:protolayout-material3:$protoLayoutVersion")
// Use to include dynamic expressions in your tiles
implementation("androidx.wear.protolayout:protolayout-expression:$protoLayoutVersion")
// Use to preview wear tiles in your own app
debugImplementation("androidx.wear.tiles:tiles-renderer:$tilesVersion")
// Use to fetch tiles from a tile provider in your tests
testImplementation("androidx.wear.tiles:tiles-testing:$tilesVersion")
}
TileService hầu như không thay đổi
Những thay đổi chính trong quá trình di chuyển này ảnh hưởng đến các thành phần trên giao diện người dùng. Do đó, việc triển khai TileService
của bạn, bao gồm mọi cơ chế tải tài nguyên, sẽ không cần hoặc chỉ cần sửa đổi rất ít.
Ngoại lệ chính liên quan đến tính năng theo dõi hoạt động trên ô: nếu ứng dụng của bạn dùng onTileEnterEvent()
hoặc onTileLeaveEvent()
, bạn nên di chuyển sang onRecentInteractionEventsAsync()
. Kể từ API 36, các sự kiện này sẽ được xử lý theo lô.
Điều chỉnh mã tạo bố cục
Trong ProtoLayout 1.2 (M2.5), phương thức onTileRequest()
sẽ trả về TileBuilders.Tile
. Đối tượng này chứa nhiều phần tử, bao gồm cả TimelineBuilders.Timeline
. Phần tử này lại chứa LayoutElement
mô tả giao diện người dùng của ô.
Với ProtoLayout 1.3 (M3), mặc dù cấu trúc và luồng dữ liệu tổng thể không thay đổi, nhưng LayoutElement
hiện được tạo bằng phương pháp lấy cảm hứng từ Compose với bố cục dựa trên các vị trí được xác định (từ trên xuống dưới) là titleSlot
(không bắt buộc; thường dùng cho tiêu đề chính hoặc tiêu đề), mainSlot
(bắt buộc; cho nội dung cốt lõi) và bottomSlot
(không bắt buộc; thường dùng cho các thao tác như nút cạnh hoặc thông tin bổ sung như văn bản ngắn). Bố cục này được tạo bằng hàm primaryLayout()
.

So sánh các hàm bố cục M2.5 và M3
M2.5
fun myLayout(
context: Context,
deviceConfiguration: DeviceParametersBuilders.DeviceParameters
) =
PrimaryLayout.Builder(deviceConfiguration)
.setResponsiveContentInsetEnabled(true)
.setContent(
Text.Builder(context, "Hello World!")
.setTypography(Typography.TYPOGRAPHY_BODY1)
.setColor(argb(0xFFFFFFFF.toInt()))
.build()
)
.build()
M3
fun myLayout(
context: Context,
deviceConfiguration: DeviceParametersBuilders.DeviceParameters,
) =
materialScope(context, deviceConfiguration) {
primaryLayout(mainSlot = { text("Hello, World!".layoutString) })
}
Để nêu bật những điểm khác biệt chính:
- Loại bỏ các trình tạo. Mẫu trình tạo truyền thống cho các thành phần giao diện người dùng Material3 được thay thế bằng một cú pháp khai báo hơn, lấy cảm hứng từ Compose. (Các thành phần không thuộc giao diện người dùng như String/Color/Modifiers cũng có trình bao bọc Kotlin mới.)
- Các hàm khởi chạy và bố cục được chuẩn hoá. Bố cục M3 dựa vào các hàm khởi tạo và cấu trúc được chuẩn hoá:
materialScope()
vàprimaryLayout()
. Các hàm bắt buộc này khởi chạy môi trường M3 (tạo chủ đề, phạm vi thành phần thông quamaterialScope
) và xác định bố cục chính dựa trên khe cắm (thông quaprimaryLayout
). Cả hai hàm này phải được gọi chính xác một lần cho mỗi bố cục.
Giao diện
Màu
Một tính năng nổi bật của Material 3 Expressive là "tạo giao diện động": các ô cho phép tính năng này (theo mặc định là bật) sẽ xuất hiện trong giao diện do hệ thống cung cấp (khả năng cung cấp phụ thuộc vào thiết bị và cấu hình của người dùng).
Một thay đổi khác trong M3 là việc mở rộng số lượng mã thông báo màu, từ 4 lên 29. Bạn có thể tìm thấy các mã màu mới trong lớp ColorScheme
.
Kiểu chữ
Tương tự như M2.5, M3 phụ thuộc nhiều vào các hằng số kích thước phông chữ được xác định trước. Bạn không nên chỉ định trực tiếp kích thước phông chữ. Các hằng số này nằm trong lớp Typography
và cung cấp một phạm vi mở rộng hơn một chút với nhiều lựa chọn biểu cảm hơn.
Để biết thông tin đầy đủ, hãy tham khảo Tài liệu về kiểu chữ.
Hình dạng
Hầu hết các thành phần M3 đều có thể thay đổi theo phương diện hình dạng cũng như màu sắc.
Một textButton
(trong mainSlot
) có hình dạng full
:

Cùng một textButton có hình dạng small
:

Thành phần
Các thành phần M3 linh hoạt và có thể định cấu hình hơn đáng kể so với các thành phần tương đương trong M2.5. Trong khi M2.5 thường yêu cầu các thành phần riêng biệt cho nhiều phương pháp xử lý hình ảnh, thì M3 thường sử dụng một thành phần "cơ sở" chung nhưng có khả năng định cấu hình cao với các giá trị mặc định phù hợp.
Nguyên tắc này áp dụng cho bố cục "root". Trong M2.5, đây là PrimaryLayout
hoặc EdgeContentLayout
. Trong M3, sau khi thiết lập một MaterialScope
cấp cao nhất, hàm primaryLayout()
sẽ được gọi. Thao tác này sẽ trả về trực tiếp bố cục gốc (không cần trình tạo) và chấp nhận LayoutElements
cho một số "vùng", chẳng hạn như titleSlot
, mainSlot
và bottomSlot
. Bạn có thể điền các thành phần giao diện người dùng cụ thể vào các khe này, chẳng hạn như các thành phần do text(), button() hoặc card() trả về, hoặc các cấu trúc bố cục, chẳng hạn như Row
hoặc Column
từ LayoutElementBuilders
.
Giao diện là một điểm cải tiến quan trọng khác của M3. Theo mặc định, các phần tử giao diện người dùng sẽ tự động tuân thủ các quy cách tạo kiểu M3 và hỗ trợ tính năng tạo chủ đề động.
M2.5 | M3 |
---|---|
Các phần tử tương tác | |
Button hoặc Chip |
|
Văn bản | |
Text |
text() |
Chỉ báo tiến trình | |
CircularProgressIndicator |
circularProgressIndicator() hoặc segmentedCircularProgressIndicator() |
Bố cục | |
PrimaryLayout hoặc EdgeContentLayout |
primaryLayout() |
— | buttonGroup() |
Hình ảnh | |
— | icon() , avatarImage() hoặc backgroundImage() |
Đối tượng sửa đổi
Trong M3, Modifiers
(bạn dùng để trang trí hoặc làm nổi bật một thành phần) giống với Compose hơn. Thay đổi này có thể giảm mã lặp lại bằng cách tự động tạo các loại nội bộ thích hợp. (Thay đổi này không liên quan đến việc sử dụng các thành phần giao diện người dùng M3; nếu cần, bạn có thể sử dụng các đối tượng sửa đổi theo kiểu trình tạo từ ProtoLayout 1.2 với các thành phần giao diện người dùng M3 và ngược lại.)
M2.5
// A Builder-style modifier to set the opacity of an element to 0.5
fun myModifier(): ModifiersBuilders.Modifiers =
ModifiersBuilders.Modifiers.Builder()
.setOpacity(TypeBuilders.FloatProp.Builder(0.5F).build())
.build()
M3
// The equivalent Compose-like modifier is much simpler
fun myModifier(): LayoutModifier = LayoutModifier.opacity(0.5F)
Bạn có thể tạo đối tượng sửa đổi bằng cách sử dụng kiểu API hoặc bạn cũng có thể sử dụng hàm mở rộng toProtoLayoutModifiers()
để chuyển đổi LayoutModifier
thành ModifiersBuilders.Modifier
.
Hàm trợ giúp
Mặc dù ProtoLayout 1.3 cho phép thể hiện nhiều thành phần giao diện người dùng bằng API lấy cảm hứng từ Compose, nhưng các phần tử bố cục cơ bản như hàng và cột từ LayoutElementBuilders
vẫn tiếp tục sử dụng mẫu trình tạo. Để thu hẹp khoảng cách về phong cách này và đảm bảo tính nhất quán với các API thành phần M3 mới, hãy cân nhắc sử dụng các hàm trợ giúp.
Không có người trợ giúp
primaryLayout(
mainSlot = {
LayoutElementBuilders.Column.Builder()
.setWidth(expand())
.setHeight(expand())
.addContent(text("A".layoutString))
.addContent(text("B".layoutString))
.addContent(text("C".layoutString))
.build()
}
)
Có người trợ giúp
// Function literal with receiver helper function
fun column(builder: Column.Builder.() -> Unit) =
Column.Builder().apply(builder).build()
primaryLayout(
mainSlot = {
column {
setWidth(expand())
setHeight(expand())
addContent(text("A".layoutString))
addContent(text("B".layoutString))
addContent(text("C".layoutString))
}
}
)
Di chuyển sang Thẻ thông tin 1.2 / ProtoLayout 1.0
Kể từ phiên bản 1.2, hầu hết các API Bố cục thẻ thông tin đều nằm trong không gian tên androidx.wear.protolayout
. Để sử dụng các API mới nhất, hãy hoàn tất các bước di chuyển sau đây trong mã của bạn.
Cập nhật phần phụ thuộc
Trong tệp bản dựng của mô-đun ứng dụng, hãy thực hiện các thay đổi sau:
Groovy
// Removeimplementation 'androidx.wear.tiles:tiles-material:version'// Include additional dependencies implementation "androidx.wear.protolayout:protolayout:1.3.0" implementation "androidx.wear.protolayout:protolayout-material:1.3.0" implementation "androidx.wear.protolayout:protolayout-expression:1.3.0" // Update implementation "androidx.wear.tiles:tiles:1.5.0"
Kotlin
// Removeimplementation("androidx.wear.tiles:tiles-material:version")// Include additional dependencies implementation("androidx.wear.protolayout:protolayout:1.3.0") implementation("androidx.wear.protolayout:protolayout-material:1.3.0") implementation("androidx.wear.protolayout:protolayout-expression:1.3.0") // Update implementation("androidx.wear.tiles:tiles:1.5.0")
Cập nhật không gian tên
Trong các tệp mã dựa trên Kotlin và Java của ứng dụng, hãy cập nhật như sau. Ngoài ra, bạn có thể thực thi tập lệnh đổi tên không gian tên này.
- Thay thế tất cả các lệnh nhập
androidx.wear.tiles.material.*
bằngandroidx.wear.protolayout.material.*
. Bạn cũng cần hoàn tất bước này cho thư việnandroidx.wear.tiles.material.layouts
. Thay thế hầu hết các lệnh nhập
androidx.wear.tiles.*
khác bằngandroidx.wear.protolayout.*
.Các lệnh nhập cho
androidx.wear.tiles.EventBuilders
,androidx.wear.tiles.RequestBuilders
,androidx.wear.tiles.TileBuilders
vàandroidx.wear.tiles.TileService
sẽ giữ nguyên.Đổi tên một vài phương thức không dùng nữa trong các lớp TileService và TileBuilder:
TileBuilders
:getTimeline()
thànhgetTileTimeline()
vàsetTimeline()
thànhsetTileTimeline()
TileService
:onResourcesRequest()
thànhonTileResourcesRequest()
RequestBuilders.TileRequest
:getDeviceParameters()
thànhgetDeviceConfiguration()
,setDeviceParameters()
thànhsetDeviceConfiguration()
,getState()
thànhgetCurrentState()
vàsetState()
thànhsetCurrentState()