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.
Î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 +.
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ă.
RecyclerView
WidgetPentru a afișa lista articolelor, activitatea principală va utiliza funcția RecyclerView
widget 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:+'
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 "),;
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ă.
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.Adapterpublic 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 onCreate
mai 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.
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:
Î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.
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.
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.
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.
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.
Î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.
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.