Introducere în tranzițiile de activitate a Lollipopului

Ce veți crea

Introducere

Unul dintre cele mai interesante aspecte ale specificațiilor Material Design este continuitatea vizuală între activități. Cu doar câteva linii de cod, noile API-uri Lollipop vă permit să treceți în mod semnificativ între două activități, grație animațiilor continue și continue. Aceasta rupe limitele clasice de activitate ale versiunilor anterioare Android și permite utilizatorului să înțeleagă cum merg elementele de la un punct la altul.

În acest tutorial, vă vom arăta cum să obțineți acest rezultat, făcând o aplicație de probă în concordanță cu orientările Google privind designul materialelor.

Cerințe preliminare

În acest tutorial, presupun că deja cunoașteți dezvoltarea Android și că folosiți Android Studio ca IDE. Voi folosi extensiv intențiile Android, presupunând o cunoaștere de bază a ciclului de viață al activității și noul RecyclerView widget introdus cu API 21, în iunie anul trecut. Nu mă voi arunca în detaliile acestei clase, dar, dacă sunteți interesat, puteți găsi o explicație extraordinară în acest tutorial Tuts +.

1. Creați prima activitate

Structura de bază a aplicației este simplă. Există două activități, una principală, MainActivity.java, a căror sarcină este să afișeze o listă de articole și oa doua, DetailActivity.java, care va afișa detaliile articolului selectat în lista precedentă.

Pasul 1: The RecyclerView Widget

Pentru a afișa lista articolelor, activitatea principală va utiliza funcția RecyclerViewwidget introdus în Android Lollipop. Primul lucru pe care trebuie să îl faceți este să adăugați următoarea linie la dependențe în proiectul dvs. build.grade fișier pentru a permite compatibilitatea înapoi:

compile 'com.android.support:recyclerview-v7:+'

Pasul 2: Definirea datelor

Din motive de coerență, nu vom defini o bază de date actuală sau o sursă similară de date pentru aplicație. În schimb, vom folosi o clasă personalizată, a lua legatura. Fiecare element va avea un nume, o culoare și informații de contact de bază asociate acestuia. Aceasta este ceea ce punerea în aplicare a a lua legatura clasa arata ca:

public class Contact // Câmpurile asociate persoanei finale personale String mName, mPhone, mEmail, mCity, mColor; Contact (numele șirului, culoarea String, telefonul String, e-mailul String, orașul String) mName = nume; mColor = culoare; mPhone = telefon; mEmail = e-mail; mCity = oraș;  // Această metodă permite obținerea elementului asociat unui anumit id, // generat în mod unic prin metoda getId definit mai jos public static Contact getItem (int id) pentru (element de contact: CONTACTS) if (item.getId () == id) element retur;  întoarce null;  // deoarece mName și mPhone combinate sunt cu siguranță unice, // nu trebuie să adăugăm alt câmp public id int getId () return mName.hashCode () + mPhone.hashCode ();  public static enum Câmpul NAME, COLOR, PHONE, EMAIL, CITY public String get (Câmp f) comutator (f) caz COLOR: return mColor; caz TELEFON: retur mPhone; cazul EMAIL: retur mEmail; caz CITY: retur mCity; cazul NAME: default: return mName; 

Veți ajunge cu un recipient frumos pentru informațiile de care aveți grijă. Dar trebuie să-l umplem cu unele date. În partea de sus a a lua legatura, adăugați următoarea bucată de cod pentru a popula setul de date.

Prin definirea datelor ca public și static, fiecare clasă din proiect este capabilă să o citească. Într-un sens, vom imita comportamentul unei baze de date, cu excepția faptului că îl codificăm într-o clasă.

