Od wersji 1.2 aplikacji Tiles możesz przesyłać strumieniowo aktualizacje danych platformy za pomocą wyrażeń dynamicznych. Następnie możesz powiązać te aktualizacje z animowanymi kafelkami. Aplikacja otrzymuje aktualizacje tej wartości co sekundę.
Dzięki wyrażeniom dynamicznym nie musisz odświeżać całej płytki, gdy zmienia się jej zawartość. Aby zwiększyć atrakcyjność kafelków, umieść na nich dynamiczne obiekty.
Powiązanie wyrażeń dynamicznych ze źródłami danych
Przestrzeń nazw androidx.wear.protolayout
i androidx.wear.protolayout.material
zawiera wiele klas, których pola akceptują wyrażenia dynamiczne.
Oto kilka przykładów:
- kilka wartości długości, w tym długość obiektu
Arc
i długość obiektuCircularProgressIndicator
; - dowolny kolor, np. kolor treści obiektu
Button
; - Wiele wartości ciągu znaków, w tym treści obiektu
Text
, treści obiektuLayoutElementsBuilders.Text
i treści opisu obiektuCircularProgressIndicator
.
Aby użyć wyrażenia dynamicznego jako możliwej wartości elementu na karcie, użyj odpowiedniego typu właściwości dynamicznej *Prop
elementu i przekaż źródło danych do metody setDynamicValue()
klasy konstruktora typu właściwości dynamicznej.
Kafelki obsługują te typy usług dynamicznych:
- W przypadku wymiarów liniowych wyrażonych w pikselach niezależnych od wyświetlacza używaj
DimensionBuilders.DpProp
. - W przypadku wymiarów kątowych mierzonych w stopniach używaj wartości
DimensionBuilders.DegreesProp
. - W przypadku wartości tekstowych użyj wartości
TypeBuilders.StringProp
. - W przypadku 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 płytce z wyjątkiem koloru), musisz też określić zestaw powiązanych ograniczeń, np. w formacie ciągu znaków. Te ograniczenia umożliwiają systemowi renderowania określenie maksymalnej ilości miejsca, jaką dana wartość może zajmować na kafelku. Zwykle te ograniczenia określasz na poziomie elementu, a nie wyrażenia dynamicznego, wywołując metodę, która zaczyna się od setLayoutConstraintsForDynamic*
.
Ten fragment kodu pokazuje, jak wyświetlać tętno z aktualizacjami w postaci 3 cyfr, z wartością zastępczą --
:
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() )
Używanie niewielkiej liczby wyrażeń na jednej karcie
Wear OS nakłada limit liczby wyrażeń, które może zawierać pojedyncza ikona. Jeśli kafelek zawiera zbyt wiele wyrażeń dynamicznych, wartości dynamiczne są ignorowane, a system używa wartości statycznych podanych przez Ciebie dla odpowiednich typów usług dynamicznych.
Konsolidowanie danych dynamicznych w obiekcie stanu
Możesz scalić najnowszy zestaw aktualizacji ze źródeł danych w stanie, który przekazujesz do swojej płytki na potrzeby renderowania wartości.
Aby używać informacji o stanie na kafelkach, wykonaj te czynności:
Utwórz zestaw kluczy, które reprezentują różne wartości stanu kafelka. W tym przykładzie tworzymy klucze dotyczące spożycia wody i notatki:
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 implementacji funkcji
onTileRequest()
wywołaj funkcjęsetState()
i ustaw początkowe mapowania każdego klucza do konkretnej wartości 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 z stanu, użyj obiektu typu
Dynamic*
. Możesz też wywołać funkcjęanimate()
, aby wyświetlić animację przejścia od poprzedniej wartości do bieżącej:Kotlin
DynamicInt32.from(KEY_WATER_INTAKE).animate()
Java
DynamicInt32.from(KEY_WATER_INTAKE).animate();
W razie potrzeby możesz też zaktualizować stan za pomocą nowych wartości. Może ona być częścią
LoadAction
.W tym przykładzie wartość spożycia wody została zaktualizowana na
400
:Kotlin
val loadAction = LoadAction.Builder() .setRequestState( State.Builder() .addKeyToValueMapping( KEY_WATER_INTAKE, DynamicDataBuilders.DynamicDataValue.fromInt(400) ) .build() ) .build()
Java
LoadAction loadAction = new LoadAction.Builder() .setRequestState( new State.Builder() .addKeyToValueMapping( KEY_WATER_INTAKE, DynamicDataBuilders.DynamicDataValue.fromInt(400) ).build() ).build();
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy obsługa JavaScript jest wyłączona
- Migracja do przestrzeni nazw ProtoLayout
- Pierwsze kroki z kafelkami
- Inne kwestie