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.
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 |
|
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 |
|
15 |
|
16 |
|
17 |
|
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
, jumpToEnd
e 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.
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.
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 TransitionListener
o 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.
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.