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 del movimento, offrendo un mix di funzionalità tra il framework di animazione delle proprietà, TransitionManager e CoordinatorLayout.
Oltre a descrivere le transizioni tra i layout, MotionLayout ti consente di animare qualsiasi proprietà del layout. Inoltre, supporta intrinsecamente le transizioni
ricercabili. Ciò significa che puoi mostrare istantaneamente qualsiasi punto all'interno della transizione
in base a una condizione, ad esempio l'input tocco. MotionLayout supporta anche
i fotogrammi chiave, consentendo transizioni completamente personalizzate in base alle tue esigenze.
MotionLayout è completamente dichiarativo, il che significa che puoi descrivere qualsiasi transizione in
XML, indipendentemente dalla sua complessità.
Note sul layout
MotionLayout è progettato per spostare, ridimensionare e animare gli elementi della UI con cui
gli utenti interagiscono, come pulsanti e barre del titolo. Non utilizzare il movimento nella tua app come
effetto speciale senza costi. Utilizzalo 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
Comprendere il
movimento di Material Design.
Inizia
Per iniziare a utilizzare MotionLayout nel tuo progetto, segui questi passaggi.
-
Aggiungi la dipendenza
ConstraintLayout:per utilizzareMotionLayoutnel tuo progetto, aggiungi la dipendenzaConstraintLayout2.0 al filebuild.gradledella tua app. Se utilizzi AndroidX, aggiungi la seguente dipendenza:Alla moda
dependencies { implementation "androidx.constraintlayout:constraintlayout:2.2.1" // To use constraintlayout in compose implementation "androidx.constraintlayout:constraintlayout-compose:1.1.1" }
Kotlin
dependencies { implementation("androidx.constraintlayout:constraintlayout:2.2.1") // To use constraintlayout in compose implementation("androidx.constraintlayout:constraintlayout-compose:1.1.1") }
-
Crea un file
MotionLayout:MotionLayoutè una sottoclasse diConstraintLayout, quindi puoi trasformare qualsiasiConstraintLayoutesistente in unMotionLayoutsostituendo il nome della classe nel file di risorse di layout, come mostrato negli esempi seguenti:AndroidX
<!-- before: ConstraintLayout --> <androidx.constraintlayout.widget.ConstraintLayout .../> <!-- after: MotionLayout --> <androidx.constraintlayout.motion.widget.MotionLayout .../>
Support Library
<!-- 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: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>
Support Library
<?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 MotionScene:nell'esempio precedente di
MotionLayout, l'attributoapp:layoutDescriptionfa riferimento a una scena di movimento. Una scena di movimento è un file di risorse XML. All'interno dell'elemento<MotionScene>radice, una scena di movimento contiene tutte le descrizioni di movimento per il layout corrispondente. Per mantenere separate le informazioni sul layout dalle descrizioni del movimento, ogniMotionLayoutfa riferimento a una scena di movimento separata. Le definizioni nella scena di movimento hanno la precedenza su qualsiasi definizione simile inMotionLayout.Ecco un esempio di file di scena di 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>
Tieni presente quanto segue:
-
<Transition>contiene la definizione di base del movimento.-
motion:constraintSetStartemotion:constraintSetEndsono riferimenti agli endpoint del movimento. Questi endpoint sono definiti negli elementi<ConstraintSet>più avanti nella scena di movimento. -
motion:durationspecifica il numero di millisecondi necessari per completare il movimento.
-
-
<OnSwipe>ti consente di creare un controllo touch per il movimento.-
motion:touchAnchorIdsi riferisce alla visualizzazione che l'utente può scorrere e trascinare. -
motion:touchAnchorSideindica che la visualizzazione viene trascinata dal lato destro. -
motion:dragDirectionsi riferisce alla direzione di avanzamento del trascinamento. Ad esempio,motion:dragDirection="dragRight"indica che l'avanzamento 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 all'estrema sinistra e destra 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 di movimento, gli elementi ConstraintSet possono contenere attributi aggiuntivi che vengono interpolati durante la transizione. Oltre a posizione e
limiti, i seguenti attributi vengono interpolati da MotionLayout:
alphavisibilityelevationrotation,rotationXerotationYtranslationX,translationYetranslationZscaleX,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 propri:
motion:attributeNameè obbligatorio e deve corrispondere a un oggetto con metodi getter e setter. I metodi getter e setter devono corrispondere a un pattern specifico. Ad esempio,backgroundColorè supportato, poiché la vista ha metodigetBackgroundColor()esetBackgroundColor()sottostanti.- L'altro attributo che devi fornire dipende dal tipo di valore. Scegli tra
i seguenti tipi supportati:
motion:customColorValueper i colorimotion:customIntegerValueper i numeri interimotion:customFloatValueper i floatmotion:customStringValueper le stringhemotion:customDimensionper le dimensionimotion:customBooleanper i valori booleani
Quando specifichi un attributo personalizzato, definisci i valori dell'endpoint sia nell'elemento <ConstraintSet> iniziale che in quello finale.
Cambiare il colore dello sfondo
Riprendendo l'esempio precedente, supponiamo che tu voglia che i colori della visualizzazione cambino come parte del suo movimento, come mostrato nella figura 2.
Aggiungi un elemento <CustomAttribute> a ogni elemento ConstraintSet, come mostrato nello snippet di codice seguente:
<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 le traiettorie di movimento durante l'esecuzione del movimento. Il valore predefinito di questo attributo èfalse.app:progress="float"consente di specificare esplicitamente l'avanzamento della transizione. Puoi utilizzare qualsiasi valore in rappresentazione in virgola mobile da0(l'inizio della transizione) a1(la fine della transizione).app:currentState="reference"ti consente di specificare unConstraintSetspecifico.app:motionDebugti consente di visualizzare informazioni di debug aggiuntive sul movimento. I valori possibili sono"SHOW_PROGRESS","SHOW_PATH"o"SHOW_ALL".
Risorse aggiuntive
Per maggiori 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)