IMPORTANT: Per accedir als fitxer de subversion: http://acacha.org/svn (sense password). Poc a poc s'aniran migrant els enllaços. Encara però funciona el subversion de la farga però no se sap fins quan... (usuari: prova i la paraula de pas 123456)

Overview

Home

All Apps

Recents

User Interface Layout

Andrescorazon user interface layout.png

Menús

Els menús són un component d'interfície d'usuari molt comuns en molts tipus d'aplicacions. Android proporciona una API de menús que permet presentar accions d'usuari d'una forma familiar i consistent. Els menús es gestionen principalment a partir de la Vista Android:

android.view.Menu

Des de la versió Android 3.0 (API level 11), ja no és necessari proveir d'un botó de menú dedicat. Cal tenir en compte que a més s'imposa el paradigma de disseny basat en Action Bar. Ja no és necessari proveir d'un menú amb totes les opcions sinó que es poden destacar les opcions de menú més importants posant-les a l'action bar.

Els menús d'accions es poden veure com una col·lecció Java, és a dir un grup d'objectes. Cada objecte del grup s'anomena menu item. Els menús tenen les accions més importants d'una activitat android: buscar, configuració, crear un email, etc...

Per mostrar el menú a l'usuari tenim dos opcions:

  • Android 2.3 o anterior: cal prémer el botó de menú.
Andrescorazon options menu example android2.3.png
  • Android 3.0 o superior: El menú d'opcions es mostra en dos parts:
  • On-screen actions: Són les opcions de menú (menu items) que apareixen a l'Action Bar. Representen les accions més importants.
  • Overflow options: conté els ítems de menú secundaris. El boto de menú es considera deprecated.
Andrescorazon actionbar example.png

Hi a diferents tipus de menú:

Definir els menús XML

Per a tots els tipus de menú, la definició del menú es realitzar mitjançant un fitxer XML. Això permet evitar escriure en el codi gran parts dels menus. Altres avantatges són:

  • És més fàcil de visualitzar la estructura del menú.
  • Separation of concerns. Es separa el contingut del menú del codi.
  • Es poden crear configuracions de menú alternatives per a diferents versiones, mides de pantalla, etc...

S'utilitza el concepte inflar (inflate menu) per referir-se a l'acció de carregar un menú definit en un XML en un objecte de tipus menu dins la nostra Activitat o Fragment.

Els menús són per tant un tipus de Recurs Android que es defineixen a la carpeta:

res/menu/

Els elements XML vàlids són els següents:

  • <menu>: Defineix un Menu que no és res més que un contenidor d'ítems. Ha de ser l'element arrel de fitxer XML. Pot tenir com a fils un o més elements <item> i <group>.
  • <item>: Crea un MenuItem que representa un entrada simple de menú. Pot tenir submenus (altres elements <menu> anidats).
  • <group>: és un contenidor opcional i invisible d'elements <item>. Menu Groups

Vegem un exemple de fitxer menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/new_game"
          android:icon="@drawable/ic_new_game"
          android:title="@string/new_game"
          android:showAsAction="ifRoom"/>
    <item android:id="@+id/help"
          android:icon="@drawable/ic_help"
          android:title="@string/help" />
</menu>

L'element <item> suporta múltiples atributs, a l'exemple:

  • android:id: Un resource ID que identifica de forma unívoca el ítem de menú.
  • android:icon: una referència a un drawable que s'utilitzarà com a icona del ítem de menu.
  • android:title: una referència a un recurs de tipus string que s'utilitza com a títol.
  • android:showAsAction: Indica quan l'opció de menú ha d'aparèixer o no al Action Bar. Normalment s'utilitza android:showAsAction="ifRoom", és a dir es posa l'acció al Action Bar si hi ha espai.

Crear menús

Per tal d'utilitzar el menu en una activitat cal inflar (inflate) el recurs de menú amb:

MenuInflater.inflate()

Vegem alguns exemples:

Per a crear menús principals, el primer es tenir en compte la frontera que marca l'API 10 (Abans de 3.0).

Vegeu un exemple de menú per a una API 10 o inferior:

options_menu.png

És el típic menú de 6 items, si hi ha més de sis ítems es posen al submenu overflow de forma automàtica.

Amb Android 3.0 (API level 11) o superior s'utilitza l'Action Bar. http://developer.android.com/guide/topics/ui/actionbar.html

NOTA: Inclús per a aplicacions en versions inferiors a la 2.0 es pot simular el Action Bar. Vegeu http://developer.android.com/resources/samples/ActionBarCompat/index.html