public contact static [] CONTACT = contact nou [] Contact nou ("John", "# 33b5e5", "+01 123456789", "[email protected]" , "# ffbb33", "+01 987654321", "[email protected]", "Bologna"), noi contacte ("Eadwine", "# ff4444", "+01 123456789" , "Verde"), noi contacte ("Ives", "# 33b5e5", " +01 11235813 "," [email protected] "," Milan "), noi contacte (" Alajos "," # ffbb33 "," +01 123456789 "," [email protected] "," Bologna " A lua legatura cu ("Gianluca", "# ff4444", "+01 11235813", "[email protected]", "Padova" @ example.com "," Veneția "),;

Pasul 3: Definirea principalelor planificări

Structura activității principale este simplă, deoarece lista va umple întregul ecran. Aspectul include a RelativeLayout ca rădăcină, dar poate fi la fel de bine LinearLayout prea-și a RecyclerView ca singurul său copil.

  

Deoarece RecyclerView widget aranjează subelementele și nimic mai mult, trebuie să creați și aspectul unui singur element de listă. Vrem să avem un cerc colorat în partea stângă a fiecărui element al listei de contacte, astfel încât mai întâi trebuie să definiți trasabilitatea circle.xml.

   

Acum aveți toate elementele necesare pentru a defini aspectul articolului din listă.

      

Pasul 4: Afișați datele utilizând RecyclerView

Aproape am ajuns la sfârșitul primei părți a tutorialului. Trebuie să mai scrieți RecyclerView.ViewHolder si RecyclerView.Adapter, și atribuie totul la vizualizarea asociată în onCreate metoda principală de activitate. În acest caz, RecyclerView.ViewHolder trebuie, de asemenea, să poată gestiona clicurile, astfel încât va trebui să adăugați o anumită clasă capabilă să facă acest lucru. Să începem să definim clasa responsabilă cu manipularea clicurilor.

clasa publică RecyclerClickListener implementează RecyclerView.OnItemTouchListener private OnItemClickListener mListener; GestureDetector mGestureDetector; interfață publică OnItemClickListener public void onItemClick (Vizualizare vizualizare, poziție int);  public RecyclerClickListener (contextual context, ascultător OnItemClickListener) mListener = ascultător; mGestureDetector = nou GestureDetector (context, noul GestureDetector.SimpleOnGestureListener () @Override public boolean onSingleTapUp (MotionEvent e) return true;);  @Override public boolean onInterceptTouchEvent (vizualizare RecyclerView, MotionEvent e) View childView = view.findChildViewUnder (e.getX (), e.getY ()); dacă (childView! = null && mListener! = null && mGestureDetector.onTouchEvent (e)) mListener.onItemClick (childView, view.getChildPosition (childView)); return true;  return false;  @Override public void onTouchEvent (vizualizare RecyclerView, MotionEvent motionEvent) 

Este necesar să se precizeze RecyclerView.Adapter, pe care o voi numi Manager de date. Acesta este responsabil pentru încărcarea datelor și introducerea acestora în vizualizările din listă. Această clasă de manager de date va conține, de asemenea, definiția RecyclerView.ViewHolder.

public class DataManager extinde RecyclerView.Adapter public class static RecyclerViewHolder extinde RecyclerView.ViewHolder TextView mName, mPhone; Vizualizați mCircle; RecyclerViewHolder (vizualizați itemView) super (itemView); mName = (TextView) itemView.findViewById (R.id.CONTACT_name); mPhone = (TextView) itemView.findViewById (R.id.CONTACT_phone); mCircle = itemView.findViewById (R.id.CONTACT_circle);  @Override publice RecyclerViewHolder onCreateViewHolder (ViewGroup viewGroup, int i) Vezi v = LayoutInflater.from (viewGroup.getContext ()) inflate (R.layout.contact_item, viewGroup, false); returnați noul RecyclerViewHolder (v);  @Overide public void onBindViewHolder (RecyclerViewHolder viewHolder, int i) // obține elementul unic de la finalul matricei principale Contact contact = Contact.CONTACTS [i]; // Setați valorile viewHolder.mName.setText (contact.get (Contact.Field.NAME)); viewHolder.mPhone.setText (contact.get (Contact.Field.PHONE)); // Setați culoarea formei GradientDrawable bgShape = (GradientDrawable) viewHolder.mCircle.getBackground (); bgShape.setColor (Color.parseColor (contact.get (Contact.Field.COLOR)));  @Override public int getItemCount () retur Contact.CONTACTS.length; 

În final, adăugați următorul cod la onCreatemai jos setContentView. Activitatea principală este gata.

RecyclerView rv = (ReciclareView) findViewById (R.id.rv); // referință layout LinearLayoutManager llm = new LinearLayoutManager (acest lucru); rv.setLayoutManager (LLM); rv.setHasFixedSize (true); // pentru a îmbunătăți performanța rv.setAdapter (nou DataManager ()); // managerul de date este asistent la RV rv.addOnItemTouchListener (// și clicul este manipulat cu noul RecyclerClickListener (acest nou RecyclerClickListener.OnItemClickListener () @Override public void onItemClick (View view, int position) // STUB: // Clic pe element trebuie manipulat));

Aceasta este ceea ce arată aplicația dacă construiți și rulați-o.

2. Creați activitatea Detalii

Pasul 1: Aspectul

A doua activitate este mult mai simplă. Acesta ia ID-ul persoanei de contact selectate și returnează informațiile suplimentare pe care prima activitate nu le afișează.

Din punct de vedere al designului, aspectul acestei activități este critic, deoarece este cea mai importantă parte a aplicației. Dar pentru ceea ce privește XML, este banal. Aspectul este o serie de TextView instanțe poziționate într-un mod plăcut, folosind RelativeLayout și LinearLayout. Aspectul arata astfel:

                    

Pasul 2: Trimiteți și primiți ID-ul prin intermediul extraselor intenționate

Întrucât cele două activități sunt legate printr-o intenție, trebuie să trimiteți câteva informații care să permită celei de-a doua activități să înțeleagăcontactați că ați solicitat detaliile.

O singură opțiune poate fi folosirea variabilei de poziție ca referință. Poziția elementului din listă corespunde poziției elementului din matrice, astfel încât nu ar trebui să existe nimic rău în utilizarea acestui întreg ca referință unică.

Acest lucru ar funcționa, dar dacă luați această abordare și, din orice motiv, setul de date este modificat în timpul rulării, referința nu se va potrivi cu persoana de contact care vă interesează. Acesta este motivul pentru care este mai bine să utilizați un IDad-hoc. Această informație este getId metoda definită în a lua legatura clasă.

Editați onItemClick handler al listei de articole, după cum se arată mai jos.

@Override public void onItemClick (Afișare vizualizare, poziție int) Intent intent = new Intent (MainActivity.this, DetailsActivity.class); intent.putExtra (DetaliiActivity.ID, Contact.CONTACTS [position] .getId ()); startActivity (intenție); 

DetailsActivity vor primi informațiile de la scop extrage și construi obiectul corect utilizând ID-ul ca referință. Acest lucru este afișat în următorul bloc de coduri.

// Înainte de a forma onCreate public static final String ID = "ID"; public Contact mContact;
// În onCreate, după metoda setContentView mContact = Contact.getItem (getIntent (). GetIntExtra (ID, 0));

La fel ca înainte în onCreateViewHolder metodă a RecylerView, viziunile sunt inițializate folosind findViewById metodă și utilizare populată setText. De exemplu, pentru a configura câmpul de nume, facem următoarele:

mName = (TextView) findViewById (R.id.DETAILS_name); mName.setText (mContact.get (Contact.Field.NAME));

Procesul este același pentru celelalte câmpuri. A doua activitate este în sfârșit gata.

3. Tranziții semnificative

Am ajuns în cele din urmă la baza tutorialului, animând cele două activități folosind noua metodă Lollipop pentru tranziție folosind un element partajat.

Pasul 1: Configurați-vă proiectul

Primul lucru pe care trebuie să-l faceți este să editați tema în style.xml fișier în Valori-V21 pliant. În acest fel, activați tranzițiile de conținut și setați intrarea și ieșirea din vizualizările care nu sunt partajate între cele două activități.

 

Rețineți că proiectul dvs. trebuie să vizeze cel puțin (și astfel să fie compilat cu) Android API 21.

Animațiile vor fi ignoratepe sistemele care nu au instalat Lollipop. Din păcate, din motive de performanță, AppCompat biblioteca nu oferă compatibilitate completă înapoi pentru aceste animații.

Pasul 2: Atribuiți numele de tranziție în fișierele de dispunere

Odată ce v-ați editat style.xml fișier, trebuie să subliniezi relațiaîntre cele două elemente comune ale punctelor de vedere.

În exemplul nostru, vizionările partajate sunt câmpul care conține numele contactului, cel al numărului de telefon și cercul colorat. Pentru fiecare dintre ele, trebuie să specificați a numele comun de tranziție. Din acest motiv, începeți adăugarea în strings.xml resursează următoarele elemente:

tranziție: NAME tranziție: CERC tranziție: TELEFON 

Apoi, pentru fiecare dintre cele trei perechi, în fișierele de aspect adăugați Android: transitionName atribuiți cu valoarea corespunzătoare. Pentru cercul colorat, codul arată astfel:

 
 

Datorită acestui atribut, Android va ști care sunt viziunile partajate între cele două activități și va anima în mod corect tranziția. Repetați același proces pentru celelalte două vizionări.

Pasul 3: Configurați intenția

Din punct de vedere al codării, va trebui să atașați un anumit ActivityOptions pachet de intenție. Metoda de care aveți nevoie este makeSceneTransitionAnimation, care ia ca parametri contextul aplicației și cât mai multe elemente comune de care avem nevoie. În onItemClick metodă a RecyclerView, editați definiția definită anterior scop asa:

@Override public void onItemClick (Afișare vizualizare, poziție int) Intent intent = new Intent (MainActivity.this, DetailsActivity.class); intent.putExtra (DetaliiActivity.ID, Contact.CONTACTS [position] .getId ()); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation (// Contextul activității MainActivity.this, // Pentru fiecare element partajat, adăugați la această metodă un nou element Pair, // care conține referința vizualizării pe care o tranziționăm * din *, // și valoarea atributului transitionName new Pair(view.findViewById (R.id.CONTACT_circle), getString (R.string.transition_name_circle)), noua pereche(view.findViewById (R.id.CONTACT_name), getString (R.string.transition_name_name)), noua pereche(view.findViewById (R.id.CONTACT_phone), getString (R.string.transition_name_phone))); ActivityCompat.startActivity (MainActivity.this, intent, options.toBundle ()); 

Pentru fiecare element partajat care urmează să fie animat, va trebui să adăugați la makeSceneTransitionAnimation metodă nouă Pereche articol. Fiecare Pereche are două valori, prima este o referință la punctul de vedere pe care îl treceți din, al doilea este valoare din transitionName atribut.

Aveți grijă când importați Pereche clasă. Va trebui să includeți android.support.v4.util pachet, nu android.util pachet. De asemenea, nu uitați să utilizați ActivityCompat.startActivity în loc de startActivity deoarece altfel nu veți putea rula aplicația dvs. pe medii cu API sub 16 ani.

Asta e. Ați terminat. Este la fel de simplu ca asta.

Concluzie

În acest tutorial ați învățat cum să treceți frumos și fără probleme între două activități care împărtășesc unul sau mai multe elemente comune, permițând o continuitate vizibilă și plăcută.

Ați început să faceți prima dintre cele două activități, al căror rol este să afișați lista de contacte. Apoi, ați finalizat cea de-a doua activitate, proiectându-i aspectul și implementând o modalitate de a transmite o referință unică între cele două activități. În sfârșit, te-ai uitat la modul în care makeSceneTransitionAnimation lucrări, grație XML transitionName atribut.

Bonus Sfat: detalii stilistică

Pentru a crea o aplicație cu aspect material, așa cum se arată în capturile de ecran anterioare, va trebui, de asemenea, să modificați culorile temei. Editați tema de bază în Valori-V21 dosar pentru a obține un rezultat frumos.

Cod