Criando animações com MotionLayout para Android

Animar diferentes widgets em seu aplicativo Android sempre foi uma experiência dolorosa para os desenvolvedores. No entanto, tudo isso mudou com a introdução do MotionLayout subclasse no Android.

Você pode usar MotionLayout em seu aplicativo para lidar com animações de widget de um estado para outro. MotionLayout foi adicionado como uma subclasse do ConstraintLayout classe na versão 2.0. Suporte para MotionLayout remonta ao nível 14 da API com a ajuda de uma biblioteca de suporte compatível com versões anteriores.

Alguns recursos úteis e interessantes da classe incluem animação de diferentes propriedades de layout, bem como suporte para transições pesquisáveis. O suporte para quadros-chave em MotionLayout é simplesmente cereja no topo. Isso permite que você crie suas próprias transições totalmente personalizadas.

Neste tutorial, você aprenderá como criar animações em seu aplicativo Android usando MotionLayout.

Adicionar dependências

O primeiro passo antes de começar a usar MotionLayout em seu aplicativo Android envolve adicionar ConstraintLayout como uma dependência do seu projeto. Isso está incluído por padrão em todos os projetos Android agora. No entanto, você ainda deve certificar-se de que qualquer projeto que use MotionLayout usa uma versão acima de 2.0.0 para o ConstraintLayout como sua dependência.

Você pode verificar suas próprias dependências de projeto abrindo o build.gradle arquivo e procurando por esta linha em dependencies.

1
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

O número da versão no final mudará de tempos em tempos. Então, não se preocupe com uma incompatibilidade. O importante a lembrar é que deve ser pelo menos 2.0.0.

Definir o layout do aplicativo

Se você estiver criando um novo aplicativo enquanto segue este tutorial, verá que o activity_main.xml arquivo está usando ConstraintLayout para posicionamento do widget. Teremos que substituir todas as instâncias de ConstraintLayout em nosso arquivo de layout com MotionLayout.

A maneira mais fácil de fazer isso é mudar seu layout de Código ver para qualquer um Dividir ou Projeto Visualizar. você vai encontrar um Árvore de Componentes painel do lado esquerdo. Abra o painel e você verá o ConstraintLayout em uso. Clique com o botão direito sobre ele e selecione Converter para MotionLayout como mostrado na imagem abaixo.

Convertendo ConstraintLayout para MotionLayoutConvertendo ConstraintLayout para MotionLayoutConvertendo ConstraintLayout para MotionLayout

Isso resultará em uma nova janela pop-up informando que a conversão para MotionLayout resultará na criação de um separado MotionScene arquivo. Clique no Converter botão.

Seu activity_main.xml arquivo agora deve ter o seguinte código XML:

1

2
 xmlns:android="https://schemas.android.com/apk/res/android"
3
    xmlns:app="http://schemas.android.com/apk/res-auto"
4
    xmlns:tools="http://schemas.android.com/tools"
5
    android:layout_width="match_parent"
6
    android:layout_height="match_parent"
7
    app:layoutDescription="@xml/activity_main_scene"
8
    tools:context=".MainActivity">
9

10
    
11
        android:id="@+id/textView"
12
        android:layout_width="wrap_content"
13
        android:layout_height="wrap_content"
14
        android:text="Hello World!"
15
        app:layout_constraintBottom_toBottomOf="parent"
16
        app:layout_constraintEnd_toEndOf="parent"
17
        app:layout_constraintStart_toStartOf="parent"
18
        app:layout_constraintTop_toTopOf="parent" />
19

20

Vamos adicionar um Button widget ao nosso layout. Vamos projetar nosso aplicativo de forma que um clique no botão fará com que nosso TextView widget salta um pouco e aumenta de tamanho. Adicione o seguinte XML abaixo do TextView widget para adicionar um botão que diz Pular e fica 20sp abaixo do nosso TextView ferramenta.

1

2
    android:id="@+id/button"
3
    android:layout_width="wrap_content"
4
    android:layout_height="wrap_content"
5
    android:text="Jump"
6
    android:textSize="18sp"
7
    android:layout_marginTop="20sp"
8
    app:layout_constraintEnd_toEndOf="parent"