Es pot utilitzar tant en objectes Activity (o subclasses Activity) com en Fragments.

Per especificar el menú d'una activitat cal sobrescriure el mètode:

onCreateOptionsMenu()

consulteu:

http://developer.android.com/reference/android/app/Activity.html#onCreateOptionsMenu%28android.view.Menu%29

Dins es fa normalment el inflate. Vegem un exemple:

 
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.game_menu, menu);
    return true;
}

de forma dinàmica es poden afegir ítems amb:

add()

O obtenir items amb:

findItem()

tots els detalls al API de MenuItem:

http://developer.android.com/reference/android/view/MenuItem.html

Action Bar

La barra d'accions (Action bar) és una característica d'Android que identifica l'aplicació i la situació de l'usuari alhora que proveeix d'accions d'usuari i modes de navegació. La barra es pot trobar a la majoria d'activitats a les que és important mostrar als usuaris les accions que es poden dur a terme i les opcions de navegació per l'aplicació.

La barra s'ha convertit en un paradigma de disseny que permet oferir als usuaris interfícies consistents entre diferents aplicacions. A més el sistema adapta de forma automàtica l'apariència de la barra per a diferents configuracions de pantalla.

Existeix una API especifica per a la barra d'accions que es va afegir a la versió 2.0 d'Android (API level 11).

Els objectius principals de la barra de navegació són:

  • Proveir d'un espai dedicat a la pantalla per tal d'identificar la marca de l'aplicació (aka brand) i la localització de l'usuari dins l'aplicació. això s'aconsegueix amb l'icona o logo de l'aplicació que apareix a l'esquerra del titol de l'activitat (tot això es però configurable)
  • Proveïx d'una navegació consistent i un refinament de la vista (View) entre diferents aplicacions. La barra d'acció porta un navegadors de pestanyes (tag navigation) incorporat que permet canviar entre els diferents fragments de l'aplicació de forma ràpida. També ofereix un llista desplegable ( drop-down list) que es pot utilitzar com una alternativa de navegació o per refinar la vista actual.
  • Fa que les accions principals (com cercar, crear, compartir, etc) tinguin un espai prominent i siguin accesibles per a l'usuari d'un forma previsible. Es pot proporcionar accés instantani a les accions d'usuari claus col·locant-les a la barra d'accions com a action items. Els Action items també poden proporcionar una action view, que mostra un widget encastat per tal de mostrar encara més possibles accions. Els items de menú que no són promocionats a la barra d'accions es troben disponibles al overflow menu, que es pot mostrar mitjançant el botó de Menú del dispositiu ( quan es troba disponible) o per un botó que apareix a la barra d'acció (quan el dispositiu no té botó de menú). Vegeu un exemple (per a més informació vegeu Menu guide):
actionbar.png

Manifest.xml

<manifest ... >
    <uses-sdk android:minSdkVersion="4"
              android:targetSdkVersion="11" />
    ...
</manifest>

Organització general

Andrescorazon action bar basics.png

Fragments

Un fragment representa un comportament o una porció de la interfície d'usuari d'una Activitat Android. Es poden combinar múltiples fragments en una sola activitat per tal de crear una UI (User Interface) multi-pane i reutilitzar els fragments en múltiples activitats. Es pot pensar en un fragment com una secció modular d'una activitat.

Els fragments són com activitats anidades dins d'altres Activitats i que tenen el seu propi layout i cicle de vida.

Són com subactivitats que es poden reutilitzar en altres activitats.

Un fragment sempre ha de estar dins d'una activitat i el cicle de vida de l'activitat està associat al cicle de vida de l'activitat, per exemple si es destrueix una activitat també es destrueixen tots els fragments que conté. Cal tenir en compte però que quan una activitat esta executant-se, cada fragment es pot manipular de forma independent, com per exemple es pot afegir o eliminar. A aquestes accions les anomenen fragment transactions, per exemple es poden afegir a una back stack.

Quan s'afegeix un fragment al layout d'una activitat, s'ha de fer dins d'un ViewGroup i el fragment defineix el seu propi layout. S'utilitza l'element XML:

<fragment>

Les qüestions que cal tenir en compte són:

  • Com mantenir l'estat dels fragments al afegir-los al back stack de l'activitat.
  • Com compartir esdeveniments amb l'activitat pare i altres fragments.
  • Com contribuir a l'Action Bar de l'activitat pare.

En resum, el que cal tenir en compte dels Fragments és:

  • Descomposen la funcionalitat i el UI de les aplicacions en mòduls
  • S'afegeixen a una pantalla per evitar la commutació entre activitats.
  • Tenen el seu propi cicle de vida i back stack
  • Requereixen l'API 11 o superior.
