如果想為應用程式提供資訊方塊,請把下列依附元件加入
應用程式的 build.gradle
檔案。
Groovy
dependencies { // Use to implement support for wear tiles implementation "androidx.wear.tiles:tiles:1.4.0" // Use to utilize standard components and layouts in your tiles implementation "androidx.wear.protolayout:protolayout:1.2.0" // Use to utilize components and layouts with Material Design in your tiles implementation "androidx.wear.protolayout:protolayout-material:1.2.0" // Use to include dynamic expressions in your tiles implementation "androidx.wear.protolayout:protolayout-expression:1.2.0" // Use to preview wear tiles in your own app debugImplementation "androidx.wear.tiles:tiles-renderer:1.4.0" // Use to fetch tiles from a tile provider in your tests testImplementation "androidx.wear.tiles:tiles-testing:1.4.0" }
Kotlin
dependencies { // Use to implement support for wear tiles implementation("androidx.wear.tiles:tiles:1.4.0") // Use to utilize standard components and layouts in your tiles implementation("androidx.wear.protolayout:protolayout:1.2.0") // Use to utilize components and layouts with Material Design in your tiles implementation("androidx.wear.protolayout:protolayout-material:1.2.0") // Use to include dynamic expressions in your tiles implementation("androidx.wear.protolayout:protolayout-expression:1.2.0") // Use to preview wear tiles in your own app debugImplementation("androidx.wear.tiles:tiles-renderer:1.4.0") // Use to fetch tiles from a tile provider in your tests testImplementation("androidx.wear.tiles:tiles-testing:1.4.0") }
建立資訊方塊
如要從應用程式提供資訊方塊,請建立可擴充 TileService
的類別並實作方法,如以下程式碼範例所示:
Kotlin
// Uses the ProtoLayout namespace for tile timeline objects. // If you haven't done so already, migrate to the ProtoLayout namespace. import androidx.wear.protolayout.TimelineBuilders.Timeline import androidx.wear.protolayout.material.Text import androidx.wear.tiles.TileBuilders.Tile private val RESOURCES_VERSION = "1" 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_DISPLAY1) .setColor(argb(0xFF000000.toInt())) .build())) .build()) override fun onTileResourcesRequest(requestParams: ResourcesRequest) = Futures.immediateFuture(Resources.Builder() .setVersion(RESOURCES_VERSION) .build() ) }
Java
// Uses the ProtoLayout namespace for tile timeline objects. // If you haven't done so already, migrate to the ProtoLayout namespace. import androidx.wear.protolayout.TimelineBuilders.Timeline; import androidx.wear.protolayout.material.Text; import androidx.wear.tiles.TileBuilders.Tile; 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) .setTileTimeline( Timeline.fromLayoutElement( new Text.Builder(this, "Hello world!") .setTypography(Typography.TYPOGRAPHY_DISPLAY1) .setColor(ColorBuilders.argb(0xFF000000)) .build())) .build() ); } @NonNull @Override protected ListenableFuture<Resources> onTileResourcesRequest( @NonNull ResourcesRequest requestParams ) { return Futures.immediateFuture(new Resources.Builder() .setVersion(RESOURCES_VERSION) .build() ); } }
接下來,請在 AndroidManifest.xml
檔案的 <application>
標記內新增服務。
<service android:name=".MyTileService" android:label="@string/tile_label" android:description="@string/tile_description" android:icon="@drawable/tile_icon_round" android:roundIcon="@drawable/tile_icon_round" 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>
權限和意圖篩選器會將此服務註冊為資訊方塊提供者。
當使用者透過手機或手錶設定資訊方塊時,可看到圖示、標籤以及說明。
透過手機調整資訊方塊時,請用預覽中繼資料標記顯示資訊方塊的預覽畫面。
資訊方塊服務生命週期總覽
在應用程式資訊清單中建立並宣告 TileService
後,
可以回應資訊方塊服務的狀態變更。
TileService
是一項「繫結服務」。您的 TileService
繫結至結果
或系統需要相互通訊的情況一般
繫結服務生命週期包含下列四種回呼方法:
onCreate()
、onBind()
、onUnbind()
和
onDestroy()
。每次服務都會叫用這些方法
就會進入新的生命週期階段
除了控制繫結服務生命週期的回呼外,
實作 TileService
生命週期特有的其他方法。所有圖塊
服務必須實作 onTileRequest()
和 onTileResourcesRequest()
以
回應來自系統的更新要求。
onTileAddEvent()
:只有在使用者時,系統才會呼叫這個方法 新增您的視訊方格;如果使用者移除並新增您的 。這就是執行任何一次性初始化的最佳時機。只有在這組圖塊重新設定時,系統才會呼叫
onTileAddEvent()
。 方塊建立時,則不會。例如,裝置在 已重新啟動或開機,但未針對資訊方塊呼叫onTileAddEvent()
您可以使用getActiveTilesAsync()
即可取得即時資訊方塊,瞭解與您擁有哪些動態磚。onTileRemoveEvent()
:只有在使用者情況下,系統才會呼叫這個方法 會移除您的動態磚。onTileEnterEvent()
:系統會在資訊方塊時呼叫這個方法 螢幕上會顯示由這個供應商提供的內容onTileLeaveEvent()
:系統會在資訊方塊時呼叫這個方法 畫面上無法顯示這個供應商提供的提示onTileRequest()
:系統會在系統呼叫這個方法時呼叫這個方法 要求這個供應商提供新的時間軸。onTileResourcesRequest()
:系統會在偵測到事件 系統要求此供應商提供資源組合。 首次載入資訊方塊或資源版本時 並輸入變更內容
查詢哪些圖塊已啟用
「主動式動態磚」是已經新增至手錶的動態磚。使用
TileService
的靜態方法 getActiveTilesAsync()
,可查詢哪些資訊方塊
不屬於您的應用程式。
建立資訊方塊 UI
資訊方塊的版面配置是以建構工具模式編寫。資訊方塊的版面配置為 這類建構過程的樹狀結構由版面配置容器和基本版面配置組成 元素。每個版面配置元素都有屬性,您可以透過各種 setter 方法進行設定。
基本的版面配置元素
系統支援 protolayout
程式庫的下列視覺元素和 Material 元件:
Material 元件
除了基礎元素之外,protolayout-material
程式庫還有提供其他元件,可確保資訊方塊設計方式符合 Material Design 使用者介面的建議事項。
Button
:可含有圖示且可供點選的圓形元件。Chip
:可含有最多兩行文字、選擇加入圖示且可供點選的體育場形元件。CompactChip
:可含有單行文字且可供點選的體育場形元件。TitleChip
:和Chip
用途類似的可點選體育場形元件,但是高度更高,可以容納標題文字。CircularProgressIndicator
:可放置在EdgeContentLayout
內的圓形進度指標,用來在螢幕邊緣顯示進度。
版面配置容器
系統支援下列容器和 Material 版面配置:
Row
:以水平方向依序排列子元素。Column
:以垂直方向依序排列子元素。Box
:讓子元素互相重疊。Arc
:以圓形排列子元素。Spannable
:為文字區段套用特定的FontStyles
,並交錯顯示文字和圖片。詳情請參閱「Spannable」。
每個容器都能包含一或多個子項,這些子項也能
容器例如,Column
可包含多個 Row
元素,如下所示:
子項,形成類似格線的版面配置。
例如,資訊方塊有一個容器版面配置和兩個子項版面配置元素 看起來會像這樣:
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(); }
Material 版面配置
除了基礎版面配置之外,protolayout-material
程式庫還有提供幾個項目
清楚明確的版面配置,能將元素固定在特定的「位置」上。
PrimaryLayout
:把單一主要操作CompactChip
放置於底部,並在上方置中顯示內容。MultiSlotLayout
:放置主要和次要標籤,並在兩個標籤之間放置選用內容,另可視需要在底部放置CompactChip
。MultiButtonLayout
:放置根據 Material Design 指南排列的一組按鈕。EdgeContentLayout
:將內容沿著螢幕邊緣排列,例如CircularProgressIndicator
。使用這個版面配置時,系統會自動為其中內容套用合適的邊界和邊框間距。
弧形
系統支援以下 Arc
容器子項:
ArcLine
:在弧形周遭轉譯曲線。ArcText
:在弧形內轉譯弧形文字。ArcAdapter
: 會在弧形內轉譯基礎版面配置元素,然後在弧形的切線上繪製。
如要進一步瞭解每種元素類型,請參閱參考文件。
修飾符
每種可用版面配置元素都可以選擇套用修飾符。以下為修飾符的使用目的:
- 變更版面配置外觀,例如為版面配置元素新增背景、框線或邊框間距。
- 新增版面配置的中繼資料,例如為版面配置元素新增語意修飾符,與螢幕閱讀器搭配使用。
- 新增功能,例如為版面配置元素新增可供點選的修飾符,讓使用者與資訊方塊互動。詳情請參閱「與資訊方塊互動」一文。
舉例來說,我們可以自訂 Image
的預設外觀和中繼資料,如以下程式碼範例所示:
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
是特殊類型的容器,可以使用和文字類似的方式排列元素。如果您想為大型文字區塊中的單一子字串套用其他樣式,而 Text
元素無法達到這個效果,就適合使用這種容器。
Spannable
容器會由 Span
子項填滿,不得使用其他子項或巢狀 Spannable
例項。
Span
子項分為兩種類型:
舉例來說,您可以把「Hello World」資訊方塊內的「world」設為斜體,並在文字間插入圖片,如以下程式碼範例所示:
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(); }
使用資源
資訊方塊無法存取應用程式的任何資源。這表示
無法將 Android 圖片 ID 傳遞至 Image
版面配置元素,並期望該元素能
解析。請改為覆寫 onTileResourcesRequest()
方法,並手動提供所有資源。
您可以透過以下兩種方式在 onTileResourcesRequest()
方法中提供圖片:
- 使用
setAndroidResourceByResId()
提供可繪製資源。 - 使用
setInlineResource()
以ByteArray
的形式提供動態圖片。
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() ); }
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- 遷移至 ProtoLayout 命名空間
- Compose 中的
ConstraintLayout
- 為應用程式建立自訂「快速設定」方塊