Crearea de animații cu MotionLayout pentru Android

Datorită remarcabilului său versatilitate, ConstraintLayout widget-ul a devenit "cuțitul armatei elvețiene" de machete pentru dezvoltatorii de aplicații Android. Cu toate acestea, adăugarea de animații complexe la conținutul său, deși posibil, poate fi destul de consumatoare de timp. De aceea, Google a introdus MotionLayout widget în I / O 2018.

MotionLayout widgetul, care face parte acum din biblioteca de suport Android, extinde ConstraintLayout widget. Acesta este un widget unic care vă permite să animați conținutul său declarativ folosind doar XML. Mai mult decât atât, oferă un control fin în toate animațiile sale.

În acest tutorial, vă vom arăta cum să îl adăugați la proiectele dvs. Android Studio și să creați câteva animații diferite cu acesta.

Cerințe preliminare

Pentru a urma acest tutorial, veți avea nevoie de:

  • Android Studio 3.1.3 sau o versiune ulterioară
  • un dispozitiv sau un emulator care rulează Android API nivel 21 sau superior
  • o înțelegere de bază a ConstraintLayout widget

1. Adăugați dependențe

Pentru a putea folosi MotionLayout widget în proiectul dvs. Android Studio, trebuie să aveți cea mai recentă versiune a bibliotecii de asistență pentru aspectul constrângerilor ca o punerea în aplicare dependenţă. În plus, pentru a evita conflictele de versiuni, asigurați-vă că includeți o dependență pentru cea mai recentă versiune stabilă a bibliotecii de suport pentru aplicații v7 appcompat.

În consecință, adăugați următorul cod la aplicaţia ale modulului build.gradle fişier:

implementare 'com.android.support:appcompat-v7:27.0.2' implementare 'com.android.support.constraint: constraint-layout: 2.0.0-alpha1'

2. Definirea unui aspect

MotionLayout widgetul poate face totul ConstraintLayout widget poate. Prin urmare, puteți înlocui în mod liber orice instanță a acesteia din urmă cu cea dintâi. Pentru moment, însă, vă sugerez să creați un nou fișier XML de aspect și să adăugați MotionLayout widget pentru ea ca element rădăcină.

   

De-a lungul acestui tutorial, vom anima un ImageView widget. Deci, adăugați-l ca primul copil al aspectului.

Aveți libertatea de a utiliza orice sursă de tragere ca sursă ImageView widget. În codul de mai sus, folosesc o culoare trasabilă.

Apoi, adăugați un buton pe care îl puteți apăsa pentru a porni animațiile. Următorul cod vă arată cum să-l poziționați în centrul planului:

În plus, pentru a monitoriza progresul animațiilor, adăugați o SeekBar widget la aspect și poziționează-l sub buton. Iată cum:

În sfârșit, pentru că există un handler de evenimente pe clic asociat cu butonul, asigurați-vă că îl definiți în activitatea dvs..

fun start (v: View) // Mai mult cod aici

3. Creați o scenă de mișcare

S-ar putea să fi observat că nu am adăugat nici o constrângere la ImageView widget în timp ce definește aspectul. Asta pentru că îi vom adăuga într-o scenă de mișcare. O scenă de mișcare este un fișier XML care conține detalii despre animația pe care doriți să o creați cu o MotionLayout widget.

Pentru a crea o nouă scenă de mișcare, creați un fișier de resurse XML și adăugați o MotionScene element la el.

   

O scenă de mișcare conține ConstraintSet elemente care specifică constrângerile care trebuie aplicate unui widget în diferite puncte ale animației. Filmele scenelor de mișcare conțin de obicei două seturi de constrângeri: una pentru începutul animației și una pentru sfârșit.

Următorul cod vă arată cum să creați două seturi de constrângeri care vă vor ajuta MotionLayout widget-ul muta ImageView widget din colțul din dreapta jos al ecranului în colțul din stânga sus:

     

Rețineți că fiecare ConstraintSet elementul trebuie să specifice întotdeauna atât poziția dorită, cât și dimensiunea dorită. Acest lucru este important deoarece va suprascrie toate informațiile definite anterior.

Pentru a ajuta la MotionLayout widget înțelege ordinea în care seturile de constrângeri trebuie aplicate, trebuie să creați în continuare a Tranziție element. Folosind numele său intuitiv constraintSetStart și constraintSetEnd atribute, puteți specifica care set trebuie aplicat mai întâi și care este ultima. Tranziție element vă permite de asemenea să specificați durata animației.

 

În acest moment, scena mișcării este completă. Însă MotionLayout widget-ul încă nu este conștient de acesta. Deci, du-te înapoi la fișier XML layout, adăugați a layoutDescription atribuiți widgetului și setați valoarea sa la numele fișierului scenei de mișcare.

Dacă numele fișierului dvs. de scena de mișcare este my_scene.xml, ta MotionLayout widget ar trebui să arate astfel:

... 

4. Porniți animația

Când rulați aplicația, MotionLayout widgetul va aplica automat setul de constrângeri specificat în constraintSetStart atributul Tranziție element. Prin urmare, pentru a începe animația, tot ce trebuie să faceți este să apelați transitionToEnd () metoda widgetului. Următorul cod, care trebuie adăugat la un handler de evenimente pe clic pe care l-ați creat într-un pas anterior, vă arată cum:

motion_container.transitionToEnd ()

