Показывать динамические обновления в плитках

Начиная с Tiles 1.2, вы можете передавать обновления данных платформы с помощью динамических выражений . Затем вы можете связать эти обновления с анимацией в ваших плитках. Ваше приложение получает обновления этого значения каждую секунду.

Используя динамические выражения, вам не нужно обновлять всю плитку при изменении ее содержимого. Чтобы создать более захватывающий опыт в ваших плитках, анимируйте эти динамические объекты.

Связывание динамических выражений с источниками данных

Пространства имен androidx.wear.protolayout и androidx.wear.protolayout.material содержат много классов, поля которых принимают динамические выражения. Вот несколько примеров:

Чтобы использовать динамическое выражение в качестве возможного значения элемента в плитке, используйте соответствующий тип динамического свойства *Prop элемента и передайте источник данных методу setDynamicValue() класса-конструктора динамического типа свойства.

Плитки поддерживают следующие типы динамических свойств:

При использовании динамического выражения, которое влияет на физические размеры — любое значение в плитке, за исключением цвета — необходимо также указать набор связанных ограничений, таких как формат строки. Эти ограничения позволяют системному рендереру определить максимальный объем пространства, которое значение может занимать в вашей плитке. Обычно эти ограничения указываются на уровне элемента, а не на уровне динамического выражения, вызывая метод, который начинается с setLayoutConstraintsForDynamic* .

В следующем фрагменте кода показано, как отображать обновления частоты сердечных сокращений с помощью трех цифр с резервным значением -- :

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()
    )

Используйте небольшое количество выражений в пределах одной плитки.

Wear OS накладывает ограничение на количество выражений, которые может иметь одна плитка. Если плитка содержит слишком много общих динамических выражений, динамические значения игнорируются, и система возвращается к статическим значениям, которые вы предоставляете соответствующим типам динамических свойств.

Объединить динамические данные в объект состояния

Вы можете объединить последний набор обновлений из источников данных в состояние , которое вы передадите на свою плитку для рендеринга значений.

Чтобы использовать информацию о состоянии в своих плитках, выполните следующие действия:

  1. Установите набор ключей, которые представляют различные значения состояния вашей плитки. Этот пример создает ключи для потребления воды и примечания:

    Котлин

    companion object {
        val KEY_WATER_INTAKE = AppDataKey<DynamicInt32>("water_intake")
        val KEY_NOTE = AppDataKey<DynamicString>("note")
    }

    Ява

    private static final AppDataKey<DynamicInt32> KEY_WATER_INTAKE =
        new AppDataKey<DynamicInt32>("water_intake");
    private static final AppDataKey<DynamicString> KEY_NOTE =
        new AppDataKey<DynamicString>("note");
  2. В вашей реализации onTileRequest() вызовите setState() и установите начальные сопоставления каждого ключа с определенным значением динамических данных:

    Котлин

    override fun onTileRequest(requestParams: TileRequest):
            ListenableFuture<Tile> {
        val state = State.Builder()
            .addKeyToValueMapping(KEY_WATER_INTAKE,
                DynamicDataBuilders.DynamicDataValue.fromInt(200))
            .addKeyToValueMapping(KEY_NOTE,
                DynamicDataBuilders.DynamicDataValue.fromString("Note about day"))
        .build()
        // ...
    
        return Futures.immediateFuture(Tile.Builder()
            // Set resources, timeline, and other tile properties.
            .setState(state)
            .build()
        )

    Ява

    @Override
    protected ListenableFuture<Tile> onTileRequest(
                ListenableFuture<Tile> {
        State state = new State.Builder()
            .addKeyToValueMapping(KEY_WATER_INTAKE,
                DynamicDataBuilders.DynamicDataValue.fromInt(200))
            .addKeyToValueMapping(KEY_NOTE,
                DynamicDataBuilders.DynamicDataValue.fromString("Note about day"))
        .build();
        // ...
    
        return Futures.immediateFuture(Tile.Builder()
            // Set resources, timeline, and other tile properties.
            .setState(state)
            .build()
        );
    }
  3. При создании макета, в месте, где вы хотите показать эти данные из состояния, используйте объект типа Dynamic* . Вы также можете вызвать animate() , чтобы показать анимацию от предыдущего значения к текущему значению:

    Котлин

    DynamicInt32.from(KEY_WATER_INTAKE).animate()

    Ява

    DynamicInt32.from(KEY_WATER_INTAKE).animate();
  4. При необходимости вы также можете обновить состояние новыми значениями. Это может быть частью LoadAction плитки.

    В этом примере значение водозабора обновлено до 400 :

    Котлин

    val loadAction = LoadAction.Builder()
        .setRequestState(
            State.Builder()
                .addKeyToValueMapping(
                    KEY_WATER_INTAKE,
                    DynamicDataBuilders.DynamicDataValue.fromInt(400)
                )
                .build()
        )
        .build()

    Ява

    LoadAction loadAction = new LoadAction.Builder()
        .setRequestState(
            new State.Builder()
                .addKeyToValueMapping(
                    KEY_WATER_INTAKE,
                    DynamicDataBuilders.DynamicDataValue.fromInt(400)
                ).build()
        ).build();
{% дословно %} {% endverbatim %} {% дословно %} {% endverbatim %}