O MotionLayout
é um tipo de layout que ajuda a gerenciar movimentos e animações de widget no app.
A MotionLayout
é uma subclasse de
ConstraintLayout
e se baseia nos recursos avançados
de layout. Como parte da biblioteca ConstraintLayout
, MotionLayout
está disponível como uma biblioteca de suporte.
A MotionLayout
preenche a lacuna entre as transições de layout e o processamento de movimentos
complexos, 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 todas as propriedades de layout. Além disso, ele é inerentemente compatível com transições
procuráveis. Isso significa que você pode mostrar instantaneamente qualquer ponto dentro da transição
com base em alguma condição, como a entrada por toque. O MotionLayout
também oferece suporte
a frames-chave, permitindo transições totalmente personalizadas para atender às suas necessidades.
O MotionLayout
é totalmente declarativo, o que significa que você pode descrever qualquer transição em
XML, independente da complexidade.
Considerações sobre design
O método MotionLayout
serve para mover, redimensionar e animar elementos da interface 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 seu app está
fazendo. Para saber mais sobre como projetar seu app com movimento, consulte a
seção Noções básicas sobre
movimento do Material Design.
Primeiros passos
Siga estas etapas para começar a usar o MotionLayout
no seu projeto.
-
Adicione a dependência
ConstraintLayout
: para usarMotionLayout
no seu projeto, adicione a dependênciaConstraintLayout
2.0 ao arquivobuild.gradle
do seu app. Se você estiver usando o AndroidX, adicione a dependência abaixo:Groovy
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha13" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha13") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13") }
-
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 .../>
Veja 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>
-
Crie um MotionScene: no exemplo de
MotionLayout
anterior, o atributoapp:layoutDescription
faz referência a uma cena de movimento. Uma cena em movimento é um arquivo de recurso XML. Dentro do 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 em movimento têm precedência sobre qualquer definição semelhante noMotionLayout
.Veja um exemplo de arquivo de cena de movimento que descreve o movimento horizontal básico da 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 do movimento. Esses endpoints são definidos nos elementos<ConstraintSet>
posteriormente na cena de movimento. -
motion:duration
especifica o número de milissegundos necessários para a conclusão do movimento.
-
-
<OnSwipe>
permite criar um controle por toque para o movimento.-
motion:touchAnchorId
refere-se à 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
refere-se à direção do progresso da ação de arrastar. Por exemplo,motion:dragDirection="dragRight"
significa que o progresso aumenta à medida que 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"
. Na horizontal, os endpoints estão nos lados esquerdo e direito da tela.
Para ver mais detalhes dos vários elementos compatíveis com uma cena de movimento, consulte os exemplos do MotionLayout.
-
Atributos interpolados
Dentro de 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 por MotionLayout
:
alpha
visibility
elevation
rotation
,rotationX
,rotationY
translationX
,translationY
,translationZ
scaleX
,scaleY
Atributos personalizados
Em uma <Constraint>
, você pode usar o elemento <CustomAttribute>
para especificar
uma transição para atributos que não sã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 os métodos getter e setter. O getter e o setter precisam corresponder a um padrão específico. Por exemplo,backgroundColor
é compatível, já que a visualização tem os métodosgetBackgroundColor()
esetBackgroundColor()
subjacentes.- O outro atributo que você precisa fornecer é baseado no tipo de valor. Escolha um
dos seguintes tipos com suporte:
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 os valores do endpoint nos elementos inicial
e final <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, como mostrado na Figura 2.
Adicione um elemento <CustomAttribute>
a cada elemento ConstraintSet
, conforme mostrado no
snippet de código a seguir:
<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, 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 estiver sendo executado. O valor padrão para este atributo éfalse
.app:progress="float"
: permite que você especifique explicitamente o andamento da transição. É possível usar qualquer valor de ponto flutuante de0
(o início da transição) a1
(o fim da transição).app:currentState="reference"
: permite que você especifique umConstraintSet
.app:motionDebug
permite exibir mais informações de depuração 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 recursos abaixo:
- Android avançado no Kotlin 03.2: animação com MotionLayout
- Exemplos do MotionLayout
- Exemplos do MotionLayout/ConstraintLayout (link em inglês) 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)