在 Wear OS 裝置上,動態磚是由兩個重要元件 (版本各自獨立) 算繪而成。如要確保應用程式動態磚在所有裝置上都能正常運作,請務必瞭解這項基礎架構。
- Jetpack 圖塊相關程式庫:這些程式庫 (包括 Wear Tiles 和 Wear ProtoLayout) 會嵌入應用程式中,而開發人員可以控管版本。應用程式會使用這些程式庫建構
TileBuilder.Tile
物件 (代表動態磚的資料結構),以回應系統的onTileRequest()
呼叫。 - ProtoLayout 算繪器:這個系統元件負責在螢幕上算繪
Tile
物件,並處理使用者互動。應用程式開發人員無法控制轉譯器版本,且不同裝置的轉譯器版本可能不同,即使是硬體相同的裝置也不例外。
動態磚的外觀或行為會因應用程式的 Jetpack 動態磚程式庫版本,以及使用者裝置上的 ProtoLayout Renderer 版本而異。舉例來說,某個裝置可能支援旋轉或顯示心率資料,另一個裝置則可能不支援。
本文說明如何確保應用程式與不同版本的 Tiles 程式庫和 ProtoLayout Renderer 相容,以及如何遷移至較高的 Jetpack 程式庫版本。
考慮相容性
如要建立可在各種裝置上正常運作的資訊方塊,請考慮支援不同的功能。您可以透過兩種主要策略達成此目的:在執行階段偵測轉譯器功能,以及提供內建備援。
偵測轉譯器功能
你可以根據特定裝置提供的功能,動態變更動態磚的版面配置。
偵測轉譯器版本
- 使用傳遞至 onTileRequest() 方法的
DeviceParameters
物件的getRendererSchemaVersion()
方法。這個方法會傳回裝置上 ProtoLayout Renderer 的主要和次要版本號碼。 - 然後,您可以在
onTileRequest()
實作中運用條件邏輯,根據偵測到的轉譯器版本調整動態磚的設計或行為。
@RequiresSchemaVersion
註解
- ProtoLayout 方法上的
@RequiresSchemaVersion
註解,表示該方法如要按照文件所述運作,所需的最低算繪器結構定義版本 (範例)。- 呼叫的方法需要比裝置上可用的更高版本,雖然不會導致應用程式當機,但可能會導致內容未顯示或功能遭到忽略。
版本偵測範例
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() }
提供備用廣告
部分資源可讓您直接在建構工具中定義備援。這通常比檢查算繪器版本簡單,而且是可用的首選方法。
常見用途是提供靜態圖片,做為 Lottie 動畫的備用圖片。如果裝置不支援 Lottie 動畫,系統會改為算繪靜態圖片。
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()
使用不同的轉譯器版本進行測試
如要針對不同版本的算繪器測試動態磚,請將動態磚部署至不同版本的 Wear OS 模擬器。(在實體裝置上,ProtoLayout Renderer 更新會透過 Play 商店或系統更新提供。無法強制安裝特定轉譯器版本。
Android Studio 的「動態磚預覽」功能會使用嵌入程式碼所依附 Jetpack ProtoLayout 程式庫的算繪器,因此測試動態磚的另一種做法是依附不同版本的 Jetpack 程式庫。
遷移至 Tiles 1.5 / ProtoLayout 1.3 (Material 3 Expressive)
更新 Jetpack 資訊方塊程式庫,即可享有最新強化功能,包括 UI 變更,讓資訊方塊與系統無縫整合。
Jetpack Tiles 1.5 和 Jetpack ProtoLayout 1.3 推出多項重大改善和異動。包括:
- 類似於 Compose 的 API,用於說明 UI。
- Material 3 Expressive 元件,包括底部貼邊按鈕,以及支援強化視覺效果:Lottie 動畫、更多漸層類型和新的弧線樣式。 - 注意:部分功能不需遷移至新版 API 也能使用。
建議
- 同時遷移所有圖塊。請避免在應用程式中混用動態磚版本。雖然 Material 3 元件位於獨立構件 (
androidx.wear.protolayout:protolayout-material3
) 中,因此技術上可以在同一個應用程式中同時使用 M2.5 和 M3 動態磚,但除非絕對必要 (例如應用程式有大量動態磚,無法一次全數遷移),否則我們強烈建議不要採取這種做法。 - 採用資訊方塊使用者體驗指南。由於資訊方塊的結構高度化且採用範本,因此請使用現有範例中的設計做為自有設計的起點。
- 測試各種螢幕和字型大小。動態磚通常包含大量資訊,因此文字 (尤其是按鈕上的文字) 容易溢位和遭到剪裁。為盡量減少這種情況,請使用預先建構的元件,並避免進行大規模自訂。使用 Android Studio 的動態磚預覽功能,以及多部實體裝置進行測試。
遷移程序
更新依附元件
請先更新 build.gradle.kts
檔案。更新版本,並將 protolayout-material
依附元件變更為 protolayout-material3
,如下所示:
// 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 幾乎沒有變動
這次遷移的主要變更會影響 UI 元件。因此,您的 TileService
實作 (包括任何資源載入機制) 應該只需要進行極少修改,甚至完全不需要修改。
主要例外狀況是動態磚活動追蹤:如果應用程式使用 onTileEnterEvent()
或 onTileLeaveEvent()
,則應遷移至 onRecentInteractionEventsAsync()
。從 API 36 開始,系統會批次處理這些事件。
調整版面配置產生程式碼
在 ProtoLayout 1.2 (M2.5) 中,onTileRequest()
方法會傳回 TileBuilders.Tile
。這個物件包含各種元素,包括 TimelineBuilders.Timeline
,而後者又包含 LayoutElement
,用於說明動態磚的 UI。
在 ProtoLayout 1.3 (M3) 中,雖然整體資料結構和流程沒有改變,但 LayoutElement
現在是採用以 Compose 為靈感的做法建構,並以定義的插槽為基礎配置版面 (從上到下依序為 titleSlot
(選用;通常用於主要標題或標頭)、mainSlot
(必要;用於核心內容) 和 bottomSlot
(選用;通常用於動作,例如邊緣按鈕,或補充資訊,例如簡短文字)。這個版面配置是由 primaryLayout()
函式建構。

比較版面配置 M2.5 和 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) })
}
如要強調主要差異,請按照下列步驟操作:
- 淘汰建構函式。傳統的 Material 3 UI 元件建構器模式,已由更具宣告性的 Compose 風格語法取代。(字串/顏色/修飾符等非 UI 元件也會取得新的 Kotlin 包裝函式)。
- 標準化初始化和版面配置函式。M3 版面配置依賴標準化的初始化和結構函式:
materialScope()
和primaryLayout()
。這些必要函式會初始化 M3 環境 (主題設定、透過materialScope
的元件範圍),並定義主要以插槽為基礎的版面配置 (透過primaryLayout
)。每個版面配置都必須準確呼叫這兩個函式一次。
主題設定
顏色
Material 3 Expressive 的一大特色是「動態主題」:啟用這項功能 (預設為啟用) 的圖塊會以系統提供的主題顯示 (適用情形取決於使用者的裝置和設定)。
M3 的另一項變更,是擴充了顏色權杖的數量,從 4 個增加到 29 個。新的顏色符記位於 ColorScheme
類別中。
Typography
與 M2.5 類似,M3 大量採用預先定義的字型大小常數,因此不建議直接指定字型大小。這些常數位於 Typography
類別中,提供稍微擴大的範圍,以及更多具表現力的選項。
如要查看完整詳細資料,請參閱字體排版說明文件。
形狀
大多數 M3 元件的形狀和顏色維度都可能有所不同。
形狀為 full
的 textButton
(位於 mainSlot
中):