Andrescorazon activity fragment lifecycle.png

Comunicant-se amb altres Fragments i l'activitat pare

La filosofia dels fragment es que siguin reutilitzables. Per tal de poder reutilitzar els components d'interfície gràfica dels Fragments, cal crear cada fragment de forma que siguin components modulars complets i auto-continguts i que defineixen el seu propi Layout i comportament.

Un cop definits, els fragments es poden associar a una activitat i connectar-los entre si amb la lògica de l'aplicació per tal de crear una interfície gràfica composta per múltiples fragments.

Sovint és important que un Fragment es comuniqui amb un altre, per exemple per a intercanviar contingut basant-se en un esdeveniment d'usuari.

IMPORTANT: Totes les comunicacions entre fragments es realitzen a través de l'Activitat associada. Dos Fragment no s'han de comunicar mai directament.

Sovint el que es fa per tal que el Fragment es pugui comunicar amb la seva activitat pare, es definir una interfície a la classe Fragment i s'implementa a l'activitat pare.

NOTA: Vegeu l'exemple que genera automàticament Eclipse d'una aplicació multipane amb un fragment amb la llista d'articles i un fragment amb els detalls

És important capturar l'activitat pare al mètode OnAttach. Vegem un exemple:

public class HeadlinesFragment extends ListFragment {
    
    OnHeadlineSelectedListener mCallback;

    // Container Activity must implement this interface
    public interface OnHeadlineSelectedListener {
        public void onArticleSelected(int position);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        
        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            mCallback = (OnHeadlineSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }
    
    ...
}

Ara el fragment es pot comunicat amb l'activitat pare cridant al mètode:

onArticleSelected()

o altres mètodes de la interfície utilitzant l'atribut mCallback que conté l'activitat pare.

NOTA: Els noms dels mètodes són de lliure elecció

Cal tenir en compte que al programar l'activitat caldrà implementar la interfície i també omplir de codi el mètode per realitzar les accions que calguin.

Vegem un exemple de com comunicar-se amb l'activitat pare quan l'usuari selecciona un ítem de la llista:

    
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Send the event to the host activity
        mCallback.onArticleSelected(position);
    }

Com s'ha d'implementar la interfície:

 
public static class MainActivity extends Activity
        implements HeadlinesFragment.OnHeadlineSelectedListener{
    ...
    
    public void onArticleSelected(int position) {
        // The user selected the headline of an article from the HeadlinesFragment
        // Do something here to display that article
    }
}

Temes

Els temes són el mecanisme que Android proporciona per oferir a l'usuari un estil consistent a una aplicació o activitat. El estil especifica les propietats visuals dels elements que conformem la interfície d'usuari, com el color, l'alçada, el padding (embolcall) o la mida de la font. Per tal de promocionar una cohesió més gran entre aplicacions a la plataforma, Android proporciona 3 temes de sistema (des de Ice Cream Sandwich):

Holo Light
Holo Dark
Holo Light amb barres d'acció fosques

Cal escollir el tema del sistema que sigui més apropiat a les necessitats i els criteris estètics de disseny de la vostra aplicació. També però és possible aplicar el vostre propi estil.

Estils

Un estil és una col·lecció de propietats que defineixen l'apariència i la forma d'una Vista (View) o Finestra Android. Permet especificar propietats com:

height, padding, font color, font size, background color...

Els estils es defineixen amb un recurs XML que es troba separat del XML que especifica el Layout.

NOTA: Els estils a Android segueixen la mateixa filosofia que les CSS, per que permeten separar el disseny del contingut.

Un exemple, per al següent Layout:

 <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textColor="#00FF00"
    android:typeface="monospace"
    android:text="@string/hello" />

Amb estils es pot convertir en:

 <TextView 
    style="@style/CodeFont"
    android:text="@string/hello" />

En aquest cas tot lo referent a l'estil s'ha posat a un recurs Android anomenat CodeFont.

IMPORTANT: Un tema és un estil que s'aplica a tota una activitat o una aplicació en comptes de a un ítem individual com a l'exemple anterior.

Quan estil s'aplica com un tema, cada vista a la activitat o l'aplicació aplica les propietats d'estil que suporta segons l'estil indicat. Per exemple, es pot aplicar el estil CodeFont de l'exemple a una activitat i aleshores tot el text dins de l'activitat serà mono-espai i verd.

Definir un estil

