Carrossel com MotionLayout

Carousel é um objeto auxiliar de movimento para criar visualizações de carrossel personalizadas que mostram uma lista de elementos que o usuário possa ler. Em comparação com outras formas de implementar essa visualizações, esse assistente permite criar rapidamente mudanças complexas de movimento e dimensão para seu Carousel, aproveitando as MotionLayout.

O widget Carousel oferece suporte a listas com início e fim, bem como listas circundantes.

Como o Carrossel com MotionLayout funciona

Suponha que você queira criar uma visualização horizontal de Carousel, com o item central ampliada:

Esse layout básico contém várias visualizações que representam os itens Carousel:

Crie uma MotionLayout com os três estados abaixo e atribua IDs a eles:

  • anterior
  • iniciar
  • próxima

Se o estado start corresponder ao layout básico, no estado anterior No próximo estado, os itens Carousel são deslocados em um para a esquerda e respectivamente para a direita.

Por exemplo, considere as cinco visualizações da Figura 3 e suponha que no elemento start estado, as visualizações B, C e D ficam visíveis e A e E estão fora da tela. Definir para cima no estado anterior para que as posições de A, B, C e D sejam onde B, C, D e E eram, com as visualizações se movendo da esquerda para a direita. Na próxima o oposto precisa acontecer, com B, C, D e E indo para onde A, B, C e D foram, e as visualizações se moveram da direita para a esquerda. Isso é mostrado na figura 4.

É fundamental que as visualizações terminem exatamente onde as visualizações originais começam. Carousel proporciona a ilusão de uma coleção infinita de elementos, movendo as visualizações reais de volta para onde estavam, mas reiniciando-as com o novo conteúdo correspondente. O diagrama a seguir mostra esse mecanismo. Pagar atenção ao "item #" de valor):

Transições

Com esses três conjuntos de restrições definidos no arquivo de cena em movimento, crie dois transições entre o start e o next, para frente e para trás e os estados start e previous. Adicione um Gerenciador OnSwipe para acionarão as transições em resposta a um gesto, conforme mostrado abaixo exemplo:

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

Depois que essa cena em movimento básica for criada, adicione um auxiliar Carousel ao layout. e faça referência às visualizações na mesma ordem em que você implementa as visualizações animação.

Defina os seguintes atributos para o auxiliar Carousel:

  • app:carousel_firstView: a visualização que representa o primeiro elemento do Carousel. Neste exemplo, C.
  • app:carousel_previousState: o ID de ConstraintSet do anterior estado.
  • app:carousel_nextState: o ID de ConstraintSet do próximo estado.
  • app:carousel_backwardTransition: o Transition ID aplicado entre os estados início e anterior.
  • app:carousel_forwardTransition: o ID de Transition aplicado entre as start e next.

Por exemplo, seu arquivo XML de layout tem algo assim:

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

Configure um adaptador da Carousel no código:

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

Outras observações

Dependendo do item atual "selecionado" no Carousel, as visualizações que representam os itens antes ou depois podem precisar ser ocultados para conta para Carousel start e end. O auxiliar Carousel processa isso automaticamente. Por padrão, ele marca essas visualizações como View.INVISIBLE em nessas situações, para que o layout geral não mude.

Um modo alternativo está disponível em que o auxiliar Carousel marca essas visualizações como View.GONE. É possível definir esse modo usando a seguinte propriedade:

app:carousel_emptyViewsBehavior="gone"

Exemplos

Para mais exemplos usando o assistente de carrossel, consulte a exemplos de projetos no GitHub.