Android/CoordinatorLayout

Què és? modifica

 
Figura 1. Aplicació que hem creat per tal de veure com funciona el CoordinatorLayout
El Coordinator Layout o "super-powered FrameLayout", és un contenidor de Views el qual ens permet coordinar les Views que estan al seu interior. Gràcies a aquest, podem fer que les nostres Views interactuïn dinàmicament durant l'execució de l'activity. Aquesta interacció s'aconsegueix modificant el comportament que adopten certes Views com per exemple, una AppBar que es desplaça quan fem scroll o volem que en prendre una acció l'activity respongui en el mateix layout.

Podem per exemple coordinar un fab(Floating action buton) i un snackbar, aconseguint fer que en clicar el botó es desplegui el snackbar i el botó és mogui per tal de fer lloc al snack. El CoordinatorLayout està inclòs en la biblioteca design d'Android que alhora aquesta està continguda en la biblioteca de suport. Per tant, ens veurem forçats a utilitzar l'AppCompatActivity si volem treballar amb CoordinatorLayouts per tal d'aconseguir un efecte més dinàmic en la nostra aplicació.

Material Design modifica

 
Figura 2. Material Design
Es tracta d'una normativa de disseny de google enfocada en la visualització d'Android desenvolupada per Google. A continuació podem veure els principals trets de Material que presenta Google (Figura 2):

El material és la metàfora

En el sentit que s'utilitza una teoria unificadora de l'espai i el sistema de moviment que proporciona. S'inspira en el paper i la tinta però dóna pas a multitud d'opcions, i com diu Google, a la màgia.

Afegeixen també la possibilitat de jugar amb les ombres i diferents nivells de superfície amb la qual cosa apareixen relacions en l'espai de les activities que són molt més realistes i alhora atractives.

Atrevit, gràfic i intencional

