Animasi kartu

Kartu mendukung beberapa pendekatan animasi yang berbeda, termasuk berikut:

Menampilkan transisi sweep

Untuk menampilkan sweep yang lancar dari satu nilai ke nilai lain, Anda dapat mengaktifkan animasi hitung nilai untuk elemen, seperti ditunjukkan dalam cuplikan kode berikut:

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

Menetapkan arah busur

Jika kartu Anda berisi busur, Anda mungkin tidak ingin garis atau teks busur selalu bertambah dalam arah teks default untuk bahasa yang dipilih pengguna. Untuk menentukan arah pertumbuhan busur, gunakan 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()
    )
}

Menampilkan efek pudar atau geser yang halus

Untuk menunjukkan dengan lebih jelas bahwa elemen muncul atau menghilang dalam kartu, atau menampilkan perubahan langkah dalam nilai kartu secara lebih halus, gunakan efek pudar dan geser dalam animasi kartu.

Jika tata letak kartu berisi elemen yang nilainya berubah, kartu tersebut akan menampilkan animasi keluar elemen, lalu memperbarui tata letak dan menampilkan animasi masuk elemen.

Transisi pudar

Cuplikan kode berikut menunjukkan cara melakukan transisi fade-in dan fade-out menggunakan metode helper dari DefaultContentTransitions. Untuk menentukan objek FadeInTransition dan FadeOutTransition kustom, panggil setFadeIn() dan setFadeOut() untuk masing-masing, di metode penyetel transisi.

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

Transisi geser

Cuplikan kode ini menunjukkan cara melakukan transisi slide-in dan slide-out menggunakan metode helper dari DefaultContentTransitions. Anda juga dapat menentukan objek SlideInTransition dan SlideOutTransition kustom dengan memanggil setSlideIn() dan setSlideOut() untuk masing-masing, di metode penyetel transisi.

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

Menampilkan transformasi

Untuk menarik perhatian ke elemen atau area tertentu dalam kartu, Anda dapat menerapkan beberapa jenis transformasi ke elemen atau area tersebut, termasuk: rotasi, penskalaan, dan translasi.

Banyak nilai floating point yang terkait dengan transformasi menerima ekspresi dinamis, yang memungkinkan Anda menganimasikan transformasi ini.

Rotasi

Untuk melakukan rotasi searah jarum jam di sekitar titik pivot yang dapat disesuaikan, gunakan kode yang mirip dengan berikut ini:

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

Pengaturan Skala

Untuk memperbesar atau memperkecil elemen dengan faktor penskalaan horizontal dan vertikal, gunakan kode yang mirip dengan berikut ini:

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

Terjemahan geometris

Untuk memindahkan elemen dengan jumlah piksel kepadatan (dp) tertentu di layar secara horizontal atau vertikal, gunakan kode yang mirip dengan berikut ini:

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

Animasi Lottie

Kartu mendukung pemutaran animasi Lottie, menggunakan sintaksis yang mirip dengan gambar:

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

Beberapa hal yang perlu diperhatikan:

  • Hanya sebagian kecil file Lottie yang didukung. Periksa kompatibilitas menggunakan salah satu validator berikut:
  • Pemutaran Lottie didukung oleh perender petak dengan versi utama minimal 1 dan versi minor minimal 500. Jika animasi tertentu tidak didukung, animasi tidak akan muncul, tetapi bagian ubin lainnya akan dirender seperti yang diharapkan. Jika perlu, Anda dapat memberikan opsi penggantian, seperti gambar statis.

Jangan tampilkan informasi penting di tengah animasi

Ada beberapa situasi ketika animasi dinonaktifkan:

  • Render kartu sistem mungkin menonaktifkan animasi untuk semua kartu.
  • Kartu hanya dapat menganimasikan 4 elemen sekaligus. Jika Anda mencoba menganimasikan lebih dari 4 elemen secara bersamaan, tidak semuanya akan menampilkan animasi.

Jika animasi dinonaktifkan, elemen akan bersifat statis dan menampilkan nilai akhir animasi. Oleh karena itu, jangan mengandalkan perilaku animasi, misal durasinya, untuk menampilkan informasi penting.