În acest moment, dacă rulați aplicația și apăsați butonul, ar trebui să vedeți ImageView widget se deplasează ușor pe ecran.

 

5. Manipulați evenimentele de animație

Prin atașarea a TransitionListener obiecte față de MotionLayout widget, puteți monitoriza îndeaproape progresul animației.

motion_container.setTransitionListener (obiect: MotionLayout.TransitionListener // Mai mult cod aici)

TransitionListener interfața are două metode abstracte, iar Android Studio va genera automat stuburi pentru ei.

onTransitionCompleted () metoda este numită atunci când o tranziție de la o constrângere setată la alta este completă. Pentru moment, să o folosim pentru resetarea constrângerilor ImageView widget prin apelarea transitionToStart () în interiorul său.

suprascrie distracția onTransitionCompleted (motionLayout: MotionLayout ?, currentId: Int) if (currentId == R.id.ending_set) // Reveniți la setul de constrângeri originale motion_container.transitionToStart ()

onTransitionChange () metoda se numește de fiecare dată când se schimbă progresul animației. Ca atare, progresul este un număr în virgulă mobilă care se află între zero și unul. Următorul cod vă arată cum să actualizați SeekBar bazat pe progresul animației:

înlocuiți distracția peTransitionChange (motionLayout: MotionLayout ?, startId: Int, endId: Int, progres: Float) seekbar.progress = ceil (progres * 100) .toInt ()

Continuați și rulați aplicația din nou pentru a vedea două animații acum.

 

6. Creați cadre cheie

În animația noastră, ImageView widgetul se mută într-o cale care arată ca o linie dreaptă. Asta pentru că MotionLayout widget-ului i se dau doar două puncte pentru a lucra cu: punctul de pornire, care este în colțul din dreapta jos al ecranului, și punctul de sfârșit, care este în colțul din stânga sus al ecranului. Dacă doriți să modificați forma traseului, va trebui să furnizați câteva puncte intermediare, care se află între punctele de plecare și sfârșit. Pentru a face acest lucru, va trebui să creați noi cadre cheie.

Înainte de a începe să creați cadre cheie, trebuie să adăugați a KeyFrameSet element la Tranziție element al scenei dvs. de mișcare. În interiorul noului element, aveți libertatea de a crea orice număr de cadre cheie.

  

MotionLayout widget-ul acceptă multe tipuri diferite de cadre cheie. În acest tutorial, vom lucra cu numai două tipuri: KeyPosition cadre și cadre KeyCycle rame.

KeyPosition cadrele sunt cele care vă ajută să modificați forma căii. În timpul creării acestora, asigurați-vă că furnizați ID-ul widget-ului țintă, o poziție de-a lungul liniei de timp, care poate fi orice număr între 0 și 100 și coordonatele dorite X sau Y specificate ca procent. Coordonatele pot fi fie relative la axele X sau Y actuale, fie pot fi relativ la traseul propriu-zis.

Următorul cod vă arată cum să creați două cadre cheie care forțează ImageView widget pentru a urma o cale care evită coliziuni cu butonul și bara de căutare:

 

Dacă rulați aplicația acum, ar trebui să vedeți o animație care arată astfel:

 

Sunteți, desigur, liberi să adăugați mai multe cadre cheie. De exemplu, adăugând următorul cadru cheie spre sfârșitul liniei de timp, puteți face ImageView widget-ul urmează o cale mai ondulată:

Folosind a KeyCycle cadru împreună cu KeyPosition cadre, puteți adăuga oscilații la animație. În timp ce îl creați, trebuie să furnizați din nou ID-ul widgetului țintă, o poziție de-a lungul cronologiei și valoarea dorită a proprietății care trebuie să oscileze înainte și înapoi. În plus, trebuie să configurați un oscilator furnizând detalii cum ar fi forma de undă de utilizat și perioada de undă.

Următorul cod creează o KeyCycle cadru care utilizează un oscilator sinusoidal pentru a roti periodic ImageView widget cu 50 de grade:

La rularea aplicației din nou, ar trebui să vedeți o animație care arată astfel:

 

7. Faceți animații widget interactive

În tot acest timp, ați apăsat un buton pentru a începe animația. Un astfel de buton nu este totuși necesar pentru că MotionLayout widget vă permite să atașați direct agenții de operare touch widget-uri animate. În prezent, acceptă evenimentele "on-click" și "on-swipe". 

De exemplu, puteți adăuga următoarele OnClick element, care vizează ImageView widget, în interiorul Tranziție element al scenei dvs. de mișcare pentru a face butonul redundant:

În mod similar, puteți utiliza un OnSwipe pentru a permite utilizatorului să tragă manual ImageView widget de pe ecran. În timp ce creați elementul, trebuie să vă asigurați că furnizați direcția potrivită de tragere și partea laterală a widget-ului care ar trebui să acționeze ca mânerul de tragere.

Dacă rulați din nou aplicația, acum ar trebui să puteți glisa ImageView widget.

 

Concluzie

Acum știți cum să utilizați MotionLayout widget pentru a adăuga rapid aplicații Android complexe, interactive. Puteți să vă asigurați că animațiile se vor desfășura fără nici un decalaj sau jitter pe majoritatea dispozitivelor, atâta timp cât evitați vizionările imbricate.

Merită remarcat faptul că versiunile viitoare de Android Studio vor include un Motion Editor vizual, care va îmbunătăți în continuare utilitatea widget-ului.

Pentru a afla mai multe, consultați documentația oficială.

Cod