El nou disseny, segons Google, està basat en la impremta (tipografies, espais, escales, colors i ús d'imatges) que guien el tractament visual dels layouts. Aconsegueixen que sigui un disseny molt més agradable a la vista i permeten una múltiple varietat d'opcions a l'hora de programar una aplicació.

El moviment dóna significat

El moviment respecta i reforça la usabilitat de les pantalles d'Android i millora l'experiència d'usuari. La intenció de Google és mostrar una continuïtat del disseny sense que el canvi de pantalles sigui brusc. Tot això sense perdre eficiència ni coherència.

Organització de les Views modifica

La manera en la qual s'organitzen les Views dintre del CoordinatorLayout és una barreja de l'organització en un Frame Layout i l'organització d'un Relative Layout, ja que podem combinar les principals propietats d'aquest dos tipus de Layouts.

FrameLayout modifica

Per defecte un FrameLayout alinea tots els elements a la part superior esquerra del dispositiu, l'un sobre l'altre amb preferència ascendent, és a dir com si enganxéssim un adhesiu sobre un altre (l'últim que enganxem quedarà per sobre dels altres si aquests se superposen).

Com és lògic el FrameLayout ens permet ubicar els elements en diferents posicions gràcies a l'atribut gravity (android:gravity=" ")

Taula amb els possibles valors assignables a la gravity:
 
Figura 3. Posicions FrameLayout
ConstantValueDescription
top0x30 Push object to the top of its container, not changing its size.
bottom0x50 Push object to the bottom of its container, not changing its size.
left0x03 Push object to the left of its container, not changing its size.
right0x05 Push object to the right of its container, not changing its size.
center_vertical0x10 Place object in the vertical center of its container, not changing its size.
fill_vertical0x70 Grow the vertical size of the object if needed so it completely fills its container.
center_horizontal0x01 Place object in the horizontal center of its container, not changing its size.
fill_horizontal0x07 Grow the horizontal size of the object if needed so it completely fills its container.
center0x11 Place the object in the center of its container in both the vertical and horizontal axis, not changing its size.
fill0x77 Grow the horizontal and vertical size of the object if needed so it completely fills its container.
clip_vertical0x80 Additional option that can be set to have the top and/or bottom edges of the child clipped to its container's bounds. The clip will be based on the vertical gravity: a top gravity will clip the bottom edge, a bottom gravity will clip the top edge, and neither will clip both edges.
clip_horizontal0x08 Additional option that can be set to have the left and/or right edges of the child clipped to its container's bounds. The clip will be based on the horizontal gravity: a left gravity will clip the right edge, a right gravity will clip the left edge, and neither will clip both edges.
start0x00800003 Push object to the beginning of its container, not changing its size.
end0x00800005 Push object to the end of its container, not changing its size.
Tots els valors de la taula anterior es poden combinar entre si utilitzant el següent format android:gravity="valor1 | valor2 | valor3 "

RelativeLayout modifica

Aquest layout permet especificar la posició de cada element de forma relativa al seu element pare o a qualsevol altre element inclòs en el Layout. D'aquesta manera, en incloure un nou element X podrem indicar per exemple que ha de col·locar-se sota l'element Y i alineat a la dreta del Layout pare.

A més a més també tenim l'opció d'ubicar els elements en funció de la ubicació d'altres gràcies als atributs següents:

 
Figura 4. RelativeLayout exemple
Constants Funció que fan
int ABOVE Rule that aligns a child's bottom edge with another child's top edge.
int ALIGN_BASELINE Rule that aligns a child's baseline with another child's baseline.
int ALIGN_BOTTOM Rule that aligns a child's bottom edge with another child's bottom edge.
int ALIGN_END Rule that aligns a child's end edge with another child's end edge.
int ALIGN_LEFT Rule that aligns a child's left edge with another child's left edge.
int ALIGN_PARENT_BOTTOM Rule that aligns the child's bottom edge with its RelativeLayout parent's bottom edge.
int ALIGN_PARENT_END Rule that aligns the child's end edge with its RelativeLayout parent's end edge.
int ALIGN_PARENT_LEFT Rule that aligns the child's left edge with its RelativeLayout parent's left edge.
int ALIGN_PARENT_RIGHT Rule that aligns the child's right edge with its RelativeLayout parent's right edge.
int ALIGN_PARENT_START Rule that aligns the child's start edge with its RelativeLayout parent's start edge.
int ALIGN_PARENT_TOP Rule that aligns the child's top edge with its RelativeLayout parent's top edge.
int ALIGN_RIGHT Rule that aligns a child's right edge with another child's right edge.
int ALIGN_START Rule that aligns a child's start edge with another child's start edge.
int ALIGN_TOP Rule that aligns a child's top edge with another child's top edge.
int BELOW Rule that aligns a child's top edge with another child's bottom edge.
int CENTER_HORIZONTAL Rule that centers the child horizontally with respect to the bounds of its RelativeLayout parent.
int CENTER_IN_PARENT Rule that centers the child with respect to the bounds of its RelativeLayout parent.
int CENTER_VERTICAL Rule that centers the child vertically with respect to the bounds of its RelativeLayout parent.
int END_OF Rule that aligns a child's start edge with another child's end edge.
int LEFT_OF Rule that aligns a child's right edge with another child's left edge.
int RIGHT_OF Rule that aligns a child's left edge with another child's right edge.
int START_OF Rule that aligns a child's end edge with another child's start edge.
int TRUE

RelativeLayout exemple xml:




CoordinatorLayout modifica

Com s'ha especificat anteriorment l'organització de les Views en un CoordinatorLayout és una barreja de l'organització que utilitza el FrameLayout (ja que podem ubicar els objectes l'un sobre l'altre i sense dependència d'on estiguin els altres ubicats amb l'atribut app:layout_anchorGravity=" " ) però a la vegada, el CoordinatorLayout també té propietats semblants a les d'un RelativeLayout perquè aquest permet ancorar una View a una altra amb la propietat (app:layout_anchor="@id/idview"), gràcies a això es pot aconseguir per exemple ancorar un FAB(FloatingActionButon) a una View, i que quan aquesta es desplaci el FAB es desplaci també.

Implementació modifica

Per aclarir el funcionament del CoordinatorLayout a continuació es presenta un exemple d'una petita aplicació que tracta els principals aspectes que ens aporta aquest nou tipus de Layout. El resultat final de l'aplicació serà el mostrat en la figura1.

Com podem observar, l'aplicació reacciona en dues situacions diferents:

  1. Al fer scroll al NestedScrollView (a mesura que fem scroll cap avall la imatge s'amplia i a la inversa)
  2. Al fer clic a un Fab o Floating Action Buton" (Quan fem clic en aquest se'ns desplega un Snackbar que va coordinat amb el botó)

Cal tenir en compte que la API que s'ha utilitzat per desenvolupar el codi es la 24. La mínima per utilitzar recursos d'aquest estil és la 21, que coincideix amb Lollipop 5.0.

Dependències modifica

El CoordinatorLayout es troba en la biblioteca design.widget que alhora es troba dins de la biblioteca de suport d'Android, obligant-nos a treballar amb l'AppCompatActivity si el que volem fer conté un layout del tipus que estem tractant en aquest wiki. Per lo tant tenim les següents dependències:




Java modifica

A continuació adjuntem el codi java de l'aplicació d'exemple. Aquest codi simplement s'encarrega de mostrar un Snackbar al fer clic sobre el FAB.



Layout modifica

 
Figura 5. Organització de les Views en el CoordinatorLayout

A la figura 5 es pot observar l'estructura del layout utilitzat en l'aplicació d'exemple.

A través d'aquesta simple estructura podem veure fàcilment diferents funcionalitats del CoordinatorLayout.

El layout està format per:

- CoordinatorLayout: És el contenidor de Views que engloba tot i permet aplicar afectes.

- AppBarLayout: És un LinearLayout vertical el qual contindrà tot el que volem que es mostri en el AppBar.

- CollapsingToolbarLayout: És un toolbar especialment pensat per utilitzar amb el CoordinatorLayout, permet que l'App Bar es pugui redimensionar en funció del scroll. Gràcies a l'atribut "app:layout_scrollFlags="scroll|exitUntilCollapsed" aconseguim que aquesta faci scroll fins a estar completament col·lapsada ( com es pot observar a la figura1).

- ImageView: Simplement serveix per mostrar una imatge, en el nostre cas dintre del AppBar.

- Toolbar: Barra superior que normalment s'utilitza per mostrar informació de l'aplicació. Com es pot observar en la figua1 el CollapsingToolbar deixa de fer scroll quan arriba al Toolbar, i passa a visual-se només aquest.

- NestedScrollView: Permet que es pugui fer scroll de les views que conté i alhora avarca tant les versions noves com les velles d'android.

- TextView: una text view clàssica.

- FloatingActionButton: botó flotant d'acció que s'utilitza per a un tipus especial d'acció preeminent. Es distingeixen per una icona d'un cercle flotant per sobre de la interfície d'usuari i tenen comportaments especials de moviment relacionats amb morphing, llançament i el punt d'ancoratge de transferència. Aquest botó, està preparat per treballar amb el CoordinatorLayout i no se li ha d'aplicar cap tipus d'atribut especial perquè es coordini amb el snackbar.



Comportament personalitzat modifica

 
Figura 6. Comportament personalitzat.
Una altra manera de fer servir el potencial del CoordinatorLayout és tractant el comportament que volem que adopti una determinada View. No és trivial ni senzill aconseguir el funcionament desitjat que es vulgui. Per aquest motiu, farem servir un codi d'un repositori el qual és bastant clarificador. A través del codi, es reflecteix aquesta característica extra que ens aporta el CoordinatorLayout. Aquest, varia totalment el comportament d'una View dins del layout i és bo destacar quin és el potencial del Coordinator.

Per no aclaparar la wiki amb encara més codi java, s'adjunten les dues funcions principals que fa servir l'autor del codi per a tractar la view. En aquest cas és una CircleImageView. El què desitja fer, és anar movent la imatge cap a la part superior esquerra tal com veiem a la figura 4.

El què fa amb la primera funció presentada (maybeInitProperties) és deduir en quina posició es troba en funció de la view de la qual depèn. En aquest cas és una Toolbar i segons on estigui situada adapta la manera de reduir la CircleImageView. Això ho fa modificant tots els atributs de la classe que ha creat per a tal que les altres funcions després puguin accedir a aquesta informació com en qualsevol altra classe java.

Així doncs en la segona funció el què fa és definir uns punts de canvi que són on la view canviarà de tamany i això ho aplica en funció de com es mogui la Toolbar de la qual depèn.

Un cop definida la classe per al comportament, s'ha d'afegir en el xml per tal que el comportament del nostre layout sigui el que acabem de programar. Per això també s'adjunta aquest fragment de codi xml on es pot veure que es fa servir aquesta classe. S'aprecia en la línia on hi ha una fletxa és on es fa servir la classe que ha creat per a donar el comportament personalitzat a la view que desitjava. Notem també que l'autor treballa amb una modificació del CircleImageView per a tal de poder tractar-la com ell espera que ho faci la funció del comportament. Tot això es el què permet que les Views que veiem en el layout puguin interactuar d'acord amb com s'han programat.

Xml:


Funció maybeInitProperties:


Funció onDependentViewChanged:



Referències i recursos modifica