具有 small
形狀的相同 textButton:

元件
M3 元件比 M2.5 對應元件更具彈性,也更方便設定。M2.5 通常需要不同的元件來處理各種視覺效果,但 M3 經常採用通用但高度可設定的「基礎」元件,並提供良好的預設值。
這項原則適用於「根」版面配置。在 M2.5 中,這可以是 PrimaryLayout
或 EdgeContentLayout
。在 M3 中,建立單一頂層 MaterialScope
後,系統會呼叫 primaryLayout()
函式。這會直接傳回根版面配置 (不需要建構工具),並接受多個「版位」的 LayoutElements
,例如 titleSlot
、mainSlot
和 bottomSlot
。這些版位可填入具體的 UI 元件,例如 text()、button() 或 card() 傳回的元件,或是版面配置結構,例如 LayoutElementBuilders
中的 Row
或 Column
。
主題是 M3 的另一項重大強化功能。根據預設,UI 元素會自動遵循 M3 樣式規格,並支援動態主題。
M2.5 | M3 |
---|---|
互動式元素 | |
Button 或 Chip |
|
Text | |
Text |
text() |
進度指標 | |
CircularProgressIndicator |
circularProgressIndicator() 或 segmentedCircularProgressIndicator() |
版面配置 | |
PrimaryLayout 或 EdgeContentLayout |
primaryLayout() |
— | buttonGroup() |
圖片 | |
— | icon() 、avatarImage() 或 backgroundImage() |
修飾符
在 M3 中,您用來裝飾或擴增元件的 Modifiers
更像 Compose。這項變更會自動建構適當的內部型別,進而減少樣板。(這項變更與 M3 UI 元件的使用方式正交;如有需要,您可以搭配 M3 UI 元件使用 ProtoLayout 1.2 的建構工具樣式修飾符,反之亦然)。
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)
您可以使用任一 API 樣式建構修飾符,也可以使用 toProtoLayoutModifiers()
擴充功能函式將 LayoutModifier
轉換為 ModifiersBuilders.Modifier
。
輔助函式
雖然 ProtoLayout 1.3 允許使用 Compose 風格的 API 表示許多 UI 元件,但 LayoutElementBuilders
的基礎版面配置元素 (例如列和欄) 仍會使用建構工具模式。為彌補這種風格差異,並提升與新版 M3 元件 API 的一致性,建議使用輔助函式。
不含 Helpers
primaryLayout(
mainSlot = {
LayoutElementBuilders.Column.Builder()
.setWidth(expand())
.setHeight(expand())
.addContent(text("A".layoutString))
.addContent(text("B".layoutString))
.addContent(text("C".layoutString))
.build()
}
)
With Helpers
// 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))
}
}
)
遷移至 Tiles 1.2 / ProtoLayout 1.0
自 1.2 版起,大多數的資訊方塊版面配置 API 都位於 androidx.wear.protolayout
命名空間中。如要使用最新的 API,請完成下列程式碼遷移步驟。
更新依附元件
在應用程式模組的建構檔案中進行下列變更:
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")
更新命名空間
在應用程式的 Kotlin 和 Java 程式碼檔案中進行下列更新。或者,您也可以執行這段命名空間重新命名指令碼。
- 將所有的
androidx.wear.tiles.material.*
匯入項目替換為androidx.wear.protolayout.material.*
。請同時為androidx.wear.tiles.material.layouts
程式庫完成這個步驟。 將大多數其他
androidx.wear.tiles.*
匯入項目替換為androidx.wear.protolayout.*
。androidx.wear.tiles.EventBuilders
、androidx.wear.tiles.RequestBuilders
、androidx.wear.tiles.TileBuilders
和androidx.wear.tiles.TileService
的匯入項目應維持不變。重新命名 TileService 和 TileBuilder 類別的幾個已淘汰的方法:
TileBuilders
:將getTimeline()
重新命名為getTileTimeline()
、setTimeline()
重新命名為setTileTimeline()
TileService
:將onResourcesRequest()
重新命名為onTileResourcesRequest()
RequestBuilders.TileRequest
:將getDeviceParameters()
重新命名為getDeviceConfiguration()
、setDeviceParameters()
重新命名為setDeviceConfiguration()
、getState()
重新命名為getCurrentState()
,以及setState()
重新命名為setCurrentState()