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:

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