Menambahkan dukungan untuk animasi kembali prediktif di Tampilan

Anda dapat membuat animasi dan transisi properti kustom dalam aplikasi, animasi lintas aktivitas kustom, dan animasi lintas fragmen kustom dengan gestur kembali prediktif menggunakan Tampilan atau Compose. Untuk mencoba cara Compose, lihat Menambahkan dukungan untuk animasi kembali prediktif.

Menambahkan transisi kustom menggunakan Progress API

Dengan AndroidX Activity 1.8.0-alpha01 atau yang lebih baru, Anda dapat menggunakan Predictive Back Progress API untuk mengembangkan animasi kustom bagi gestur kembali prediktif di aplikasi Anda. Progress API berguna dalam menganimasikan tampilan, tetapi memiliki batasan saat menganimasikan transisi antar-fragmen. Dalam OnBackPressedCallback, kami telah memperkenalkan metode handleOnBackProgressed, handleOnBackCancelled , dan handleOnBackStarted untuk menganimasikan objek saat pengguna menggeser kembali. Gunakan metode ini jika Anda perlu menyesuaikan lebih dari animasi default yang disediakan oleh sistem, atau animasi Komponen Material.

Kami memperkirakan sebagian besar aplikasi akan menggunakan AndroidX API yang kompatibel dengan versi lama, tetapi ada juga API platform serupa dalam antarmuka OnBackAnimationCallback yang tersedia untuk diuji di Android 14 dan yang lebih tinggi.

Menggunakan Progress API dengan AndroidX Transitions

Progress API dapat digunakan dengan AndroidX Transitions 1.5.0-alpha01 atau yang lebih baru di Android 14 dan yang lebih baru untuk membuat transisi Kembali Prediktif.

  1. Gunakan TransitionManager#controlDelayedTransition, bukan beginDelayedTransition, untuk memutar transisi saat pengguna menggeser kembali.
  2. Buat transisi dalam handleOnBackStarted.
  3. Putar transisi dengan peristiwa kembali dalam handleOnBackProgressed dengan menghubungkan currentFraction ke BackEvent.progress yang memperlihatkan seberapa jauh pengguna telah menggeser kembali.
  4. Selesaikan transisi setelah pengguna melakukan gestur kembali di handleOnBackPressed.
  5. Terakhir, reset status transisi dalam handleOnBackCancelled.

Video, kode Kotlin, dan XML berikut menunjukkan transisi kustom antara dua kotak yang diterapkan dengan OnBackPressedCallback:

    class MyFragment : Fragment() {

    val transitionSet = TransitionSet().apply {
        addTransition(Fade(Fade.MODE_OUT))
        addTransition(ChangeBounds())
        addTransition(Fade(Fade.MODE_IN))
    }
    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val callback = object : OnBackPressedCallback(enabled = false) {

            var controller: TransitionSeekController? = null

            @RequiresApi(34)
            override fun handleOnBackStarted(backEvent: BackEvent) {
                // Create the transition
                controller = TransitionManager.controlDelayedTransition(
                    binding.card,
                    transitionSet
                )
                changeTextVisibility(ShowText.SHORT)
            }

            @RequiresApi(34)
            override fun handleOnBackProgressed(backEvent: BackEvent) {
                // Play the transition as the user swipes back
                if (controller?.isReady == true) {
                    controller?.currentFraction = backEvent.progress
                }
            }

            override fun handleOnBackPressed() {
                // Finish playing the transition when the user commits back
                controller?.animateToEnd()
                this.isEnabled = false
            }

            @RequiresApi(34)
            override fun handleOnBackCancelled() {
                // If the user cancels the back gesture, reset the state
                transition(ShowText.LONG)
            }
        }

        binding.shortText.setOnClickListener {
            transition(ShowText.LONG)
            callback.isEnabled = true
        }

        this.requireActivity().onBackPressedDispatcher.addCallback(callback)
    }

    private fun transition(showText: ShowText) {
        TransitionManager.beginDelayedTransition(
            binding.card,
            transitionSet
        )
        changeTextVisibility(showText)
    }

    enum class ShowText { SHORT, LONG }
    private fun changeTextVisibility(showText: ShowText) {
        when (showText) {
            ShowText.SHORT -> {
                binding.shortText.isVisible = true
                binding.longText.isVisible = false
            }
            ShowText.LONG -> {
                binding.shortText.isVisible = false
                binding.longText.isVisible = true
            }
        }
    }
}
  
<?xml version="1.0" encoding="utf-8"?>
...
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/card"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        ...>

        <TextView
            android:id="@+id/short_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            ... />

        <TextView
            android:id="@+id/long_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone"
            .../>

    </androidx.constraintlayout.widget.ConstraintLayout>

Saat menangani transisi Kembali Prediktif, perhatikan hal berikut:

  • Gunakan isSeekingSupported untuk memeriksa apakah transisi mendukung Kembali Prediktif.
  • Ganti isSeekingSupported agar menampilkan true (benar) untuk transisi kustom Anda.
  • Buat satu pengontrol per animasi.
  • Transisi Kembali Prediktif didukung dengan transisi AndroidX, tetapi tidak dengan transisi framework. Lakukan migrasi dari transisi framework dan gunakan transisi Animator dan AndroidX sebagai gantinya.
  • Transisi Kembali Prediktif didukung di perangkat yang menjalankan Android 14 dan yang lebih baru serta tidak kompatibel dengan versi sebelumnya.
  • Transisi yang dibuat dengan scene XML juga didukung. Di handleOnBackStarted, setel TransitionSeekController ke hasil TransitionManager.createSeekController, bukan hasil controlDelayedTransition.

Referensi Tambahan