Kafelki obsługują kilka różnych metod animacji, w tym:
- Przejścia z efektem przesuwania za pomocą animacji tweening.
- Płynne przejścia animacji wchodzenia i wychodzenia z kafelka.
- Animacje Lottie.
Wyświetlanie przejścia z przesunięciem
Aby wyświetlić płynne przejście od jednej wartości do drugiej, możesz włączyć animacje przejścia elementu, jak pokazano w tym fragmencie kodu:
private var startValue = 15f private var endValue = 105f private val animationDurationInMillis = 2000L // 2 seconds override fun onTileRequest(requestParams: RequestBuilders.TileRequest): ListenableFuture<Tile> { val circularProgressIndicator = CircularProgressIndicator.Builder() .setProgress( FloatProp.Builder(/* static value */ 0.25f) .setDynamicValue( // Or you can use some other dynamic object, for example // from the platform and then at the end of expression // add animate(). DynamicFloat.animate( startValue, endValue, AnimationSpec.Builder() .setAnimationParameters( AnimationParameters.Builder() .setDurationMillis(animationDurationInMillis) .build() ) .build(), ) ) .build() ) .build() return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement(circularProgressIndicator)) .build() ) }
Ustawianie kierunku łuku
Jeśli element zawiera łuk, możesz nie chcieć, aby linia łuku lub tekst zawsze powiększały się w domyślnym kierunku tekstu dla wybranego przez użytkownika języka. Aby określić kierunek wzrostu łuku, użyj interfejsów API ArcDirection
:
public override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile> { return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( EdgeContentLayout.Builder(deviceParameters) .setResponsiveContentInsetEnabled(true) .setEdgeContent( Arc.Builder() // Arc should always grow clockwise. .setArcDirection(LayoutElementBuilders.ARC_DIRECTION_CLOCKWISE) .addContent( ArcLine.Builder() // Set color, length, thickness, and more. // Arc should always grow clockwise. .setArcDirection( LayoutElementBuilders.ARC_DIRECTION_CLOCKWISE ) .build() ) .build() ) .build() ) ) .build() ) }
Wyświetlanie płynnego przejścia lub przesunięcia
Aby wyraźniej wskazać, że element pojawia się lub znika w kafelku, lub aby subtelniej pokazać zmianę wartości kafelka, użyj w animacjach kafelków efektów zanikania i przesuwania.
Jeśli układ kafelków zawiera element, którego wartość się zmienia, kafelek wyświetla animację wyjścia elementu, a następnie aktualizuje układ i wyświetla animację wejścia elementu.
Przejścia z efektem zanikania
Poniższy fragment kodu pokazuje, jak za pomocą metod pomocniczych z DefaultContentTransitions
przeprowadzić przejścia z efektem pojawiania się i znikania. Aby zdefiniować niestandardowe obiekty FadeInTransition
i FadeOutTransition
, wywołaj odpowiednio metody setFadeIn()
i setFadeOut()
w metodach ustawiających przejście.
public override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile> { // Assumes that you've defined a custom helper method called // getTileTextToShow(). val tileText = getTileTextToShow() return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, tileText) .setModifiers( Modifiers.Builder() .setContentUpdateAnimation( AnimatedVisibility.Builder() .setEnterTransition(DefaultContentTransitions.fadeIn()) .setExitTransition(DefaultContentTransitions.fadeOut()) .build() ) .build() ) .build() ) ) .build() ) }
Przejścia między slajdami
Ten fragment kodu pokazuje, jak wykonywać przejścia wsuwania i wysuwania za pomocą metod pomocniczych z DefaultContentTransitions
. Możesz też zdefiniować niestandardowe obiekty SlideInTransition
i SlideOutTransition
, wywołując odpowiednio funkcje setSlideIn()
i setSlideOut()
w metodach ustawiających przejście.
public override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile> { // Assumes that you've defined a custom helper method called // getTileTextToShow(). val tileText = getTileTextToShow() return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, tileText) .setModifiers( Modifiers.Builder() .setContentUpdateAnimation( AnimatedVisibility.Builder() .setEnterTransition( DefaultContentTransitions.slideIn( ModifiersBuilders.SLIDE_DIRECTION_LEFT_TO_RIGHT ) ) .setExitTransition( DefaultContentTransitions.slideOut( ModifiersBuilders.SLIDE_DIRECTION_LEFT_TO_RIGHT ) ) .build() ) .build() ) .build() ) ) .build() ) }
Wyświetlanie przekształcenia
Aby zwrócić uwagę na konkretny element lub obszar w karcie, możesz zastosować do niego kilka rodzajów przekształceń, w tym obrót, skalowanie i przesunięcie.
Wiele wartości zmiennoprzecinkowych powiązanych z przekształceniami akceptuje dynamiczne wyrażenia, które umożliwiają animowanie tych przekształceń.
Obrót
Aby wykonać obrót w kierunku zgodnym z ruchem wskazówek zegara wokół dostosowywanego punktu obrotu, użyj kodu podobnego do tego:
return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, someTileText) .setModifiers( Modifiers.Builder() .setTransformation( ModifiersBuilders.Transformation.Builder() // Set the pivot point 50 dp from the left edge // and 100 dp from the top edge of the screen. .setPivotX(dp(50f)) .setPivotY(dp(100f)) // Rotate the element 45 degrees clockwise. .setRotation(degrees(45f)) .build() ) .build() ) .build() ) ) .build() )
Skalowanie
Aby powiększyć lub pomniejszyć element o współczynniki skalowania w pionie i poziomie, użyj kodu podobnego do tego:
return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, someTileText) .setModifiers( Modifiers.Builder() .setTransformation( ModifiersBuilders.Transformation.Builder() // Set the pivot point 50 dp from the left edge // and 100 dp from the top edge of the screen. .setPivotX(dp(50f)) .setPivotY(dp(100f)) // Shrink the element by a scale factor // of 0.5 horizontally and 0.75 vertically. .setScaleX(FloatProp.Builder(0.5f).build()) .setScaleY(FloatProp.Builder(0.75f).build()) .build() ) .build() ) .build() ) ) .build() )
Tłumaczenie geometryczne
Aby przesunąć element o określoną liczbę pikseli gęstości (dp) na ekranie w poziomie lub w pionie, użyj kodu podobnego do tego:
return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline( Timeline.fromLayoutElement( Text.Builder(this, someTileText) .setModifiers( Modifiers.Builder() .setTransformation( ModifiersBuilders.Transformation.Builder() // Translate (move) the element 60 dp to the right // and 80 dp down. .setTranslationX(dp(60f)) .setTranslationY(dp(80f)) .build() ) .build() ) .build() ) ) .build() )
Animacje Lottie
Kafelki obsługują odtwarzanie animacji Lottie przy użyciu składni podobnej do składni obrazów:
class LottieAnimation : TileService() { val lottieResourceId = "lottie_animation" override fun onTileRequest(requestParams: RequestBuilders.TileRequest): ListenableFuture<Tile> { val layout = LayoutElementBuilders.Image.Builder() .setWidth(dp(150f)) .setHeight(dp(150f)) .setResourceId(lottieResourceId) .build() return Futures.immediateFuture( Tile.Builder() .setResourcesVersion(RESOURCES_VERSION) .setTileTimeline(Timeline.fromLayoutElement(layout)) .build() ) } override fun onTileResourcesRequest( requestParams: ResourcesRequest ): ListenableFuture<Resources> { val lottieImage = ResourceBuilders.ImageResource.Builder() .setAndroidLottieResourceByResId( ResourceBuilders.AndroidLottieResourceByResId.Builder(R.raw.lottie) .setStartTrigger(createOnVisibleTrigger()) .build() ) .build() return Futures.immediateFuture( Resources.Builder() .setVersion(requestParams.version) .addIdToImageMapping(lottieResourceId, lottieImage) .build() ) } }
Kilka uwag:
- Obsługiwany jest tylko podzbiór plików Lottie. Sprawdź zgodność za pomocą jednego z tych walidatorów:
- Weryfikator online: https://skottie.skia.org/. W sekcji „Raport zgodności” plik musi przejść testy „Błędy specyfikacji”, „Ostrzeżenia dotyczące specyfikacji” (z ignorowaniem właściwości wspólnych) i „Błędy profilu niskiego zużycia energii”.
- Biblioteka weryfikacji w języku Rust: https://github.com/google/lottie-tools.
- Odtwarzanie animacji Lottie jest obsługiwane przez programy renderujące kafelki w wersji głównej co najmniej
1
i wersji podrzędnej co najmniej500
. Jeśli dana animacja nie jest obsługiwana, nie będzie się wyświetlać, ale reszta kafelka będzie renderowana zgodnie z oczekiwaniami. W razie potrzeby możesz podać opcję rezerwową, np. obraz statyczny.
Nie wyświetlaj ważnych informacji w środku animacji.
Animacje są wyłączone w kilku sytuacjach:
- Renderowanie kafelków przez system może wyłączyć animacje wszystkich kafelków.
- Kafel może animować tylko 4 elementy naraz. Jeśli spróbujesz animować więcej niż 4 elementy jednocześnie, nie wszystkie będą animowane.
Jeśli animacja jest wyłączona, elementy są statyczne i wyświetlają wartość końcową animacji. Z tego powodu nie polegaj na zachowaniu animacji, np. na jej czasie trwania, aby wyświetlać ważne informacje.