9
    app:layout_constraintStart_toStartOf="parent"
10
    app:layout_constraintTop_toBottomOf="@id/textView" />

Editando o arquivo MotionScene

Você se lembra que o Android Studio nos mostrou uma janela pop-up que mencionava que a conversão do nosso ConstraintLayout para MotionLayout resultará na criação de um MotionScene arquivo? O nome disso MotionScene arquivo é activity_main_scene.xml. Você pode encontrá-lo sob res > xml > activity_main_scene.xml no seu projecto.

Uma referência ao arquivo de cena de movimento também está presente em nosso activity_main.xml arquivo sob o app:layoutDescription atributo. O activity_main_scene.xml arquivo contém o seguinte código:

1

2
 
3
    xmlns:android="http://schemas.android.com/apk/res/android"
4
    xmlns:motion="http://schemas.android.com/apk/res-auto">
5

6
    
7
        motion:constraintSetEnd="@+id/end"
8
        motion:constraintSetStart="@id/start"
9
        motion:duration="1000">
10
       
11
       
12
    
13

14
     android:id="@+id/start">
15
    
16

17
     android:id="@+id/end">
18
    
19

Como você pode ver, o arquivo de cena contém uma raiz MotionScene tag com outras tags dentro dela que controlam o movimento real ou a animação de um widget.

O Transition etiqueta dentro MotionScene define como a animação irá prosseguir com base em seu início e fim ConstraintSets. Cada ConstrainSet pode conter um Constraint tag que você pode usar para fornecer restrição e visualizar valores de atributos específicos.

Há três coisas que queremos mudar em nosso TextView a cada clique do botão. A cor do texto deve mudar de preto para teal_700. Esses valores são definidos no cores.xml arquivo. O espaçamento entre o TextView widget e o Button deve aumentar para 40sp. O TextView widget deve ser dimensionado para o dobro do tamanho original.

Aqui está o XML que podemos usar dentro do nosso MotionScene arquivo para fazer nosso textView nervoso.

1

2
 
3
    xmlns:android="http://schemas.android.com/apk/res/android"
4
    xmlns:motion="http://schemas.android.com/apk/res-auto">
5

6
    
7
        motion:constraintSetEnd="@+id/end"
8
        motion:constraintSetStart="@id/start"
9
        motion:duration="200"
10
        motion:motionInterpolator="easeIn">
11
        
12
            motion:targetId="@id/button"
13
            motion:clickAction="transitionToEnd" />
14
    
15

16
    
17
        android:id="@+id/start">
18
        
19
            android:id="@id/textView">
20
            
21
                motion:attributeName="textColor"
22
                motion:customColorValue="@color/black" />
23
        
24
    
25

26
    
27
        android:id="@+id/end">
28
        
29
            android:id="@id/textView"
30
            android:scaleX="2"
31
            android:scaleY="2">
32
            
33
                android:layout_marginBottom="40sp"
34
                android:layout_width="wrap_content"
35
                android:layout_height="wrap_content"
36
                motion:layout_constraintBottom_toTopOf="@id/button" />
37
            
38
                motion:attributeName="textColor"
39
                motion:customColorValue="@color/teal_700" />
40
        
41
    
42

Os atributos dentro Transition especifique a duração da animação em milissegundos, bem como o método de interpolação usado para calcular os valores intermediários. Também usamos o opcional OnClick para especificar quando a transição deve ser acionada. O targetId O atributo determina qual visualização acionará a animação. No nosso caso, usamos nosso botão como elemento de gatilho. O clickAction O atributo especifica o que deve acontecer quando o usuário clicar em nosso botão. Neste caso, definimos o seu valor para transitiontoEnd. Outros valores possíveis são toggle, transitionToStart, jumpToEnde jumpToStart.

Depois disso, definimos nosso ConstraintSet tags que determinam a aparência do nosso widget no início e no final da animação. Você também pode considerar o uso do Motion Editor se não preferir escrever todo o XML sozinho. Isso também lhe dará uma boa ideia da aparência do seu layout no início e no final da animação.

Editor de movimentoEditor de movimentoEditor de movimento

Tente executar seu aplicativo no emulador ou em um dispositivo físico agora. Você deve ver o TextView pular, mudar de cor e aumentar de tamanho.

