MotionLayout
é um tipo de layout que ajuda a gerenciar movimento e animação de widgets no seu app.
O MotionLayout
é uma subclasse de
ConstraintLayout
e aproveita os recursos avançados
de layout. Como parte da biblioteca ConstraintLayout
, MotionLayout
está disponível como uma biblioteca de suporte.
O MotionLayout
preenche a lacuna entre as transições de layout e o processamento
complexo de movimentos, oferecendo uma combinação de recursos entre o framework de animação
de propriedade,
TransitionManager
e
CoordinatorLayout
.
Além de descrever transições entre layouts, o MotionLayout
permite
animar qualquer propriedade de layout. Além disso, ele oferece suporte inerente a transições
pesquisáveis. Isso significa que você pode mostrar instantaneamente qualquer ponto dentro da transição
com base em alguma condição, por exemplo, a entrada por toque. O MotionLayout
também é compatível com
frames-chave, permitindo transições totalmente personalizadas para atender às suas necessidades.
MotionLayout
é totalmente declarativo, o que significa que você pode descrever qualquer transição em
XML, não importa a complexidade.
Considerações sobre o design
O MotionLayout
destina-se a mover, redimensionar e animar elementos de IU com que
os usuários interagem, como botões e barras de título. Não use movimento no app como
um efeito especial desnecessário. Use-o para ajudar os usuários a entender o que o app está
fazendo. Para saber mais sobre como projetar seu app com movimento, consulte a
seção do Material Design Como entender
o movimento.
Primeiros passos
Siga estas etapas para começar a usar o MotionLayout
no seu projeto.
-
Adicione a dependência
ConstraintLayout
:para usarMotionLayout
no projeto, adicione a dependênciaConstraintLayout
2.0 ao arquivobuild.gradle
do app. Se você estiver usando o AndroidX, adicione a seguinte dependência:Groovy
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.0-beta01" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-beta01" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.0-beta01") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-beta01") }
-
Crie um arquivo
MotionLayout
:MotionLayout
é uma subclasse deConstraintLayout
, então você pode transformar qualquerConstraintLayout
existente em umMotionLayout
, substituindo o nome da classe no seu arquivo de recurso de layout, conforme mostrado nos exemplos a seguir:AndroidX
<!-- before: ConstraintLayout --> <androidx.constraintlayout.widget.ConstraintLayout .../> <!-- after: MotionLayout --> <androidx.constraintlayout.motion.widget.MotionLayout .../>
Biblioteca de Suporte
<!-- before: ConstraintLayout --> <android.support.constraint.ConstraintLayout .../> <!-- after: MotionLayout --> <android.support.constraint.motion.MotionLayout .../>
Confira um exemplo completo de um arquivo
MotionLayout
, que define o layout mostrado na Figura 1:AndroidX
<?xml version="1.0" encoding="utf-8"?> <!-- activity_main.xml --> <androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/motionLayout" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutDescription="@xml/scene_01" tools:showPaths="true"> <View android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:background="@color/colorAccent" android:text="Button" /> </androidx.constraintlayout.motion.widget.MotionLayout>
Biblioteca de Suporte
<?xml version="1.0" encoding="utf-8"?> <!-- activity_main.xml --> <android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/motionLayout" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutDescription="@xml/scene_01" tools:showPaths="true"> <View android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:background="@color/colorAccent" android:text="Button" /> </android.support.constraint.motion.MotionLayout>
-
Criar um MotionScene:no exemplo anterior de
MotionLayout
, o atributoapp:layoutDescription
faz referência a um MotionScene. Uma cena em movimento é um arquivo de recurso XML. No elemento raiz<MotionScene>
, uma cena de movimento contém todas as descrições de movimento para o layout correspondente. Para manter as informações de layout separadas das descrições de movimento, cadaMotionLayout
faz referência a uma cena de movimento separada. As definições na cena de movimento têm precedência sobre definições semelhantes noMotionLayout
.Confira um exemplo de arquivo de cena em movimento que descreve o movimento horizontal básico na Figura 1:
<?xml version="1.0" encoding="utf-8"?> <MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto"> <Transition motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000"> <OnSwipe motion:touchAnchorId="@+id/button" motion:touchAnchorSide="right" motion:dragDirection="dragRight" /> </Transition> <ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent" /> </ConstraintSet> </MotionScene>
Observe o seguinte:
-
<Transition>
contém a definição básica do movimento.-
motion:constraintSetStart
emotion:constraintSetEnd
são referências aos endpoints da movimentação. Esses endpoints são definidos nos elementos<ConstraintSet>
mais tarde na cena de movimento. -
motion:duration
especifica o número de milissegundos necessários para que a animação seja concluída.
-
-
<OnSwipe>
permite criar um controle por toque para o movimento.-
motion:touchAnchorId
se refere à visualização que o usuário pode deslizar e arrastar. -
motion:touchAnchorSide
significa que a visualização está sendo arrastada do lado direito. -
motion:dragDirection
se refere à direção do avanço da ação de arrastar. Por exemplo,motion:dragDirection="dragRight"
significa que o progresso aumenta conforme a visualização é arrastada para a direita.
-
-
<ConstraintSet>
é onde você define as várias restrições que descrevem seu movimento. Neste exemplo, um<ConstraintSet>
é definido para cada endpoint do movimento. Esses endpoints são centralizados verticalmente usandoapp:layout_constraintTop_toTopOf="parent"
eapp:layout_constraintBottom_toBottomOf="parent"
. Horizontalmente, os endpoints estão nas extremidades esquerda e direita da tela.
Para ter uma visão mais detalhada dos diversos elementos compatíveis com uma cena de movimento, consulte os Exemplos do MotionLayout.
-
Atributos interpolados
Em um arquivo de cena em movimento, os elementos ConstraintSet
podem conter outros
atributos que são interpolados durante a transição. Além da posição e dos limites, os seguintes atributos são interpolados pelo MotionLayout
:
alpha
visibility
elevation
rotation
,rotationX
,rotationY
translationX
,translationY
,translationZ
scaleX
,scaleY
Atributos personalizados
Em um <Constraint>
, você pode usar o elemento <CustomAttribute>
para especificar
uma transição para atributos que não estão simplesmente relacionados à posição ou aos atributos
View
.
<Constraint android:id="@+id/button" ...> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60"/> </Constraint>
Um <CustomAttribute>
contém dois atributos próprios:
motion:attributeName
: é obrigatório e precisa corresponder a um objeto com métodos getter e setter. O getter e o setter precisam corresponder a um padrão específico. Por exemplo,backgroundColor
é compatível, porque a visualização tem os métodosgetBackgroundColor()
esetBackgroundColor()
.- O outro atributo que você precisa fornecer é baseado no tipo de valor. Escolha um
dos seguintes tipos compatíveis:
motion:customColorValue
para coresmotion:customIntegerValue
para números inteirosmotion:customFloatValue
para flutuantesmotion:customStringValue
para stringsmotion:customDimension
para dimensõesmotion:customBoolean
para booleanos
Ao especificar um atributo personalizado, defina valores de endpoint nos elementos inicial e
final do <ConstraintSet>
.
Mudar cor do plano de fundo
Com base no exemplo anterior, suponha que você queira que as cores da visualização mudem como parte do movimento, conforme mostrado na Figura 2.
Adicione um elemento <CustomAttribute>
a cada elemento ConstraintSet
, conforme mostrado no
sequência de comandos abaixo:
<ConstraintSet android:id="@+id/start"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60" /> </Constraint> </ConstraintSet> <ConstraintSet android:id="@+id/end"> <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent"> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#9999FF" /> </Constraint> </ConstraintSet>
Atributos adicionais do MotionLayout
Além dos atributos no exemplo anterior, o MotionLayout
tem outros
atributos que você pode especificar:
app:applyMotionScene="boolean"
: indica se a cena de movimento será aplicada. O valor padrão para este atributo étrue
.app:showPaths="boolean"
indica se as trajetórias de animação serão mostradas enquanto o movimento está em execução. O valor padrão para este atributo éfalse
.app:progress="float"
: permite que você especifique explicitamente o andamento da transição. Você pode usar qualquer valor de ponto flutuante de0
(o início da transição) a1
(o final da transição).app:currentState="reference"
: permite que você especifique umConstraintSet
.app:motionDebug
: permite exibir informações de depuração adicionais sobre o movimento. Os valores possíveis são"SHOW_PROGRESS"
,"SHOW_PATH"
ou"SHOW_ALL"
.
Outros recursos
Para mais informações sobre MotionLayout
, consulte os seguintes recursos:
- Android avançado no Kotlin 03.2: animação com o MotionLayout
- Exemplos do MotionLayout
- Exemplos do MotionLayout/ConstraintLayout no GitHub
- Introdução ao MotionLayout (parte I)
- Introdução ao MotionLayout (parte II)
- Introdução ao MotionLayout (parte III)
- Introdução ao MotionLayout (parte IV) (em inglês)