Kachelanimationen

Kacheln unterstützen verschiedene Animationsansätze, darunter die folgenden:

Wischblende einfügen

Wenn Sie einen sanften Übergang von einem Wert zu einem anderen darstellen möchten, können Sie Tween-Animationen für ein Element aktivieren, wie im folgenden Code-Snippet gezeigt:

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

Richtung des Bogens festlegen

Wenn Ihre Kachel einen Bogen enthält, soll die Bogenlinie oder der Text möglicherweise nicht immer in der Standardtextrichtung für die vom Nutzer ausgewählte Sprache wachsen. Verwenden Sie die ArcDirection-APIs, um eine Richtung für das Wachstum des Bogens anzugeben:

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

Ein sanftes Ein- oder Ausblenden anzeigen

Um deutlicher zu machen, dass ein Element in einer Kachel ein- oder ausgeblendet wird, oder um eine plötzliche Änderung des Werts einer Kachel subtiler darzustellen, können Sie in Ihren Kachel-Animationen Ein- und Ausblendungs- sowie Ein- und Ausgleiteffekte verwenden.

Wenn ein Kachel-Layout ein Element enthält, dessen Wert sich ändert, wird die Exit-Animation des Elements angezeigt. Anschließend wird das Layout aktualisiert und die Enter-Animation des Elements wird eingeblendet.

Ein- und Ausblendungen

Das folgende Code-Snippet zeigt, wie Ein- und Ausblendungen mit den Hilfsmethoden aus DefaultContentTransitions durchgeführt werden. Um benutzerdefinierte FadeInTransition- und FadeOutTransition-Objekte zu definieren, rufen Sie setFadeIn() bzw. setFadeOut() in den Setter-Methoden für Übergänge auf.

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

Folienübergänge

Das folgende Code-Snippet zeigt, wie Ein- und Ausblendungseffekte mit den Hilfsmethoden aus DefaultContentTransitions ausgeführt werden. Sie können auch benutzerdefinierte SlideInTransition- und SlideOutTransition-Objekte definieren, indem Sie setSlideIn() bzw. setSlideOut() in den Setter-Methoden für Übergänge aufrufen.

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

Transformation anzeigen

Um die Aufmerksamkeit auf ein bestimmtes Element oder einen bestimmten Bereich in einer Kachel zu lenken, können Sie verschiedene Arten von Transformationen darauf anwenden, z. B. Drehung, Skalierung und Translation.

Viele Gleitkommawerte, die mit Transformationen verknüpft sind, akzeptieren dynamische Ausdrücke, mit denen Sie diese Transformationen animieren können.

Ausrichtung

Wenn Sie eine Drehung im Uhrzeigersinn um einen anpassbaren Drehpunkt ausführen möchten, verwenden Sie Code wie den folgenden:

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

Skalierung

Wenn Sie ein Element mit horizontalen und vertikalen Skalierungsfaktoren vergrößern oder verkleinern möchten, verwenden Sie Code wie den folgenden:

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

Geometrische Übersetzung

Wenn Sie ein Element um eine bestimmte Anzahl von geräteunabhängigen Pixeln (dp) horizontal oder vertikal über den Bildschirm bewegen möchten, verwenden Sie Code wie den folgenden:

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

Lottie-Animationen

Kacheln unterstützen die Wiedergabe von Lottie-Animationen mit einer ähnlichen Syntax wie bei Bildern:

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

Beachten Sie folgende Punkte:

  • Es wird nur eine Teilmenge von Lottie-Dateien unterstützt. Prüfen Sie die Kompatibilität mit einem der folgenden Validatoren:
    • Online-Validator: https://skottie.skia.org/ Im Bereich „Kompatibilitätsbericht“ muss die Datei die Tests „Spezifikationsfehler“, „Spezifikationswarnungen“ (mit ignorierten allgemeinen Eigenschaften) und „Fehler im Low-Power-Profil“ bestehen.
    • Eine Rust-Validierungsbibliothek: https://github.com/google/lottie-tools.
  • Die Lottie-Wiedergabe wird von Tile-Renderern mit einer Hauptversion von mindestens 1 und einer Nebenversion von mindestens 500 unterstützt. Wenn eine bestimmte Animation nicht unterstützt wird, wird sie nicht angezeigt. Der Rest der Kachel wird jedoch wie erwartet gerendert. Bei Bedarf können Sie eine Fallback-Option wie ein statisches Bild angeben.

Wichtige Informationen nicht in der Mitte einer Animation anzeigen

Es gibt mehrere Situationen, in denen Animationen deaktiviert sind:

  • Das Rendern von Kacheln durch das System kann Animationen für alle Kacheln deaktivieren.
  • Eine Kachel kann jeweils nur vier Elemente animieren. Wenn Sie versuchen, mehr als vier Elemente gleichzeitig zu animieren, wird nicht für alle eine Animation angezeigt.

Wenn eine Animation deaktiviert ist, sind die Elemente statisch und zeigen den Endwert der Animation an. Verlassen Sie sich daher nicht auf das Verhalten der Animation, z. B. ihre Dauer, um wichtige Informationen anzuzeigen.