タイルに動的な更新を表示する

Tiles 1.2 以降では、動的式を使用して、プラットフォーム データの更新をストリーミングできます。そのうえでこのような更新をタイル内のアニメーションに関連付けられます。アプリはこの値を毎秒更新します。

動的式を使用すると、コンテンツを変更したときにタイル全体を更新する必要がありません。タイルでより魅力的な体験ができるようにするには、そのような動的オブジェクトをアニメーション化します。

動的式をデータソースに関連付ける

androidx.wear.protolayout 名前空間と androidx.wear.protolayout.material 名前空間には、フィールドで動的式が使えるクラスが多数含まれています。以下はその一例です。

タイル内の要素の許容値として動的式を使用するには、要素に対応する *Prop 動的プロパティ型を使用して、データソースを動的プロパティ型のビルダークラスの setDynamicValue() メソッドに渡します。

タイルは次の動的プロパティ型をサポートしています。

物理寸法(色以外のタイル内の値)に影響を与える動的式を使用する場合は、文字列形式などの関連する制約も指定する必要があります。これらの制約に基づき、システム レンダラはタイル内で値が占有できる最大スペースを決定します。通常、この制約は動的式レベルではなく、要素レベルで指定します。指定するには setLayoutConstraintsForDynamic* で始まるメソッドを呼び出します。

以下のコード スニペットは、3 桁の値とフォールバック値 -- を使用して、心拍数の更新を表示する方法を示しています。

override fun onTileRequest(requestParams: RequestBuilders.TileRequest) =
    Futures.immediateFuture(
        Tile.Builder()
            .setResourcesVersion(RESOURCES_VERSION)
            .setFreshnessIntervalMillis(60 * 60 * 1000) // 60 minutes
            .setTileTimeline(
                Timeline.fromLayoutElement(
                    Text.Builder(
                        this,
                        TypeBuilders.StringProp.Builder("--")
                            .setDynamicValue(
                                PlatformHealthSources.heartRateBpm()
                                    .format()
                                    .concat(DynamicBuilders.DynamicString.constant(" bpm"))
                            )
                            .build(),
                        TypeBuilders.StringLayoutConstraint.Builder("000").build(),
                    )
                        .build()
                )
            )
            .build()
    )

1 つのタイル内で限られた数の式を使用する

Wear OS では、1 つのタイルに設定できる式の数に上限が設定されています。タイルに含まれる動的式が多すぎる場合、動的な値は無視され、システムはそれぞれの動的プロパティ型で指定された静的な値にフォールバックします。

動的データを状態オブジェクトに統合する

データソースからの最新の更新セットを状態に統合して、それをタイルに渡し、値をレンダリングできます。

タイルの状態情報を使用する手順は次のとおりです。

  1. タイルの状態のさまざまな値を表すキーのセットを設定します。この例では、水分摂取量と qqq メモのキーを作成します。

    companion object {
        val KEY_WATER_INTAKE = intAppDataKey("key_water_intake")
        val KEY_NOTE = stringAppDataKey("key_note")
    }

  2. onTileRequest() の実装で setState() を呼び出し、各キーから特定の動的データ値への初期マッピングを設定します。

    override fun onTileRequest(
        requestParams: RequestBuilders.TileRequest
    ): ListenableFuture<Tile?> {
        // If the tile hasn't had any state set yet, use the default values
        val state =
            if (requestParams.currentState.keyToValueMapping.isNotEmpty())
                requestParams.currentState
            else
                StateBuilders.State.Builder()
                    .setStateMap(
                        dynamicDataMapOf(
                            KEY_WATER_INTAKE mapTo 200,
                            KEY_NOTE mapTo "Good"
                        )
                    )
                    .build()
    
        return Futures.immediateFuture(
            Tile.Builder()
                // Set resources, timeline, and other tile properties.
                .setState(state)
                .build()
        )
    }

  3. レイアウトを作成する際に、状態からのこのデータを表示する場所では Dynamic* タイプのオブジェクトを使用します。animate() を呼び出して、前の値から現在の値までのアニメーションを表示することもできます。

    val waterIntakeValue =
        DynamicBuilders.DynamicInt32.from(KEY_WATER_INTAKE)

  4. 必要に応じて、新しい値を使って状態を更新することもできます。これはタイルの LoadAction の一部として設定できます。

    この例では、水分摂取量を 400 に更新します。

    val loadAction =
        loadAction(
            dynamicDataMapOf(
                KEY_WATER_INTAKE mapTo 400,
                KEY_NOTE mapTo "Outstanding"
            )
        )