Carrousel avec MotionLayout

Essayer Compose
Jetpack Compose est le kit d'outils d'interface utilisateur recommandé pour Android. Découvrez comment ajouter un carrousel dans Compose.

Carousel est un objet d'assistance de mouvement permettant de créer des vues de carrousel personnalisées qui affichent une liste d'éléments que l'utilisateur peut parcourir. Contrairement à d'autres méthodes d'implémentation de ces vues, cet assistant vous permet de créer rapidement des mouvements complexes et des changements de dimension pour votre Carousel en tirant parti de MotionLayout.

Le widget Carousel est compatible avec les listes avec un début et une fin, ainsi qu'avec les listes circulaires.

Fonctionnement de Carousel avec MotionLayout

Supposons que vous souhaitiez créer une vue Carousel horizontale, avec l'élément central agrandi :

Cette mise en page de base contient plusieurs vues représentant les éléments Carousel :

Créez un MotionLayout avec les trois états suivants et attribuez-leur des ID :

  • previous
  • start
  • next

Si l'état start correspond à la mise en page de base, dans l'état previous et l'état next , les éléments Carousel sont décalés d'un élément vers la gauche et vers la droite, respectivement.

Par exemple, prenez les cinq vues de la figure 3 et supposez que dans l'état start , les vues B, C et D sont visibles, et que A et E sont en dehors de l'écran. Configurez l'état previous de sorte que les positions de A, B, C et D soient celles de B, C, D et E, les vues se déplaçant de gauche à droite. Dans l'état next , l'inverse doit se produire, avec B, C, D et E se déplaçant vers les positions de A, B, C et D, et les vues se déplaçant de droite à gauche. Ceci est illustré dans la figure 4 :

Il est essentiel que les vues se terminent exactement là où les vues d'origine commencent. Carousel donne l'illusion d'une collection infinie d'éléments en déplaçant les vues réelles vers leur position d'origine, mais en les réinitialisant avec le nouveau contenu correspondant. Le schéma suivant illustre ce mécanisme. Faites attention aux valeurs "item #" :

Transitions

Avec ces trois ensembles de contraintes définis dans votre fichier de scène de mouvement, créez deux transitions (avant et arrière) entre les états start et next , et entre les états start et previous. Ajoutez un OnSwipe gestionnaire pour déclencher les transitions en réponse à un geste, comme illustré dans l'exemple suivant :

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

Une fois cette scène de mouvement de base créée, ajoutez un assistant Carousel à la mise en page et référencez les vues dans le même ordre que celui dans lequel vous implémentez votre animation précédente et suivante.

Définissez les attributs suivants pour l'assistant Carousel :

  • app:carousel_firstView: la vue qui représente le premier élément du Carousel. Dans cet exemple, il s'agit de C.
  • app:carousel_previousState: l'ID ConstraintSet de l'état previous.
  • app:carousel_nextState : l'ID ConstraintSet de l'état next.
  • app:carousel_backwardTransition: the Transition ID applied between the start and previous states.
  • app:carousel_forwardTransition : l'ID Transition appliqué entre les états start et next.

Par exemple, vous avez quelque chose comme ceci dans votre fichier XML de mise en page :

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

Configurez un adaptateur Carousel dans le code :

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

Remarques supplémentaires

En fonction de l'élément "sélectionné" actuel dans le Carousel, les vues représentant les éléments précédents ou suivants peuvent avoir besoin d'être masquées pour tenir correctement compte du début et de la fin du Carousel. L'assistant Carousel gère cela automatiquement. Par défaut, il marque ces vues comme View.INVISIBLE dans ces situations, de sorte que la mise en page globale ne change pas.

Un autre mode est disponible, dans lequel l'assistant Carousel marque plutôt ces vues comme View.GONE. Vous pouvez définir ce mode à l'aide de la propriété suivante :

app:carousel_emptyViewsBehavior="gone"

Exemples

Pour obtenir d'autres exemples d'utilisation de l'assistant Carousel, consultez les exemples de projets sur GitHub.