アプリでタイルの提供を開始するには、アプリの 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
は、アプリ リクエストの結果として、またはシステムがそれと通信する必要がある場合にバインドされます。一般的な bound-service のライフサイクルには、onCreate()
、onBind()
、onUnbind()
、onDestroy()
の 4 つのコールバック メソッドが含まれます。サービスが新しいライフサイクル フェーズに入るたびに、これらのメソッドが呼び出されます。
バインドされたサービスのライフサイクルを制御するコールバックに加えて、TileService
ライフサイクルに固有のメソッドを実装できます。すべてのタイルサービスは、システムからの更新のリクエストに応答するために、onTileRequest()
と onTileResourcesRequest()
を実装する必要があります。
onTileAddEvent()
: ユーザーが初めてタイルを追加したときと、ユーザーがタイルを削除して再度追加したときにのみ、このメソッドが呼び出されます。これが 1 回限りの初期化を行うのに最適なタイミングです。onTileAddEvent()
は、タイルのセットが再構成されたときにのみ呼び出されます。タイルがシステムによって作成されたときは必ず呼び出されません。たとえば、デバイスを再起動したときや電源を入れたときに、すでに追加されているタイルに対してonTileAddEvent()
は呼び出されません。代わりにgetActiveTilesAsync()
を使用すると、アクティブなタイルのスナップショットを取得できます。onTileRemoveEvent()
: ユーザーがタイルを削除した場合にのみ、このメソッドが呼び出されます。onTileEnterEvent()
: このプロバイダが提供するタイルが画面に表示されたときに、システムがこのメソッドを呼び出します。onTileLeaveEvent()
: このプロバイダが提供するタイルが画面の視界から外れると、システムがこのメソッドを呼び出します。onTileRequest()
: システムがこのプロバイダに新しいタイムラインをリクエストすると、システムがこのメソッドを呼び出します。onTileResourcesRequest()
: システムがこのプロバイダからリソース バンドルをリクエストすると、システムがこのメソッドを呼び出します。これは、タイルの初回読み込み時、またはリソース バージョンの変更時に発生します。
アクティブなタイルのクエリ
アクティブなタイルとは、スマートウォッチで表示するために追加されたタイルのことです。TileService
の静的メソッド getActiveTilesAsync()
を使用して、アプリに属するタイルをクエリします。
タイルの UI を作成する
タイルのレイアウトは、ビルダー パターンを使用して記述し、レイアウト コンテナと基本的なレイアウト要素からなるツリーのように作成します。各レイアウト要素にはプロパティがあり、さまざまなセッター メソッドで設定できます。
基本的なレイアウト要素
protolayout
ライブラリの次の視覚的要素とマテリアル コンポーネントがサポートされています。
Text
: テキスト文字列をレンダリングし、必要に応じて折り返します。Image
: 画像をレンダリングします。Spacer
: 要素間にパディングを設定します。背景色を設定するときは区切りとして機能します。
マテリアル コンポーネント
基本要素に加えて、protolayout-material
ライブラリにはマテリアル デザイン ユーザー インターフェースの推奨事項に沿ったタイルデザインを実現するためのコンポーネントが用意されています。
Button
: アイコンを含むようにデザインされた、クリック可能な円形のコンポーネント。Chip
: 最大 2 行のテキストと任意のアイコンを含むようにデザインされた、クリック可能なスタジアム形のコンポーネント。CompactChip
: 1 行のテキストを含むようにデザインされた、クリック可能なスタジアム形のコンポーネント。TitleChip
:Chip
に似ているが、タイトル テキストを表示できるように高さが大きくなっている、クリック可能なスタジアム形のコンポーネント。CircularProgressIndicator
:EdgeContentLayout
内に配置して画面の端に進行状況を表示できる、円形の進行状況インジケーター。
レイアウト コンテナ
次のコンテナとマテリアル レイアウトがサポートされています。
Row
: 子要素を水平方向に並べます。Column
: 子要素を垂直方向に並べます。Box
: 子要素を重ね合わせます。Arc
: 子要素を環状に並べます。Spannable
: テキストのセクションに特定のFontStyles
を適用し、テキストや画像の間に入れます。詳細については、Spannable をご覧ください。
どのコンテナにも、子を 1 つ以上含めることができます。子はコンテナにすることもできます。たとえば、Column
に子として複数の Row
要素を含めることができます。この場合、格子状のレイアウトになります。
一例として、コンテナ レイアウトと 2 つの子レイアウト要素を持つタイルは次のようになります。
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(); }
マテリアル レイアウト
基本的なレイアウトに加えて、protolayout-material
ライブラリには、特定の「スロット」内に要素を保持するための独自のレイアウトがいくつか用意されています。
PrimaryLayout
: 1 つのプライマリ アクションCompactChip
を下部に配置し、その中央にコンテンツを重ねます。MultiSlotLayout
: プライマリ ラベルとセカンダリ ラベルを配置し、その間にオプションのコンテンツを配置して、下部にオプションのCompactChip
を配置します。MultiButtonLayout
: マテリアル ガイドラインに沿って並んだボタンのセットを配置します。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
は、テキストと同様に要素をレイアウトする特別なタイプのコンテナです。大きなテキスト ブロック内の 1 つの部分文字列だけに別のスタイルを適用する場合に便利です。これは Text
要素では不可能です。
Spannable
コンテナは Span
の子で満たされます。その他の子やネストされた Spannable
インスタンスは使用できません。
Span
の子には、次の 2 種類があります。
たとえば、次のコードサンプルに示すように、「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()
メソッド内で画像を指定する方法には次の 2 つがあります。
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
- アプリ用のカスタム クイック設定タイルを作成する