Per definir/crear un estil, cal crear i guardar un fitxer XML al directory:

res/values

El nom del fitxer XML es arbitrari, però ha de tenir l'extensió .xml.

NOTA: Com podeu veure no hi ha una carpeta especifica per al recurs de tipus estil...

Vegem un exemple:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="CodeFont" parent="@android:style/TextAppearance.Medium">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textColor">#00FF00</item>
        <item name="android:typeface">monospace</item>
    </style>
</resources>

L'arrel XML sempre és resources. Per cada estil es defineix un element XML anomenat style.

Cada estil es convertit en un recurs Android en temps de compilació i es pot referenciar utilitzant el valor del atribut:

name

A l'exemple faríem referència utilitzant:

@style/CodeFont

Herència

L'herència s'utilitza per modificar i adaptar estils predefinits o aplicar petits canvis a un estil sense haver de tornar a definir-lo tot.

Un exemple de com com heretar l'apariència per defecte del text a Android i modificar-la:

    <style name="GreenText" parent="@android:style/TextAppearance">
        <item name="android:textColor">#00FF00</item>
    </style>

Si es vol heretar d'estils definits per un mateix i no pas pel sistema, NO s'ha d'utilitzar l'atribut parent.

 <style name="CodeFont.Red">
        <item name="android:textColor">#FF0000</item>
    </style>

Per utilitzar-lo es fa referència de la següent manera:

@style/CodeFont.Red.

Es pot fer tants cops com calgui:

 <style name="CodeFont.Red.Big">
        <item name="android:textSize">30sp</item>
    </style>

IMPORTANT: El punt només es pot utilitzar per a estils propis no per a estils de sistema. Aleshores cal utilitzar parent.

Style Properties

El suc en els estils està en conèixer les propietats d'estil que es poden aplicar. El millor lloc per conèixer les propietats d'estil que es poden aplicar és la referència de la classe de la vista que esteu utilitzant. Un exemple (textView):

http://developer.android.com/reference/android/widget/TextView.html#lattrs

Un exemple concret sense estils:

<EditText
    android:inputType="number"
    ... />

I amb estils:

 <style name="Numbers">
  <item name="android:inputType">number</item>
  ...
 </style>

I per aplicar-lo:

 <EditText
    style="@style/Numbers"
    ... />

Per una referència de tots els estils disponibles cal consultar R.attr:

http://developer.android.com/reference/android/R.attr.html

Cal tenir en compte però que no tots els objectes de tipus vista suporten tots els atributs. En tot cas s'intenta aplicar una propietat d'estil no aplicable aleshores s'ignora.

IMPORTANT: Algunes propietats d'estil només són aplicables als temes! Per exemple algunes propietats pode amagar el titol, la barra d'estat o canviar el fons de la finestra. Aquest tipus de propietats comencen per window a R.attr

Aplicar un estil a una vista

Vegem un exemple:

<TextView
    style="@style/CodeFont"
    android:text="@string/hello" />

NOTA: Fixeu-vos que l'atribut estil no utilitza el namespace Android, és a dir no utilitza el prefix android.

Aplicar un tema a una activitat o aplicació

Es fa indicant-ho al fitxer:

AndroidManifest.xml

Cal editar l'etiqueta:

<application>

Per incloure l'atribut:

android:theme

Amb el nom de l'estil. Per exemple:

<application android:theme="@style/CustomTheme">

Si desitgeu que un tema s'apliqui a una activitat concreta aleshores cal afegir l'atribut:

android:theme

A l'etiqueta:

<activity>

De la mateixa forma que hi ha molts alt altres recursos built-in, també tenim estils per defecte que es poden utilitzar per tal de no tenir que definir-los un mateix. un exemple:

<activity android:theme="@android:style/Theme.Dialog">

Per fer que una activitat sembli un diàleg.

O per exemple per indicar un fons transparent, es pot utilitzar el tema Translucent:

<activity android:theme="@android:style/Theme.Translucent">

Es pot utilitzar l'herència per a partir d'un estil concret aplicar les vostres pròpies especificitats.

<color name="custom_theme_color">#b0b0ff</color>
<style name="CustomTheme" parent="android:Theme.Light">
    <item name="android:windowBackground">@color/custom_theme_color</item>
    <item name="android:colorBackground">@color/custom_theme_color</item>
</style>

Aleshores per utilitzar-lo:

<activity android:theme="@style/CustomTheme">

També es posible seleccionar un tema o un altre segons la versió d'Android:

<style name="LightThemeSelector" parent="android:Theme.Light">
    ...
</style>

