MotionLayout
è un tipo di layout che ti aiuta a gestire il movimento e l'animazione dei widget nella tua app.MotionLayout
è una sottoclasse di ConstraintLayout
e si basa sulle sue ricche funzionalità di layout. Nell'ambito della libreria ConstraintLayout
, MotionLayout
è disponibile come libreria di supporto.
MotionLayout
colma il divario tra le transizioni di layout e la gestione complessa dei movimenti, offrendo un mix di funzionalità tra il framework di animazione delle proprietà, TransitionManager
e CoordinatorLayout
.
Oltre a descrivere le transizioni tra i layout, MotionLayout
consente di animare qualsiasi proprietà del layout. Inoltre, supporta intrinsecamente le transizioni scorrevoli. Ciò significa che puoi mostrare immediatamente qualsiasi punto all'interno della transizione in base a una condizione, ad esempio l'input tocco. MotionLayout
supporta anche i keyframe, che consentono transizioni completamente personalizzate in base alle tue esigenze.
MotionLayout
è completamente dichiarativo, il che significa che puoi descrivere qualsiasi transizione in XML, indipendentemente dalla complessità.
Considerazioni sul design
MotionLayout
è progettato per spostare, ridimensionare e animare gli elementi dell'interfaccia utente con cui interagiscono gli utenti, ad esempio pulsanti e barre dei titoli. Non utilizzare il movimento nella tua app come
effetto speciale senza costi. Utilizzala per aiutare gli utenti a capire cosa fa la tua app. Per saperne di più sulla progettazione dell'app con il movimento, consulta la sezione Informazioni sul movimento di Material Design.
Inizia
Per iniziare a utilizzare MotionLayout
nel tuo progetto, segui questi passaggi.
-
Aggiungi la dipendenza
ConstraintLayout
: per utilizzareMotionLayout
nel tuo progetto, aggiungi la dipendenzaConstraintLayout
2.0 al filebuild.gradle
della tua app. Se utilizzi AndroidX, aggiungi la seguente dipendenza:dependencies {
implementation "androidx.constraintlayout:constraintlayout:2.2.0-beta01"
// To use constraintlayout in compose
implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-beta01"
}dependencies {
implementation("androidx.constraintlayout:constraintlayout:2.2.0-beta01")
// To use constraintlayout in compose
implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-beta01")
} -
Crea un file
MotionLayout
:MotionLayout
è una sottoclasse diConstraintLayout
, quindi puoi trasformare qualsiasiConstraintLayout
esistente in unMotionLayout
sostituendo il nome della classe nel file della risorsa di layout, come mostrato nei seguenti esempi:<!-- before: ConstraintLayout --> <androidx.constraintlayout.widget.ConstraintLayout .../> <!-- after: MotionLayout --> <androidx.constraintlayout.motion.widget.MotionLayout .../>
<!-- before: ConstraintLayout --> <android.support.constraint.ConstraintLayout .../> <!-- after: MotionLayout --> <android.support.constraint.motion.MotionLayout .../>
Ecco un esempio completo di un file
MotionLayout
, che definisce il layout mostrato nella figura 1:<?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>
<?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>
-
Crea una scena animata: nell'esempio
MotionLayout
precedente, l'attributoapp:layoutDescription
fa riferimento a una scena animata. Una scena in movimento è un file di risorse XML. All'interno del suo elemento radice<MotionScene>
, una scena animata contiene tutte le descrizioni dei movimenti per il layout corrispondente. Per mantenere separate le informazioni sul layout dalle descrizioni del movimento, ogniMotionLayout
fa riferimento a una scena di movimento distinta. Le definizioni nella scena in movimento hanno la precedenza su eventuali definizioni simili nelMotionLayout
.Ecco un esempio di file di scena con movimento che descrive il movimento orizzontale di base nella 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>
Nota:
-
<Transition>
contiene la definizione di base del movimento.-
motion:constraintSetStart
emotion:constraintSetEnd
sono riferimenti ai punti finali del movimento. Questi endpoint sono definiti negli elementi<ConstraintSet>
più avanti nella scena di movimento. -
motion:duration
specifica il numero di millisecondi necessari per completare il movimento.
-
-
<OnSwipe>
consente di creare un controllo touch per il movimento.-
motion:touchAnchorId
si riferisce alla visualizzazione che l'utente può scorrere e trascinare. -
motion:touchAnchorSide
indica che la visualizzazione viene trascinata dal lato destro. -
motion:dragDirection
si riferisce alla direzione di avanzamento del trascinamento. Ad esempio,motion:dragDirection="dragRight"
indica che il progresso aumenta man mano che la visualizzazione viene trascinata verso destra.
-
-
<ConstraintSet>
è dove definisci i vari vincoli che descrivono il movimento. In questo esempio, viene definito un<ConstraintSet>
per ogni endpoint del movimento. Questi endpoint sono centrati verticalmente utilizzandoapp:layout_constraintTop_toTopOf="parent"
eapp:layout_constraintBottom_toBottomOf="parent"
. Orizzontalmente, gli endpoint si trovano ai lati sinistro e destro dello schermo.
Per un'analisi più dettagliata dei vari elementi supportati da una scena di movimento, consulta gli esempi di MotionLayout.
-
Attributi interpolati
All'interno di un file di scena animata, gli elementi ConstraintSet
possono contenere attributi aggiuntivi che vengono interpolati durante la transizione. Oltre a position e
bounds, i seguenti attributi vengono interpolati da MotionLayout
:
alpha
visibility
elevation
rotation
,rotationX
erotationY
translationX
,translationY
etranslationZ
scaleX
,scaleY
Attributi personalizzati
All'interno di un <Constraint>
, puoi utilizzare l'elemento <CustomAttribute>
per specificare
una transizione per gli attributi che non sono semplicemente correlati alla posizione o agli attributi View
.
<Constraint android:id="@+id/button" ...> <CustomAttribute motion:attributeName="backgroundColor" motion:customColorValue="#D81B60"/> </Constraint>
Un <CustomAttribute>
contiene due attributi:
motion:attributeName
è obbligatorio e deve corrispondere a un oggetto con metodi getter e setter. Il getter e il setter devono corrispondere a un pattern specifico. Ad esempio,backgroundColor
è supportato, poiché la visualizzazione ha metodigetBackgroundColor()
esetBackgroundColor()
sottostanti.- L'altro attributo da fornire si basa sul tipo di valore. Scegli tra
i seguenti tipi supportati:
motion:customColorValue
per i colorimotion:customIntegerValue
per numeri interimotion:customFloatValue
per i floatmotion:customStringValue
per le stringhemotion:customDimension
per le dimensionimotion:customBoolean
per i valori booleani
Quando specifichi un attributo personalizzato, definisci i valori di endpoint sia negli elementi <ConstraintSet>
inizio che
<ConstraintSet>
fine.
Cambia il colore dello sfondo
Basandoti sull'esempio precedente, supponiamo che tu voglia che i colori della visualizzazione cambino nel corso del movimento, come mostrato nella figura 2.
Aggiungi un elemento <CustomAttribute>
a ogni elemento ConstraintSet
, come mostrato nel seguente snippet di codice:
<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>
Attributi MotionLayout aggiuntivi
Oltre agli attributi nell'esempio precedente, MotionLayout
ha altri attributi che potresti voler specificare:
app:applyMotionScene="boolean"
indica se applicare la scena di movimento. Il valore predefinito di questo attributo ètrue
.app:showPaths="boolean"
indica se mostrare i percorsi di movimento durante l'esecuzione del movimento. Il valore predefinito di questo attributo èfalse
.app:progress="float"
consente di specificare in modo esplicito lo stato di avanzamento della transizione. Puoi utilizzare qualsiasi valore in virgola mobile da0
(l'inizio della transizione) a1
(la fine della transizione).app:currentState="reference"
ti consente di specificare unConstraintSet
specifico.app:motionDebug
ti consente di visualizzare ulteriori informazioni di debug sul movimento. I valori possibili sono"SHOW_PROGRESS"
,"SHOW_PATH"
o"SHOW_ALL"
.
Risorse aggiuntive
Per ulteriori informazioni su MotionLayout
, consulta le seguenti risorse:
- Android avanzato in Kotlin 03.2: animazione con MotionLayout
- Esempi di MotionLayout
- Esempi di MotionLayout/ConstraintLayout su GitHub
- Introduzione a MotionLayout (parte I)
- Introduzione a MotionLayout (parte II)
- Introduzione a MotionLayout (parte III)
- Introduzione a MotionLayout (parte IV)