Animação de controle usando XMLAnimação de controle usando XMLAnimação de controle usando XML

Controlando a animação programaticamente

Embora tenha sido possível animar nosso texto simplesmente escrevendo algum XML, você provavelmente gostará de ter mais controle sobre a animação. Executar a animação programaticamente oferece a opção de realizar outras tarefas com base no progresso geral da animação.

Adicione a seguinte linha ao seu Button widget XML para chamar um método chamado start() definido em nosso MainActivity.kt arquivo:

1
android:onClick="start"

Defina um método chamado start() dentro do MainActivity classe logo abaixo onCreate(). Deverá ter o seguinte código:

1
fun start(v: View) {
2
        val motionContainer = findViewById<MotionLayout>(R.id.motion_container)
3
        motionContainer.transitionToEnd();
4
}

Começamos obtendo primeiro uma referência ao nosso MotionLayout. Na próxima linha, usamos o transitionToEnd() método para fazer a transição para a animação dos valores no início ConstraintSet até o final ConstraintSet.

Você pode anexar um ouvinte de transição ao seu MotionLayout widget para monitorar o progresso da animação e lidar com o que acontece em diferentes eventos. O TransitionListener interface tem quatro métodos abstratos. O Android Studio gerará stubs para todos esses métodos para você automaticamente. Seu código abaixo da chamada para transitionToEnd() deve ficar assim agora:

1
val jumpButton = findViewById<Button>(R.id.button)
2
val greeting = findViewById<TextView>(R.id.textView)
3

4
motionContainer.setTransitionListener(
5
    object: MotionLayout.TransitionListener {
6

7
        override fun onTransitionStarted(
8
            motionLayout: MotionLayout?,
9
            startId: Int,
10
            endId: Int
11
        ) {
12
            jumpButton.setBackgroundColor(Color.BLACK);
13
        }
14

15
        override fun onTransitionChange(
16
            motionLayout: MotionLayout?,
17
            startId: Int,
18
            endId: Int,
19
            progress: Float
20
        ) {
21

22
        }
23

24
        override fun onTransitionCompleted(
25
            motionLayout: MotionLayout?,
26
            currentId: Int) {
27
            if(currentId == R.id.end) {
28
                greeting.text = "Good Evening!";
29
            }
30
        }
31

32
        override fun onTransitionTrigger(
33
            motionLayout: MotionLayout?,
34
            triggerId: Int,
35
            positive: Boolean,
36
            progress: Float
37
        ) {
38

39
        }
40
    }
41
)

Começamos obtendo uma referência ao TextView widget e o Button ferramenta.

Dentro de TransitionListenero onTransitionStarted() O método é acionado quando a transição está prestes a começar. Aceita o definido MotionLayout como o primeiro parâmetro. O segundo e o terceiro parâmetros são os IDs dos conjuntos de restrições inicial e final.

Nós chamamos o setBackgroundColor() método no jumpButton para mudar sua cor para preto assim que a transição começar.

O onTransitionCompleted() O método é acionado quando a transição é concluída. Aceita dois parâmetros. A primeira é a referência ao nosso MotionLayout. O segundo é o ID do ConstraintSet atualmente aplicável ao layout.

Nós verificamos se o currentId corresponde ao Id do nosso final ConstraintSet. O texto de saudação muda para Boa noite! se houver uma correspondência. Você também pode fazer outras coisas aqui, como levar a transição de volta ao estado inicial fazendo uma chamada para transitionToStart().

Clicando no Pular botão desta vez irá atualizar o texto e mudar a cor do botão também.

Controlar animação usando códigoControlar animação usando códigoControlar animação usando código

Pensamentos finais

Neste tutorial, você aprendeu como animar diferentes widgets em sua atividade usando MotionLayout. É possível animar layouts usando apenas XML. No entanto, você pode obter controle granular sobre a animação se usar código para fazer a animação. Também permite que você faça outras coisas durante diferentes estágios da animação.

O Android Studio também vem com um Motion Editor que ajuda você a definir rapidamente transições complexas. Você também poderá ver os estágios inicial e final da animação ao usar o Motion Editor.

Deixe uma resposta