Es pot utilitzar:

res/values-v11

com a tipus de recurs alternatiu.

Exemples

Dashboard
styles.xml
<resources>
    <style name="ActionBarCompat">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">50dp</item>
        <item name="android:orientation">horizontal</item>
        <item name="android:background">@drawable/actionbar_background</item>
    </style>
 
    <style name="DashboardButton">
        <item name="android:layout_gravity">center_vertical</item>
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:gravity">center_horizontal</item>
        <item name="android:drawablePadding">2dp</item>
        <item name="android:textSize">16dp</item>
        <item name="android:textStyle">bold</item>
        <item name="android:textColor">#ff29549f</item>
        <item name="android:background">@null</item>
    </style>   
 
   <style name="FooterBar">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">40dp</item>
        <item name="android:orientation">horizontal</item>
        <item name="android:background">#dedede</item>
    </style>
</resources>
Source code
Android Styles (styles.xml) 
 https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/values/styles.xml
Android Themes (themes.xml)
 https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/res/res/values/themes.xml

Aquest fitxers permeten aprendre a través d'exemples. Per exemple aquí podeu trobar l'estil

<style name="Theme.Dialog">

System Bars

  1. Status Bar
  2. Navigation Bar
  3. Combined Bar
Andrescorazon system bars.png

Common App UI

  1. Main Action Bar
  2. View Control
  3. Content Area
  4. Split Action Bar
Andrescorazon common app ui.png

Input Controls

Input Events

Event Listeners

Llista d'esdeveniment típics:

  • onClick()
  • onLongClick()
  • onFocusChange()
  • onKey()
  • onTouch()
  • onCreateContextMenu()

Event Handlers

Gestiona l'esdeveniment.

Android UI Toolkit

El paquet Java:

android.view [1]

Proveeix les classes i interfícies Java encarregades de la interfície gràfica Android i és l'encarregada de gestionar el layout de la pantalla amb la que interactua l'usuari. En alguns casos també es fa referencia a aquest paquet, conjuntament amb:

android.widget [2]

com a Android UI toolkit.

Views (Vistes)

Tots els elements d'interfície a Android es construeixen utilitzant els objecte View o ViewGroup.

Android proporciona una col·lecció de Vistes i grups de vistes per defecte que permeten implementar els controls més habituals com Botons o camps de text (Text Fields)

ViewList

L'objecte android.widget.ListView [3] té la següent jerarquia:

java.lang.Object
  ↳ 	android.view.Viewandroid.view.ViewGroupandroid.widget.AdapterView<T extends android.widget.Adapter>
 	  	  	   ↳ 	android.widget.AbsListView
 	  	  	  	   ↳ 	android.widget.ListView

Per tant podem veure com es tracta d'un Widget Android, i també com és un conjunt de vistes o viewGroup i que a més és de tipus AdapterView, és a dir, una llista que treballa amb Adaptadors.

Un exemple de layout XML amb una ViewList:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ListView
        android:id="@+id/mylist"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout> 
Adapters

Els adaptadors s'utilitzen per proveir de dades al objecte ListView (o si utilitzem fragments els ListFragment). També defineixen com es mostra cada fila a la ListView.

Els adaptadors s'assignen a ListView o ListFragment utilitzant el mètode:

setAdapter [4]

Un adaptador és una classe filla de:

BaseAdapter [5]

Android us proporcionar una sèrie de adaptadors per defecte com:

Adaptadors a mida

Per controlar la forma en que l'adaptador assigna les dades d'origen als diferents elements de la UI a mida d'un afila cal crear un implementació pròpia de Adapter (subclase de BaseAdapter).

El mètode que cal sobreescriure és:

getView()

Que és el que utilitza la ListView o el ListFragment per obtenir la vista de la fila. El root del layout. Exemple:

package de.vogella.android.listactivity;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MySimpleArrayAdapter extends ArrayAdapter<String> {
  private final Context context;
  private final String[] values;

  public MySimpleArrayAdapter(Context context, String[] values) {
    super(context, R.layout.rowlayout, values);
    this.context = context;
    this.values = values;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) context
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.rowlayout, parent, false);
    TextView textView = (TextView) rowView.findViewById(R.id.label);
    ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);
    textView.setText(values[position]);
    // Change the icon for Windows and iPhone
    String s = values[position];
    if (s.startsWith("iPhone")) {
      imageView.setImageResource(R.drawable.no);
    } else {
      imageView.setImageResource(R.drawable.ok);
    }

    return rowView;
  }
} 
Exemples

Vegeu també

Enllaços externs