Od wersji 1.2 kafelków możesz przesyłać strumieniowo aktualizacje danych platformy za pomocą wyrażenia dynamiczne. Następnie możesz powiązać te aktualizacje z animacjami. w swoich kafelkach. Aplikacja aktualizuje tę wartość co sekundę.
Dzięki zastosowaniu wyrażeń dynamicznych nie musisz odświeżać całego kafelka, gdy jest zmian treści. Aby zwiększyć zaangażowanie kafelków, włącz animację tych dynamicznych obiektów.
Powiąż wyrażenia dynamiczne ze źródłami danych
androidx.wear.protolayout
i androidx.wear.protolayout.material
przestrzenie nazw zawierają wiele klas, których pola przyjmują wyrażenia dynamiczne.
Oto kilka przykładów:
- Kilku wartości długości, w tym długości obiektu
Arc
oraz długość obiektuCircularProgressIndicator
. - Dowolny kolor, na przykład kolor treści obiektu
Button
. - wielu wartości ciągów znaków, w tym zawartości obiektu
Text
, zawartość obiektuLayoutElementsBuilders.Text
oraz zawartość opis obiektuCircularProgressIndicator
.
Aby użyć wyrażenia dynamicznego jako możliwej wartości elementu w kafelku, użyj funkcji
odpowiedni typ właściwości dynamicznej *Prop
i przekazać dane.
źródło do klasy konstruktora klasy usługi dynamicznej typu setDynamicValue()
.
Kafelki obsługują te typy właściwości dynamicznych:
- W przypadku wymiarów liniowych mierzonych w pikselach niezależnych od wyświetlania użyj funkcji
DimensionBuilders.DpProp
- W przypadku wymiarów kątowych mierzonych w stopniach należy użyć funkcji
DimensionBuilders.DegreesProp
- Jako wartości ciągów znaków użyj
TypeBuilders.StringProp
. - Jako wartości kolorów użyj
ColorBuilders.ColorProp
. - W przypadku wartości zmiennoprzecinkowych użyj
TypeBuilders.FloatProp
.
Jeśli używasz wyrażenia dynamicznego, które wpływa na wymiary fizyczne – dowolna wartość w argumencie
kafelka oprócz koloru – musisz też określić zestaw powiązanych ograniczeń, takich jak
w formacie ciągu znaków. Dzięki tym ograniczeniom system renderowania może określić
maksymalna ilość miejsca, jaką dana wartość może zająć na kafelku. Zwykle
określaj te ograniczenia na poziomie elementu, a nie wyrażenia dynamicznego
poziomu za pomocą metody, która rozpoczyna się od setLayoutConstraintsForDynamic*
.
Fragment kodu poniżej pokazuje, jak wyświetlać aktualizacje tętna za pomocą 3
cyfry, z wartością zastępczą --
:
Kotlin
import androidx.wear.protolayout.material.Text public 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(), StringLayoutConstraint.Builder("000") .build() ).build() ) ).build() )
Java
import androidx.wear.protolayout.material.Text; @Override protected ListenableFuture<Tile> onTileRequest( @NonNull TileRequest requestParams ) { return Futures.immediateFuture(new Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setFreshnessIntervalMillis(60 * 60 * 1000) // 60 minutes .setTileTimeline(Timeline.fromLayoutElement( new Text.Builder( this, new TypeBuilders.StringProp.Builder("--") .setDynamicValue(PlatformHealthSources.heartRateBpm() .format() .concat(DynamicBuilders.DynamicString.constant(" bpm"))) .build(), new StringLayoutConstraint.Builder("000") .build() ).build()) ).build() ); }
Używaj małej liczby wyrażeń w jednym kafelku
Wear OS nakłada limit liczby wyrażeń, które można dodać do jednego kafelka użytkowników. Jeśli kafelek zawiera zbyt wiele wyrażeń dynamicznych, wartości dynamiczne są ignorowany, a system wraca do wartości statycznych, które podasz odpowiednich typów usług dynamicznych.
Możesz bezpiecznie dodać do kafelka poniższy zestaw wyrażeń, ponieważ nie ma zbyt wielu wyrażeń. W związku z tym kafelek działa prawidłowo:
Kotlin
val personHealthInfo = DynamicString.constant("This person has walked ") .concat(PlatformHealthSources.dailySteps() .div(1000) .format()) .concat("thousands of steps and has a current heart rate ") .concat(PlatformHealthSources.heartRateBpm() .format()) .concat(" beats per minute")
Java
DynamicString personHealthInfo = DynamicString.constant("This person has walked ") .concat(PlatformHealthSources.dailySteps() .div(1000) .format()) .concat("thousands of steps and has a current heart rate ") .concat(PlatformHealthSources.heartRateBpm() .format()) .concat(" beats per minute");
Ten kafelek może mieć jednak zbyt wiele wyrażeń:
Kotlin
// Note that this template is applied as many times as the loop iterates. // The system doesn't reuse dynamic expressions. val dynamicStringTemplate = PlatformHealthSources.dailySteps() .div(1000) .format() for (person in people) { // SomeProperty .setDynamicValue( DynamicBuilders.DynamicString.constant("Steps for ") .concat(person) .concat(" are ") .concat(dynamicStringTemplate) ) }
Java
// Note that this template is applied as many times as the loop iterates. // The system doesn't reuse dynamic expressions. DynamicString dynamicStringTemplate = PlatformHealthSources.dailySteps() .div(1000) .format(); for (int i = 0; i < people.size(); i++) { // SomeProperty .setDynamicValue( DynamicBuilders.DynamicString.constant("Steps for ") .concat(people[i]) .concat(" are ") .concat(dynamicStringTemplate) ); }
Skonsoliduj dane dynamiczne w obiekcie stanu
Możesz skonsolidować najnowszy zestaw aktualizacji ze źródeł danych w stan, który jest przekazywany do kafelka w celu renderowania wartości.
Aby użyć informacji o stanie w kafelkach, wykonaj te czynności:
Utwórz zestaw kluczy reprezentujących różne wartości stanu. W tym przykładzie tworzymy klucze do picia wody i nutę:
Kotlin
companion object { val KEY_WATER_INTAKE = AppDataKey<DynamicInt32>("water_intake") val KEY_NOTE = AppDataKey<DynamicString>("note") }
Java
private static final AppDataKey<DynamicInt32> KEY_WATER_INTAKE = new AppDataKey<DynamicInt32>("water_intake"); private static final AppDataKey<DynamicString> KEY_NOTE = new AppDataKey<DynamicString>("note");
W ramach implementacji kodu
onTileRequest()
wywołajsetState()
i ustal początkowe mapowania z każdego klucza na określoną wartość danych dynamicznych:Kotlin
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() )
Java
@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() ); }
Podczas tworzenia układu – w miejscu, w którym chcesz wyświetlać te dane ze stanu, użyj obiektu typu
Dynamic*
. Możesz też zadzwonić pod numeranimate()
, aby pokazana jest animacja zmiany poprzedniej wartości na obecną:Kotlin
DynamicInt32.from(KEY_WATER_INTAKE).animate()
Java
DynamicInt32.from(KEY_WATER_INTAKE).animate();
W razie potrzeby możesz też zaktualizować stan o nowe wartości. Może to być w obszarze
LoadAction
kafelka.W tym przykładzie wartość spożycia wody jest aktualizowana na
400
:Kotlin
state.addKeyToValueMapping(KEY_WATER_INTAKE, DynamicDataBuilders.DynamicDataValue.fromInt(400))
Java
state.addKeyToValueMapping(KEY_WATER_INTAKE, DynamicDataBuilders.DynamicDataValue.fromInt(400));
Polecane dla Ciebie
- Uwaga: tekst linku wyświetla się, gdy JavaScript jest wyłączony
- Migracja do przestrzeni nazw ProtoLayout
- Pierwsze kroki z kafelkami
- Inne uwagi