Karuzela z ruchem

Carousel to obiekt pomocniczy ruchu służący do tworzenia niestandardowych widoków karuzeli pokazujących listę elementów, które użytkownik może przejrzeć. W porównaniu z innymi sposobami implementacji takich widoków ten moduł pomocniczy umożliwia szybkie wprowadzanie złożonych zmian ruchu i wymiarów w elemencie Carousel przy użyciu funkcji MotionLayout.

Widżet Carousel obsługuje listy z początkiem i końcem oraz listy z zawijaniem kołowym.

Jak działa karuzela z funkcją Motion Layout

Załóżmy, że chcesz utworzyć widok Carousel w poziomie z powiększonym środkowym elementem:

Ten podstawowy układ zawiera kilka widoków reprezentujących elementy Carousel:

Utwórz obiekt MotionLayout z 3 stanami i nadaj mu identyfikatory:

  • poprzednia
  • start
  • dalej

Jeśli stan start odpowiada układowi podstawowemu, w stanach poprzedni i next elementy Carousel są przesuwane odpowiednio w lewo i w prawo.

Weźmy na przykład 5 widoków z rysunku 3 i załóżmy, że w stanie start widać widoki B, C i D, a punkty A i E są poza ekranem. Skonfiguruj stan poprzedniego tak, aby pozycje A, B, C i D znajdowały się tam, gdzie znajdowały się B, C, D i E, przy przesuwaniu widoków od lewej do prawej. W stanie następnym musi wystąpić odwrotna sytuacja: punkty B, C, D i E muszą przechodzić do miejsc, w których znajdowały się A, B, C i D, a widoki przenoszą się od prawej do lewej. Widać to na ilustracji 4:

Ważne jest, aby wyświetlenia kończyły się dokładnie tam, gdzie zaczęły się oryginalne wyświetlenia. Funkcja Carousel daje wrażenie nieskończonego zbioru elementów, przenosząc rzeczywiste widoki z powrotem na miejsce, ale inicjując je z nowymi, pasującymi treściami. Poniższy diagram przedstawia ten mechanizm. Zwróć uwagę na wartości atrybutu „numer produktu”):

Przejścia

Po zdefiniowaniu tych 3 zestawów ograniczeń w pliku sceny ruchu utwórz dwa przejścia (w przód i w tył) między stanem start i next oraz start i poprzedni. Dodaj moduł obsługi OnSwipe, aby uruchamiać przejścia w odpowiedzi na gest, jak w tym przykładzie:

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

Po utworzeniu tej podstawowej sceny ruchu dodaj do układu pomocnika Carousel i odwołuj się do widoków w tej samej kolejności, w której implementujesz poprzednią i następną animację.

Ustaw te atrybuty pomocnika Carousel:

  • app:carousel_firstView: widok reprezentujący pierwszy element właściwości Carousel – w tym przykładzie jest to widok C.
  • app:carousel_previousState: identyfikator ConstraintSet poprzedniego stanu.
  • app:carousel_nextState: identyfikator ConstraintSet stanu następnego.
  • app:carousel_backwardTransition: identyfikator Transition stosowany między stanami start i poprzedni.
  • app:carousel_forwardTransition: identyfikator Transition stosowany między stanem start i next.

Na przykład w pliku XML układu mamy coś takiego:

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

Skonfiguruj adapter Carousel w kodzie:

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.
            }
        });

Uwagi dodatkowe

W zależności od tego, który element jest „wybrany” w Carousel, widoki przedstawiające elementy przed lub po nim mogą być ukryte, aby prawidłowo uwzględniać rozpoczęcie i koniec elementu Carousel. Asystent Carousel zajmuje się tym automatycznie. W takich sytuacjach domyślnie oznacza je jako View.INVISIBLE, więc ogólny układ się nie zmienia.

Dostępny jest tryb alternatywny, w którym pomocnik Carousel oznacza te widoki jako View.GONE. Ten tryb możesz ustawić za pomocą tej właściwości:

app:carousel_emptyViewsBehavior="gone"

Przykłady

Więcej przykładów z użyciem narzędzia pomocniczego karuzeli znajdziesz w przykładowych projektach na GitHubie.