Carousel dengan MotionLayout

Carousel adalah objek helper gerakan untuk membuat tampilan carousel kustom yang menampilkan daftar elemen yang dapat dibaca pengguna secara sekilas. Dibandingkan dengan cara lain untuk mengimplementasikan tampilan tersebut, helper ini memungkinkan Anda membuat perubahan gerakan dan dimensi yang kompleks untuk Carousel dengan cepat dengan memanfaatkan MotionLayout.

Widget Carousel mendukung daftar dengan awal dan akhir serta daftar menyeluruh.

Cara kerja Carousel dengan MotionLayout

Misalnya Anda ingin membuat tampilan Carousel horizontal, dengan item tengah diperbesar:

Tata letak dasar ini berisi beberapa tampilan yang mewakili item Carousel:

Buat MotionLayout dengan tiga status berikut dan berikan ID:

  • sebelumnya
  • mulai
  • berikutnya

Jika status start sesuai dengan tata letak dasar, dalam status sebelumnya dan status next, item Carousel digeser oleh satu ke kiri dan ke kanan.

Misalnya, ambil lima tampilan pada gambar 3 dan asumsikan bahwa pada status awal, tampilan B, C, dan D terlihat, serta A dan E berada di luar layar. Siapkan status sebelumnya sehingga posisi A, B, C, dan D berada di tempat B, C, D, dan E berada, dengan tampilan bergerak dari kiri ke kanan. Pada status berikutnya, hal yang sebaliknya perlu terjadi, dengan B, C, D, dan E bergerak ke tempat A, B, C, dan D berada, dan tampilan bergerak dari kanan ke kiri. Hal ini ditunjukkan dalam gambar 4:

Penayangan harus berakhir persis di tempat penayangan asli dimulai. Carousel memberikan ilusi tentang kumpulan elemen yang tak terbatas dengan memindahkan tampilan sebenarnya kembali ke tempat sebelumnya, tetapi melakukan inisialisasi ulang dengan konten baru yang sesuai. Diagram berikut menunjukkan mekanisme ini. Perhatikan nilai "item #"):

Transisi

Setelah tiga kumpulan batasan ini ditentukan dalam file scene gerakan, buat dua transisi—maju dan mundur—antara status start dan next serta status start dan previous. Tambahkan pengendali OnSwipe untuk memicu transisi sebagai respons terhadap gestur, seperti yang ditunjukkan pada contoh berikut:

    <Transition
        motion:constraintSetStart="@id/start"
        motion:constraintSetEnd="@+id/next"
        motion:duration="1000"
        android:id="@+id/forward">
        <OnSwipe
            motion:dragDirection="dragLeft"
            motion:touchAnchorSide="left" />
    </Transition>

    <Transition
        motion:constraintSetStart="@+id/start"
        motion:constraintSetEnd="@+id/previous"
        android:id="@+id/backward">
        <OnSwipe
            motion:dragDirection="dragRight"
            motion:touchAnchorSide="right" />
    </Transition>

Setelah scene gerakan dasar ini dibuat, tambahkan helper Carousel ke tata letak dan rujuk tampilan dalam urutan yang sama dengan saat Anda menerapkan animasi sebelumnya dan berikutnya.

Tetapkan atribut berikut untuk helper Carousel:

  • app:carousel_firstView: tampilan yang mewakili elemen pertama Carousel—dalam contoh ini, C.
  • app:carousel_previousState: ID ConstraintSet dari status sebelumnya.
  • app:carousel_nextState: ID ConstraintSet dari status berikutnya.
  • app:carousel_backwardTransition: ID Transition yang diterapkan di antara status awal dan sebelumnya.
  • app:carousel_forwardTransition: ID Transition yang diterapkan di antara status start dan next.

Misalnya, Anda memiliki sesuatu seperti ini dalam file XML tata letak Anda:

    <androidx.constraintlayout.motion.widget.MotionLayout ... >

        <ImageView  android:id="@+id/imageView0" .. />
        <ImageView  android:id="@+id/imageView1" .. />
        <ImageView  android:id="@+id/imageView2" .. />
        <ImageView  android:id="@+id/imageView3" .. />
        <ImageView  android:id="@+id/imageView4" .. />

        <androidx.constraintlayout.helper.widget.Carousel
            android:id="@+id/carousel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:carousel_forwardTransition="@+id/forward"
            app:carousel_backwardTransition="@+id/backward"
            app:carousel_previousState="@+id/previous"
            app:carousel_nextState="@+id/next"
            app:carousel_infinite="true"
            app:carousel_firstView="@+id/imageView2"
            app:constraint_referenced_ids="imageView0,imageView1,imageView2,imageView3,imageView4" />

    </androidx.constraintlayout.motion.widget.MotionLayout>

Siapkan adaptor Carousel dalam kode:

Kotlin

carousel.setAdapter(object : Carousel.Adapter {
            override fun count(): Int {
              // Return the number of items in the Carousel.
            }

            override fun populate(view: View, index: Int) {
                // Implement this to populate the view at the given index.
            }

            override fun onNewItem(index: Int) {
                // Called when an item is set.
            }
        })

Java

carousel.setAdapter(new Carousel.Adapter() {
            @Override
            public int count() {
                // Return the number of items in the Carousel.
            }

            @Override
            public void populate(View view, int index) {
                // Populate the view at the given index.
            }

            @Override
            public void onNewItem(int index) {
                 // Called when an item is set.
            }
        });

Catatan tambahan

Bergantung pada item saat ini yang "selected" di Carousel, tampilan yang mewakili item sebelum atau sesudah mungkin perlu disembunyikan agar dapat memperhitungkan Carousel dengan benar start dan end. Helper Carousel menangani hal ini secara otomatis. Secara default, tindakan ini akan menandai tampilan tersebut sebagai View.INVISIBLE dalam situasi ini, sehingga tata letak keseluruhan tidak berubah.

Mode alternatif tersedia, yang memungkinkan helper Carousel menandai tampilan tersebut sebagai View.GONE. Anda dapat menyetel mode ini menggunakan properti berikut:

app:carousel_emptyViewsBehavior="gone"

Contoh

Untuk contoh lain penggunaan helper Carousel, lihat project contoh di GitHub.